TradingAgents/PLAN.md

15 KiB
Raw Blame History

Implementation Plan: Medium-Term Positioning Upgrade

Lead Architect Overview

Four objectives to upgrade TradingAgents for medium-term (13 month) positioning:

  1. Agentic Debate — Increase debate rounds to 23
  2. Fundamental Data — Extend look-back to 8 quarters with TTM trend computation
  3. Relative Performance — Sector & peer comparison tools
  4. Macro Regime Flag — Classify market as risk-on / risk-off / transition

Step 1: Agentic Debate — Increase Rounds (Architect + API Integrator)

Assigned to: API Integrator Agent Risk: LOW — Config-only change, conditional logic already supports arbitrary round counts.

Changes:

  • File: tradingagents/default_config.py

    • Change "max_debate_rounds": 1"max_debate_rounds": 2
    • Change "max_risk_discuss_rounds": 1"max_risk_discuss_rounds": 2
  • File: tradingagents/graph/trading_graph.py (line 146)

    • Pass config values to ConditionalLogic:
      self.conditional_logic = ConditionalLogic(
          max_debate_rounds=self.config.get("max_debate_rounds", 2),
          max_risk_discuss_rounds=self.config.get("max_risk_discuss_rounds", 2),
      )
      
    • NOTE: Currently ConditionalLogic() is called with no args, so it uses its own defaults of 1. The config values are never actually wired in. This is a bug fix.

Verification:

  • Investment debate: count threshold = 2 * 2 = 4 → Bull speaks 2×, Bear speaks 2× before judge
  • Risk debate: count threshold = 3 * 2 = 6 → Each of 3 analysts speaks 2× before judge
  • max_recur_limit of 100 is sufficient (was 100, worst case ~20 graph steps)

Step 2: Fundamental Data — 8-Quarter TTM Trend (API Integrator + Economist)

Assigned to: API Integrator (data layer) + Economist (TTM computation logic) Risk: MEDIUM — Requires new data tool + prompt update + TTM computation module.

2A: New TTM Computation Module (Economist Agent)

  • New file: tradingagents/dataflows/ttm_analysis.py
    • compute_ttm_metrics(income_df, balance_df, cashflow_df) -> dict
      • Sum last 4 quarters of income stmt for flow items (Revenue, Net Income, EBITDA, Operating Income, Gross Profit)
      • Use latest quarter for balance sheet (stock items: Total Assets, Total Debt, Equity)
      • Compute key ratios: Revenue Growth (QoQ and YoY), Margin trends (Gross, Operating, Net), ROE trend, Debt/Equity trend, FCF trend
    • format_ttm_report(metrics: dict, ticker: str) -> str
      • Markdown report with 8-quarter trend table + TTM summary + quarter-over-quarter trajectory

2B: New Tool — get_ttm_analysis (API Integrator Agent)

  • File: tradingagents/agents/utils/fundamental_data_tools.py

    • Add new @tool function get_ttm_analysis(ticker, curr_date) -> str
    • Internally calls existing vendor-routed get_income_statement, get_balance_sheet, get_cashflow with freq="quarterly"
    • Passes raw data to compute_ttm_metrics() and format_ttm_report()
  • File: tradingagents/agents/utils/agent_utils.py

    • Export get_ttm_analysis tool

2C: Update Fundamentals Analyst Prompt (Economist Agent)

  • File: tradingagents/agents/analysts/fundamentals_analyst.py

    • Add get_ttm_analysis to tools list
    • Update system prompt from "past week" to:

      "You are a researcher tasked with analyzing fundamental information covering the last 8 quarters (2 years) for a company. First call get_ttm_analysis to obtain a Trailing Twelve Months (TTM) trend report including revenue growth, margin trajectories, and key ratio trends. Then supplement with get_fundamentals for the latest snapshot. Write a comprehensive report covering multi-quarter trends, not just the most recent filing."

  • File: tradingagents/graph/trading_graph.py_create_tool_nodes()

    • Add get_ttm_analysis to the "fundamentals" ToolNode

