Crypto-Analyst / main.py
menikev's picture
Update main.py
487144c verified
import asyncio
import time
import re
import json
from crewai import Crew, Process
from textwrap import dedent
from crypto_analysis_agents import CryptoAnalysisAgents
from crypto__analysis_tasks import CryptoAnalysisTasks
class CryptoCrew:
def __init__(self, crypto):
self.crypto = crypto
self.agents_instance = CryptoAnalysisAgents()
self.tasks_instance = CryptoAnalysisTasks()
def run(self):
return asyncio.run(self.run_async())
async def run_async(self):
start_time = time.time()
try:
# Create agents
market_analyst = self.agents_instance.market_analyst()
technical_analyst = self.agents_instance.technical_analyst()
advisor = self.agents_instance.crypto_advisor()
# Create tasks
tasks = [
self.tasks_instance.market_research(market_analyst, self.crypto),
self.tasks_instance.technical_analysis(technical_analyst, self.crypto),
self.tasks_instance.sentiment_analysis(advisor, self.crypto),
self.tasks_instance.recommend(advisor, self.crypto)
]
# Enhanced crew configuration
crew = Crew(
agents=[market_analyst, technical_analyst, advisor],
tasks=tasks,
verbose=True, # Enable for better debugging
process=Process.sequential,
max_iterations=8,
task_timeout=90
)
# Run crew
result = await asyncio.to_thread(crew.kickoff)
end_time = time.time()
return self.parse_result(result, end_time - start_time)
except Exception as e:
execution_time = time.time() - start_time
return {
"summary": f"Analysis failed: {str(e)}",
"market_data": self._get_fallback_market_data(),
"technical_data": self._get_fallback_technical_data(),
"sentiment": self._get_fallback_sentiment(),
"recommendation": {"action": "HOLD", "confidence": "Low", "reasoning": "Analysis incomplete"},
"execution_time": execution_time,
"risk_assessment": "High - Analysis failed"
}
def parse_result(self, result, execution_time):
"""Enhanced parsing to extract structured data from LLM responses"""
result_str = str(result)
# Extract market data
market_data = self._extract_market_data(result_str)
# Extract technical analysis
technical_data = self._extract_technical_data(result_str)
# Extract detailed sentiment analysis
sentiment_analysis = self._extract_sentiment_analysis(result_str)
# Extract recommendation
recommendation = self._extract_recommendation(result_str)
# Extract risk assessment
risk_assessment = self._extract_risk_assessment(result_str)
return {
"summary": self._clean_summary(result_str),
"market_data": market_data,
"technical_data": technical_data,
"sentiment": sentiment_analysis,
"recommendation": recommendation,
"risk_assessment": risk_assessment,
"execution_time": execution_time,
"last_updated": time.strftime("%Y-%m-%d %H:%M:%S UTC", time.gmtime())
}
def _extract_market_data(self, text):
"""Extract market metrics from analysis"""
market_data = {
"current_price": "N/A",
"market_cap": "N/A",
"price_change_24h": "N/A",
"price_change_7d": "N/A",
"volume_24h": "N/A",
"market_dominance": "N/A"
}
# Extract price
price_match = re.search(r'\$([0-9,]+\.?[0-9]*)', text)
if price_match:
market_data["current_price"] = f"${price_match.group(1)}"
# Extract market cap
mcap_match = re.search(r'market cap[:\s]+\$([0-9,]+\.?[0-9]*[BMK]?)', text, re.IGNORECASE)
if mcap_match:
market_data["market_cap"] = f"${mcap_match.group(1)}"
# Extract percentage changes
change_24h = re.search(r'24h?[:\s]*([+-]?[0-9]+\.?[0-9]*%)', text, re.IGNORECASE)
if change_24h:
market_data["price_change_24h"] = change_24h.group(1)
change_7d = re.search(r'7d?[:\s]*([+-]?[0-9]+\.?[0-9]*%)', text, re.IGNORECASE)
if change_7d:
market_data["price_change_7d"] = change_7d.group(1)
return market_data
def _extract_technical_data(self, text):
"""Extract technical indicators"""
technical_data = {
"rsi": "N/A",
"rsi_signal": "Neutral",
"moving_average_7d": "N/A",
"moving_average_50d": "N/A",
"trend": "Neutral",
"support_level": "N/A",
"resistance_level": "N/A"
}
# Extract RSI
rsi_match = re.search(r'RSI[:\s]*([0-9]+\.?[0-9]*)', text, re.IGNORECASE)
if rsi_match:
rsi_value = float(rsi_match.group(1))
technical_data["rsi"] = str(rsi_value)
if rsi_value > 70:
technical_data["rsi_signal"] = "Overbought"
elif rsi_value < 30:
technical_data["rsi_signal"] = "Oversold"
else:
technical_data["rsi_signal"] = "Neutral"
# Extract moving averages
ma_match = re.search(r'(?:7-day )?MA[:\s]*\$([0-9,]+\.?[0-9]*)', text, re.IGNORECASE)
if ma_match:
technical_data["moving_average_7d"] = f"${ma_match.group(1)}"
# Determine trend
if "bullish" in text.lower() or "uptrend" in text.lower():
technical_data["trend"] = "Bullish"
elif "bearish" in text.lower() or "downtrend" in text.lower():
technical_data["trend"] = "Bearish"
return technical_data
def _extract_sentiment_analysis(self, text):
"""Extract differentiated sentiment analysis"""
# Default to varied sentiments for demonstration
sentiment_data = {
"overall": "Neutral",
"social_media": "Neutral",
"news": "Neutral",
"community": "Neutral"
}
# Extract overall sentiment
if re.search(r'overall.*positive|positive.*overall', text, re.IGNORECASE):
sentiment_data["overall"] = "Positive"
elif re.search(r'overall.*negative|negative.*overall', text, re.IGNORECASE):
sentiment_data["overall"] = "Negative"
elif "bullish" in text.lower():
sentiment_data["overall"] = "Positive"
elif "bearish" in text.lower():
sentiment_data["overall"] = "Negative"
# Extract social media sentiment
if re.search(r'social.*positive|twitter.*positive|reddit.*positive', text, re.IGNORECASE):
sentiment_data["social_media"] = "Positive"
elif re.search(r'social.*negative|twitter.*negative|reddit.*negative', text, re.IGNORECASE):
sentiment_data["social_media"] = "Negative"
elif re.search(r'social.*bullish|community.*optimistic', text, re.IGNORECASE):
sentiment_data["social_media"] = "Positive"
# Extract news sentiment
if re.search(r'news.*positive|headlines.*positive|media.*positive', text, re.IGNORECASE):
sentiment_data["news"] = "Positive"
elif re.search(r'news.*negative|headlines.*negative|regulatory.*concern', text, re.IGNORECASE):
sentiment_data["news"] = "Negative"
# Extract community sentiment
if re.search(r'community.*positive|development.*active|adoption.*growing', text, re.IGNORECASE):
sentiment_data["community"] = "Positive"
elif re.search(r'community.*negative|development.*slow|adoption.*declining', text, re.IGNORECASE):
sentiment_data["community"] = "Negative"
elif re.search(r'institutional.*adoption|enterprise.*adoption', text, re.IGNORECASE):
sentiment_data["community"] = "Positive"
return sentiment_data
def _extract_recommendation(self, text):
"""Extract investment recommendation with reasoning"""
recommendation = {
"action": "HOLD",
"confidence": "Medium",
"reasoning": "Standard analysis completed",
"time_horizon": "Medium-term",
"risk_level": "Moderate"
}
# Extract recommendation
if re.search(r'recommendation[:\s]*BUY|BUY.*recommendation', text, re.IGNORECASE):
recommendation["action"] = "BUY"
elif re.search(r'recommendation[:\s]*SELL|SELL.*recommendation', text, re.IGNORECASE):
recommendation["action"] = "SELL"
# Extract confidence
if re.search(r'confidence[:\s]*high|high.*confidence', text, re.IGNORECASE):
recommendation["confidence"] = "High"
elif re.search(r'confidence[:\s]*low|low.*confidence', text, re.IGNORECASE):
recommendation["confidence"] = "Low"
# Extract reasoning
reason_match = re.search(r'(?:reason|reasoning)[:\s]*([^.]+)', text, re.IGNORECASE)
if reason_match:
recommendation["reasoning"] = reason_match.group(1).strip()
return recommendation
def _extract_risk_assessment(self, text):
"""Extract risk assessment"""
if re.search(r'high.*risk|risk.*high|volatile|risky', text, re.IGNORECASE):
return "High Risk"
elif re.search(r'low.*risk|risk.*low|stable|conservative', text, re.IGNORECASE):
return "Low Risk"
else:
return "Moderate Risk"
def _clean_summary(self, text):
"""Clean and format the summary"""
# Remove excess whitespace and format
summary = re.sub(r'\s+', ' ', text).strip()
# Truncate if too long
if len(summary) > 1000:
summary = summary[:1000] + "..."
return summary
def _get_fallback_market_data(self):
return {
"current_price": "N/A",
"market_cap": "N/A",
"price_change_24h": "N/A",
"price_change_7d": "N/A",
"volume_24h": "N/A",
"market_dominance": "N/A"
}
def _get_fallback_technical_data(self):
return {
"rsi": "N/A",
"rsi_signal": "Neutral",
"moving_average_7d": "N/A",
"moving_average_50d": "N/A",
"trend": "Neutral",
"support_level": "N/A",
"resistance_level": "N/A"
}
def _get_fallback_sentiment(self):
return {
"overall": "Neutral",
"social_media": "Neutral",
"news": "Neutral",
"community": "Neutral"
}
if __name__ == "__main__":
print("## Welcome to Enhanced Crypto Analysis Crew")
print('-------------------------------')
crypto = input(dedent("""
What is the cryptocurrency you want to analyze?
"""))
crypto_crew = CryptoCrew(crypto)
result = crypto_crew.run()
print("\n\n########################")
print("## Here is the Enhanced Report")
print("########################\n")
print(json.dumps(result, indent=2))