Spaces:
Sleeping
Sleeping
| TRADER_SYSTEM = """You are a professional crypto trading agent. Your job is to analyze market data and make a single trading decision. | |
| Rules: | |
| - You MUST respond with ONLY a JSON object, no markdown, no explanation outside the JSON. | |
| - action must be exactly one of: BUY, SELL, HOLD | |
| - size is the fraction of available capital to use (0.0 to 1.0) | |
| - confidence is your confidence level (0.0 to 1.0) | |
| - reason is a brief explanation (max 100 words) | |
| Response format (strict JSON): | |
| {"action": "BUY|SELL|HOLD", "size": 0.5, "confidence": 0.7, "reason": "..."}""" | |
| TECHNICAL_ANALYST_SYSTEM = """You are a technical analysis expert for crypto markets. Analyze the provided OHLCV data and technical indicators. | |
| Provide a structured technical analysis in JSON format: | |
| {"signal": "BULLISH|BEARISH|NEUTRAL", "strength": 0.0, "key_levels": {"support": 0.0, "resistance": 0.0}, "summary": "..."} | |
| Respond ONLY with the JSON object.""" | |
| NEWS_ANALYST_SYSTEM = """You are a crypto news sentiment analyst. Analyze the provided news headlines and assess market sentiment. | |
| Respond ONLY with a JSON object: | |
| {"sentiment": "POSITIVE|NEGATIVE|NEUTRAL", "score": 0.0, "key_themes": ["theme1"], "summary": "..."} | |
| score ranges from -1.0 (very negative) to 1.0 (very positive).""" | |
| SENTIMENT_ANALYST_SYSTEM = """You are a crypto market sentiment analyst specializing in on-chain data and market psychology. | |
| Analyze the provided Fear & Greed index, funding rates, and other sentiment indicators. | |
| Respond ONLY with a JSON object: | |
| {"sentiment": "EXTREME_FEAR|FEAR|NEUTRAL|GREED|EXTREME_GREED", "score": 0.0, "funding_bias": "LONG|SHORT|NEUTRAL", "summary": "..."}""" | |
| RESEARCHER_SYSTEM = """You are a senior crypto research analyst moderating a bull vs bear debate. You receive analyses from multiple analysts and must synthesize them into a final research note. | |
| Consider both bullish and bearish arguments objectively. Identify the strongest signals. | |
| Respond ONLY with a JSON object: | |
| {"verdict": "BULLISH|BEARISH|NEUTRAL", "conviction": 0.0, "bull_points": ["..."], "bear_points": ["..."], "synthesis": "..."} | |
| conviction ranges from 0.0 to 1.0.""" | |
| RISK_MANAGER_SYSTEM = """You are a crypto portfolio risk manager. You receive a trading recommendation and must validate it against risk constraints. | |
| Risk rules: | |
| - Max position size: 80% of capital | |
| - If drawdown > 20%, reduce position sizes by 50% | |
| - Do not override HOLD decisions with BUY unless conviction > 0.6 | |
| Respond ONLY with a JSON object: | |
| {"approved": true, "adjusted_action": "BUY|SELL|HOLD", "adjusted_size": 0.5, "risk_note": "..."}""" | |
| def build_trader_prompt_A(market_data: dict) -> str: | |
| """Benchmark A: single agent sees price + indicators directly.""" | |
| asset = market_data.get("asset", "BTC/USDT") | |
| price = market_data.get("current_price", 0) | |
| ohlcv = market_data.get("recent_ohlcv", []) | |
| indicators = market_data.get("indicators", {}) | |
| portfolio = market_data.get("portfolio", {}) | |
| ohlcv_text = "" | |
| if ohlcv: | |
| ohlcv_text = "\nRecent OHLCV (last 7 days):\n" | |
| for row in ohlcv[-7:]: | |
| ohlcv_text += f" {row['date']}: O={row['open']:.2f} H={row['high']:.2f} L={row['low']:.2f} C={row['close']:.2f} V={row['volume']:.0f}\n" | |
| ind_text = "" | |
| if indicators: | |
| ind_text = f""" | |
| Technical Indicators: | |
| RSI(14): {indicators.get('rsi', 'N/A')} | |
| MA(20): {indicators.get('ma20', 'N/A')} | |
| MA(50): {indicators.get('ma50', 'N/A')} | |
| MACD: {indicators.get('macd', 'N/A')} | |
| MACD Signal: {indicators.get('macd_signal', 'N/A')} | |
| MACD Hist: {indicators.get('macd_hist', 'N/A')} | |
| Bollinger Upper: {indicators.get('bb_upper', 'N/A')} | |
| Bollinger Lower: {indicators.get('bb_lower', 'N/A')}""" | |
| port_text = f""" | |
| Portfolio Status: | |
| Cash: ${portfolio.get('cash', 0):.2f} | |
| Position: {portfolio.get('position', 0):.6f} {asset.split('/')[0]} | |
| Total Value: ${portfolio.get('total_value', 0):.2f}""" | |
| return f"""Asset: {asset} | |
| Current Price: ${price:.2f} | |
| {ohlcv_text}{ind_text}{port_text} | |
| Based on this data, make your trading decision.""" | |
| def build_technical_analyst_prompt(market_data: dict) -> str: | |
| asset = market_data.get("asset", "BTC/USDT") | |
| price = market_data.get("current_price", 0) | |
| ohlcv = market_data.get("recent_ohlcv", []) | |
| indicators = market_data.get("indicators", {}) | |
| ohlcv_text = "" | |
| if ohlcv: | |
| ohlcv_text = "\nRecent OHLCV (last 14 days):\n" | |
| for row in ohlcv[-14:]: | |
| ohlcv_text += f" {row['date']}: O={row['open']:.2f} H={row['high']:.2f} L={row['low']:.2f} C={row['close']:.2f} V={row['volume']:.0f}\n" | |
| ind_text = f""" | |
| Indicators: | |
| RSI(14): {indicators.get('rsi', 'N/A')} | |
| MA(20): {indicators.get('ma20', 'N/A')} | MA(50): {indicators.get('ma50', 'N/A')} | |
| MACD: {indicators.get('macd', 'N/A')} | Signal: {indicators.get('macd_signal', 'N/A')} | |
| BB Upper: {indicators.get('bb_upper', 'N/A')} | BB Lower: {indicators.get('bb_lower', 'N/A')}""" | |
| return f"Asset: {asset}\nCurrent Price: ${price:.2f}\n{ohlcv_text}{ind_text}\n\nProvide your technical analysis." | |
| def build_news_analyst_prompt(news_items: list, asset: str) -> str: | |
| if not news_items: | |
| return f"No news available for {asset}. Respond with neutral sentiment." | |
| headlines = "\n".join(f"- {item.get('title', '')}" for item in news_items[:10]) | |
| return f"Asset: {asset}\n\nRecent news headlines:\n{headlines}\n\nAnalyze the sentiment." | |
| def build_sentiment_analyst_prompt(onchain_data: dict, asset: str) -> str: | |
| fng = onchain_data.get("fear_greed", {}) | |
| funding = onchain_data.get("funding_rate", None) | |
| return f"""Asset: {asset} | |
| Fear & Greed Index: {fng.get('value', 'N/A')} ({fng.get('label', 'N/A')}) | |
| Funding Rate: {f'{funding:.4f}%' if funding is not None else 'N/A'} | |
| Analyze the market sentiment.""" | |
| def build_researcher_prompt(tech_analysis: dict, news_analysis: dict, sentiment_analysis: dict, asset: str) -> str: | |
| return f"""Asset: {asset} | |
| Technical Analysis: | |
| {tech_analysis} | |
| News Analysis: | |
| {news_analysis} | |
| Sentiment Analysis: | |
| {sentiment_analysis} | |
| Synthesize these analyses into a final research verdict.""" | |
| def build_risk_manager_prompt(recommendation: dict, portfolio: dict) -> str: | |
| return f"""Trading Recommendation: | |
| {recommendation} | |
| Portfolio Status: | |
| Cash: ${portfolio.get('cash', 0):.2f} | |
| Position: {portfolio.get('position', 0):.6f} | |
| Total Value: ${portfolio.get('total_value', 0):.2f} | |
| Current Drawdown: {portfolio.get('drawdown', 0):.1%} | |
| Validate this recommendation against risk constraints.""" | |
| def build_trader_prompt_B(tech_analysis: dict, news_analysis: dict, portfolio: dict, asset: str, price: float) -> str: | |
| return f"""Asset: {asset} | |
| Current Price: ${price:.2f} | |
| Technical Analysis Summary: {tech_analysis.get('summary', 'N/A')} (Signal: {tech_analysis.get('signal', 'N/A')}) | |
| News Sentiment Summary: {news_analysis.get('summary', 'N/A')} (Sentiment: {news_analysis.get('sentiment', 'N/A')}, Score: {news_analysis.get('score', 0):.2f}) | |
| Portfolio: | |
| Cash: ${portfolio.get('cash', 0):.2f} | |
| Total Value: ${portfolio.get('total_value', 0):.2f} | |
| Make your trading decision based on the analyses above.""" | |
| def build_trader_prompt_C(research: dict, risk_decision: dict, portfolio: dict, asset: str, price: float) -> str: | |
| return f"""Asset: {asset} | |
| Current Price: ${price:.2f} | |
| Research Verdict: {research.get('verdict', 'N/A')} (Conviction: {research.get('conviction', 0):.2f}) | |
| Research Synthesis: {research.get('synthesis', 'N/A')} | |
| Risk Manager Assessment: {risk_decision.get('risk_note', 'N/A')} | |
| Risk-Adjusted Action: {risk_decision.get('adjusted_action', 'HOLD')} (size: {risk_decision.get('adjusted_size', 0)}) | |
| Portfolio: | |
| Cash: ${portfolio.get('cash', 0):.2f} | |
| Total Value: ${portfolio.get('total_value', 0):.2f} | |
| Make your final trading decision.""" | |