2D: Data Layer — Ensure 8 Quarters Available

  • yfinance: ticker.quarterly_income_stmt returns up to 5 quarters. To get 8, we need to combine quarterly + annual or make 2 calls. Actually, yfinance returns the last 4-5 quarters by default. We'll need to fetch 2+ years of data.

    • Approach: Call ticker.quarterly_income_stmt which returns available quarters (typically 4-5). Also call ticker.income_stmt (annual) for older periods. Combine to reconstruct 8 quarters.
    • Alternative (preferred): yfinance ticker.get_income_stmt(freq="quarterly", as_dict=False) can return more data. Test this.
    • Fallback: Alpha Vantage INCOME_STATEMENT endpoint returns up to 20 quarterly reports — use this as the configured vendor for TTM.
  • File: tradingagents/default_config.py

    • Add to tool_vendors: "get_ttm_analysis": "alpha_vantage,yfinance" to prefer Alpha Vantage for richer quarterly history

Data Source Assessment:

Source Quarters Available Notes
yfinance quarterly_income_stmt 4-5 Limited but free
Alpha Vantage INCOME_STATEMENT Up to 20 quarterly Best option, needs API key
Alpha Vantage BALANCE_SHEET Up to 20 quarterly Same
Alpha Vantage CASH_FLOW Up to 20 quarterly Same

Step 3: Relative Performance — Sector & Peer Comparison (API Integrator + Economist)

Assigned to: API Integrator (tools) + Economist (comparison logic) Risk: MEDIUM — New tools leveraging existing scanner infrastructure.

3A: New Peer Comparison Module (Economist Agent)

  • New file: tradingagents/dataflows/peer_comparison.py
    • get_sector_peers(ticker) -> list[str]
      • Use yfinance Ticker.info["sector"] to identify sector
      • Return top 5-8 peers from same sector (use existing _SECTOR_TICKERS mapping from alpha_vantage_scanner.py, or yfinance Sector.top_companies)
    • compute_relative_performance(ticker, peers, period="6mo") -> str
      • Download price history for ticker + peers via yf.download()
      • Compute: 1-week, 1-month, 3-month, 6-month returns for each
      • Rank ticker among peers
      • Compute ticker's alpha vs sector ETF
      • Return markdown table with relative positioning

3B: New Tools — get_peer_comparison and get_sector_relative (API Integrator)

  • File: tradingagents/agents/utils/fundamental_data_tools.py

    • get_peer_comparison(ticker, curr_date) -> str — @tool
      • Calls get_sector_peers() and compute_relative_performance()
      • Returns ranked peer table with ticker highlighted
    • get_sector_relative(ticker, curr_date) -> str — @tool
      • Compares ticker vs its sector ETF over multiple time frames
      • Returns outperformance/underperformance metrics
  • File: tradingagents/agents/utils/agent_utils.py

    • Export both new tools

3C: Wire Into Fundamentals Analyst (API Integrator)

  • File: tradingagents/agents/analysts/fundamentals_analyst.py

    • Add get_peer_comparison and get_sector_relative to tools list
    • Update prompt to instruct: "Also analyze how the company performs relative to sector peers and its sector ETF benchmark over 1-week, 1-month, 3-month, and 6-month periods."
  • File: tradingagents/graph/trading_graph.py_create_tool_nodes()

    • Add both tools to "fundamentals" ToolNode

3D: Vendor Routing

  • These tools use yfinance directly (no Alpha Vantage endpoint for peer comparison)
  • No vendor routing needed — direct yfinance calls inside the module
  • Register in TOOLS_CATEGORIES under "fundamental_data" for consistency

Step 4: Macro Regime Flag (Economist Agent)

Assigned to: Economist Agent Risk: MEDIUM — New module + new state field + integration into Research Manager.

