diff --git a/.gitignore b/.gitignore index 005cbd99..6f52df29 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Git worktrees .worktrees/ +orchestrator/profile_runs/ # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/orchestrator/profile_stage_chain.py b/orchestrator/profile_stage_chain.py index 68fad753..5022fc51 100644 --- a/orchestrator/profile_stage_chain.py +++ b/orchestrator/profile_stage_chain.py @@ -5,6 +5,8 @@ import json import signal import time from collections import defaultdict +from datetime import datetime, timezone +from pathlib import Path from tradingagents.graph.propagation import Propagator from tradingagents.graph.trading_graph import TradingAgentsGraph @@ -34,6 +36,7 @@ def build_parser() -> argparse.ArgumentParser: parser.add_argument("--analysis-prompt-style", default="compact") parser.add_argument("--selected-analysts", default="market") parser.add_argument("--overall-timeout", type=int, default=120) + parser.add_argument("--dump-dir", default="orchestrator/profile_runs") return parser @@ -65,6 +68,10 @@ def main() -> None: phase_totals = defaultdict(float) started_at = time.monotonic() last_at = started_at + dump_dir = Path(args.dump_dir) + dump_dir.mkdir(parents=True, exist_ok=True) + run_id = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ") + dump_path = dump_dir / f"{args.ticker.replace('/', '_')}_{args.date}_{run_id}.json" def alarm_handler(signum, frame): raise _ProfileTimeout(f"profiling timeout after {args.overall_timeout}s") @@ -97,6 +104,7 @@ def main() -> None: "analysis_prompt_style": args.analysis_prompt_style, "node_timings": node_timings, "phase_totals_seconds": {key: round(value, 3) for key, value in phase_totals.items()}, + "dump_path": str(dump_path), } except Exception as exc: payload = { @@ -108,10 +116,12 @@ def main() -> None: "error": str(exc), "node_timings": node_timings, "phase_totals_seconds": {key: round(value, 3) for key, value in phase_totals.items()}, + "dump_path": str(dump_path), } finally: signal.alarm(0) + dump_path.write_text(json.dumps(payload, ensure_ascii=False, indent=2)) print(json.dumps(payload, ensure_ascii=False, indent=2)) diff --git a/tradingagents/agents/managers/research_manager.py b/tradingagents/agents/managers/research_manager.py index bd610fd7..304d9e24 100644 --- a/tradingagents/agents/managers/research_manager.py +++ b/tradingagents/agents/managers/research_manager.py @@ -17,7 +17,10 @@ def create_research_manager(llm, memory): investment_debate_state = state["investment_debate_state"] curr_situation = f"{market_research_report}\n\n{sentiment_report}\n\n{news_report}\n\n{fundamentals_report}" - past_memories = memory.get_memories(curr_situation, n_matches=2) + past_memories = memory.get_memories( + curr_situation, + n_matches=1 if use_compact_analysis_prompt() else 2, + ) past_memory_str = "" for i, rec in enumerate(past_memories, 1): @@ -32,12 +35,14 @@ Return a concise response with: 3. Simple execution plan Past lessons: -{truncate_prompt_text(past_memory_str, 400)} +{truncate_prompt_text(past_memory_str, 180)} {instrument_context} Debate history: -{truncate_prompt_text(history, 1200)}""" +{truncate_prompt_text(history, 700)} + +Keep the full answer under 180 words.""" else: prompt = f"""As the portfolio manager and debate facilitator, your role is to critically evaluate this round of debate and make a definitive decision: align with the bear analyst, the bull analyst, or choose Hold only if it is strongly justified based on the arguments presented. diff --git a/tradingagents/agents/researchers/bear_researcher.py b/tradingagents/agents/researchers/bear_researcher.py index 815a50cf..ec418734 100644 --- a/tradingagents/agents/researchers/bear_researcher.py +++ b/tradingagents/agents/researchers/bear_researcher.py @@ -18,7 +18,10 @@ def create_bear_researcher(llm, memory): fundamentals_report = state["fundamentals_report"] curr_situation = f"{market_research_report}\n\n{sentiment_report}\n\n{news_report}\n\n{fundamentals_report}" - past_memories = memory.get_memories(curr_situation, n_matches=2) + past_memories = memory.get_memories( + curr_situation, + n_matches=1 if use_compact_analysis_prompt() else 2, + ) past_memory_str = "" for i, rec in enumerate(past_memories, 1): @@ -27,15 +30,15 @@ def create_bear_researcher(llm, memory): if use_compact_analysis_prompt(): prompt = f"""You are a Bear Analyst. Make the strongest concise short case against the stock. -Use only the highest-signal evidence from the reports below. Address the latest bull point directly. Keep the answer under 220 words and end with a clear stance. +Use only the highest-signal evidence from the reports below. Address the latest bull point directly. Keep the answer under 140 words and end with a clear stance. -Market report: {truncate_prompt_text(market_research_report, 800)} -Sentiment report: {truncate_prompt_text(sentiment_report, 500)} -News report: {truncate_prompt_text(news_report, 500)} -Fundamentals report: {truncate_prompt_text(fundamentals_report, 700)} -Debate history: {truncate_prompt_text(history, 600)} -Last bull argument: {truncate_prompt_text(current_response, 400)} -Past lessons: {truncate_prompt_text(past_memory_str, 400)} +Market: {truncate_prompt_text(market_research_report, 420)} +Sentiment: {truncate_prompt_text(sentiment_report, 220)} +News: {truncate_prompt_text(news_report, 220)} +Fundamentals: {truncate_prompt_text(fundamentals_report, 320)} +Debate history: {truncate_prompt_text(history, 260)} +Last bull argument: {truncate_prompt_text(current_response, 180)} +Past lessons: {truncate_prompt_text(past_memory_str, 180)} """ else: prompt = f"""You are a Bear Analyst making the case against investing in the stock. Your goal is to present a well-reasoned argument emphasizing risks, challenges, and negative indicators. Leverage the provided research and data to highlight potential downsides and counter bullish arguments effectively. diff --git a/tradingagents/agents/researchers/bull_researcher.py b/tradingagents/agents/researchers/bull_researcher.py index e93434d5..c4d1f125 100644 --- a/tradingagents/agents/researchers/bull_researcher.py +++ b/tradingagents/agents/researchers/bull_researcher.py @@ -18,7 +18,10 @@ def create_bull_researcher(llm, memory): fundamentals_report = state["fundamentals_report"] curr_situation = f"{market_research_report}\n\n{sentiment_report}\n\n{news_report}\n\n{fundamentals_report}" - past_memories = memory.get_memories(curr_situation, n_matches=2) + past_memories = memory.get_memories( + curr_situation, + n_matches=1 if use_compact_analysis_prompt() else 2, + ) past_memory_str = "" for i, rec in enumerate(past_memories, 1): @@ -27,15 +30,15 @@ def create_bull_researcher(llm, memory): if use_compact_analysis_prompt(): prompt = f"""You are a Bull Analyst. Make the strongest concise long case for the stock. -Use only the highest-signal evidence from the reports below. Address the latest bear point directly. Keep the answer under 220 words and end with a clear stance. +Use only the highest-signal evidence from the reports below. Address the latest bear point directly. Keep the answer under 140 words and end with a clear stance. -Market report: {truncate_prompt_text(market_research_report, 800)} -Sentiment report: {truncate_prompt_text(sentiment_report, 500)} -News report: {truncate_prompt_text(news_report, 500)} -Fundamentals report: {truncate_prompt_text(fundamentals_report, 700)} -Debate history: {truncate_prompt_text(history, 600)} -Last bear argument: {truncate_prompt_text(current_response, 400)} -Past lessons: {truncate_prompt_text(past_memory_str, 400)} +Market: {truncate_prompt_text(market_research_report, 420)} +Sentiment: {truncate_prompt_text(sentiment_report, 220)} +News: {truncate_prompt_text(news_report, 220)} +Fundamentals: {truncate_prompt_text(fundamentals_report, 320)} +Debate history: {truncate_prompt_text(history, 260)} +Last bear argument: {truncate_prompt_text(current_response, 180)} +Past lessons: {truncate_prompt_text(past_memory_str, 180)} """ else: prompt = f"""You are a Bull Analyst advocating for investing in the stock. Your task is to build a strong, evidence-based case emphasizing growth potential, competitive advantages, and positive market indicators. Leverage the provided research and data to address concerns and counter bearish arguments effectively.