4A: Macro Regime Classifier Module (Economist)

  • New file: tradingagents/dataflows/macro_regime.py
    • classify_macro_regime(curr_date: str = None) -> dict
      • Returns: {"regime": "risk-on"|"risk-off"|"transition", "confidence": float, "signals": dict, "summary": str}
    • Signal sources (all via yfinance — free, no API key needed):
      1. VIX level: yf.Ticker("^VIX") → <16 risk-on, 16-25 transition, >25 risk-off
      2. VIX trend: 5-day vs 20-day SMA — rising = risk-off signal
      3. Credit spread proxy: yf.Ticker("HYG") vs yf.Ticker("LQD") — HYG/LQD ratio declining = risk-off
      4. Yield curve proxy: yf.Ticker("TLT") (20yr) vs yf.Ticker("SHY") (1-3yr) — TLT outperforming = risk-off (flight to safety)
      5. Market breadth: S&P 500 (^GSPC) above/below 200-SMA
      6. Sector rotation signal: Defensive sectors (XLU, XLP, XLV) outperforming cyclicals (XLY, XLK, XLI) = risk-off
    • Scoring: Each signal contributes -1 (risk-off), 0 (neutral), or +1 (risk-on). Aggregate:
      • Sum >= 3: "risk-on"
      • Sum <= -3: "risk-off"
      • Otherwise: "transition"
    • format_macro_report(regime_data: dict) -> str
      • Markdown report with signal breakdown, regime classification, and confidence level

4B: New Tool — get_macro_regime (API Integrator)

  • File: tradingagents/agents/utils/fundamental_data_tools.py (or new macro_tools.py)

    • get_macro_regime(curr_date) -> str — @tool
    • Calls classify_macro_regime() and format_macro_report()
  • File: tradingagents/agents/utils/agent_utils.py

    • Export get_macro_regime

4C: Add Macro Regime to Agent State

  • File: tradingagents/agents/utils/agent_states.py
    • Add to AgentState:
      macro_regime_report: Annotated[str, "Macro regime classification (risk-on/risk-off/transition)"]
      

4D: Wire Into Market Analyst (API Integrator)

  • File: tradingagents/agents/analysts/market_analyst.py

    • Add get_macro_regime to tools list
    • Update prompt to include: "Before analyzing individual stock technicals, call get_macro_regime to determine the current market environment (risk-on, risk-off, or transition). Interpret all subsequent technical signals through this macro lens."
    • Return macro_regime_report in output dict
  • File: tradingagents/graph/trading_graph.py_create_tool_nodes()

    • Add get_macro_regime to "market" ToolNode

4E: Feed Macro Regime Into Downstream Agents

  • File: tradingagents/agents/managers/research_manager.py

    • Add macro_regime_report to the curr_situation string that gets passed to the judge
    • Update prompt to reference macro regime in decision-making
  • File: tradingagents/agents/managers/risk_manager.py

    • Include macro regime context in risk assessment prompt
  • File: tradingagents/graph/trading_graph.py_log_state()

    • Add macro_regime_report to logged state

Step 5: Integration Tests (Tester Agent)

Assigned to: Tester Agent

5A: Test Debate Rounds — tests/test_debate_rounds.py

  • Test ConditionalLogic with max_debate_rounds=2:
    • Verify bull/bear alternate correctly for 4 turns
    • Verify routing to "Research Manager" after count >= 4
  • Test ConditionalLogic with max_risk_discuss_rounds=2:
    • Verify aggressive→conservative→neutral rotation for 6 turns
    • Verify routing to "Risk Judge" after count >= 6
  • Test config values are properly wired from TradingAgentsGraph config to ConditionalLogic

5B: Test TTM Analysis — tests/test_ttm_analysis.py

  • Unit test compute_ttm_metrics() with mock 8-quarter DataFrames
    • Verify TTM revenue = sum of last 4 quarters
    • Verify margin calculations
    • Verify QoQ and YoY growth rates
  • Unit test format_ttm_report() output contains expected sections
  • Integration test get_ttm_analysis tool with real ticker (mark @pytest.mark.integration)

5C: Test Peer Comparison — tests/test_peer_comparison.py

  • Unit test get_sector_peers() returns valid tickers for known sectors
  • Unit test compute_relative_performance() with mock price data
    • Verify correct return calculations
    • Verify ranking logic
  • Integration test with real ticker (mark @pytest.mark.integration)

5D: Test Macro Regime — tests/test_macro_regime.py

  • Unit test classify_macro_regime() with mocked yfinance data:
    • All risk-on signals → "risk-on"
    • All risk-off signals → "risk-off"
    • Mixed signals → "transition"
  • Unit test format_macro_report() output format
  • Unit test scoring edge cases (VIX at boundaries, missing data gracefully handled)
  • Integration test with real market data (mark @pytest.mark.integration)

5E: Test Config Wiring — tests/test_config_wiring.py

  • Test that TradingAgentsGraph(config={...}) properly passes debate rounds to ConditionalLogic
  • Test that new tools appear in the correct ToolNodes
  • Test that new state fields exist in AgentState

File Change Summary

File Action Objective
tradingagents/default_config.py EDIT #1 debate rounds, #2 tool vendor
tradingagents/graph/trading_graph.py EDIT #1 wire config, #2/#3/#4 add tools to ToolNodes, #4 log macro
tradingagents/graph/conditional_logic.py NO CHANGE Already supports arbitrary rounds
tradingagents/agents/utils/agent_states.py EDIT #4 add macro_regime_report
tradingagents/agents/analysts/fundamentals_analyst.py EDIT #2/#3 new tools + prompt
tradingagents/agents/analysts/market_analyst.py EDIT #4 macro regime tool + prompt
tradingagents/agents/managers/research_manager.py EDIT #4 include macro in decision
tradingagents/agents/managers/risk_manager.py EDIT #4 include macro in risk assessment
tradingagents/agents/utils/fundamental_data_tools.py EDIT #2/#3 new tool functions
tradingagents/agents/utils/agent_utils.py EDIT #2/#3/#4 export new tools
tradingagents/agents/__init__.py NO CHANGE Tools don't need agent-level export
tradingagents/dataflows/ttm_analysis.py NEW #2 TTM computation
tradingagents/dataflows/peer_comparison.py NEW #3 peer comparison logic
tradingagents/dataflows/macro_regime.py NEW #4 macro regime classifier
tradingagents/dataflows/interface.py EDIT #2/#3 register new tools in TOOLS_CATEGORIES
tests/test_debate_rounds.py NEW #1 tests
tests/test_ttm_analysis.py NEW #2 tests
tests/test_peer_comparison.py NEW #3 tests
tests/test_macro_regime.py NEW #4 tests
tests/test_config_wiring.py NEW Integration wiring tests

Execution Order

  1. Step 1 (Debate Rounds) — Independent, can start immediately
  2. Step 4A (Macro Regime Module) — Independent, can start in parallel
  3. Step 2A (TTM Module) — Independent, can start in parallel
  4. Step 3A (Peer Comparison Module) — Independent, can start in parallel
  5. Step 2B2D (TTM Integration) — Depends on 2A
  6. Step 3B3D (Peer Integration) — Depends on 3A
  7. Step 4B4E (Macro Integration) — Depends on 4A
  8. Step 5 (All Tests) — Depends on all above

Steps 1, 2A, 3A, 4A can all run in parallel.


Risk Mitigation

  • yfinance quarterly data limit: If yfinance returns <8 quarters, TTM module gracefully computes with available data and notes the gap. Alpha Vantage fallback provides full 20 quarters.
  • New state field (macro_regime_report): Default empty string. All existing agents that don't produce it will leave it empty — no reducer conflicts.
  • Rate limits: Macro regime and peer comparison both call yfinance which has no rate limit. Sector performance via Alpha Vantage is already rate-limited at 75/min.
  • Backward compatibility: All changes are additive. max_debate_rounds=1 still works. New tools are optional in prompts. macro_regime_report defaults to empty.