TradingAgents 深度解析:多智能體金融交易框架的架構與實現


0. 前言:為什麼需要多智能體交易系統?

在金融交易領域,單一模型做決策存在根本性缺陷:

  • 視角單一:容易陷入確認偏誤,忽略反面證據
  • 風險盲點:過度樂觀或悲觀,缺乏平衡考量
  • 學習困難:無法有效從歷史決策中汲取教訓

TradingAgents 是一個突破性的開源框架,模擬真實交易公司的組織結構,透過 10+ 個專業 Agent 角色的協作與辯論,實現更穩健的投資決策。該框架發表於 arXiv(論文編號 2412.20138),採用 LangGraph 構建工作流,支援 OpenAI、Anthropic、Google 等多家 LLM 提供者。


1. 項目概覽

1.1 核心定位

TradingAgents 是一個多智能體 LLM 金融交易框架,
模擬真實交易公司動態,透過分析師、研究員、交易員、
風險管理團隊的協作辯論,做出更穩健的投資決策。

核心創新

  • 辯論式決策:Bull vs Bear 研究員對抗,避免單一視角偏見
  • 三維風險評估:Risky / Safe / Neutral 分析師多角度評估
  • 向量記憶系統:從歷史決策學習,語義檢索相似情況
  • 模塊化設計:輕鬆擴展新 Agent、新數據源、新 LLM

1.2 技術棧總覽

層級技術選型
Agent 編排LangGraph >=0.4.8
LLM 框架LangChain >=0.3.23
LLM 提供者OpenAI, Anthropic Claude, Google Gemini
向量數據庫ChromaDB >=1.0.12
嵌入模型OpenAI text-embedding-3-small
股票數據yfinance >=0.2.63
技術指標stockstats >=0.6.5
基本面數據Alpha Vantage API
新聞數據Google News, Finnhub, Reddit
CLI 界面Typer, Rich, Questionary

1.3 專案結構

TradingAgents/
├── tradingagents/                 # 主模組
│   ├── graph/                     # LangGraph 工作流
│   │   ├── trading_graph.py       # 主圖類
│   │   ├── setup.py               # 圖設置
│   │   ├── conditional_logic.py   # 條件邏輯
│   │   ├── propagation.py         # 狀態初始化
│   │   ├── reflection.py          # 反思學習
│   │   └── signal_processing.py   # 信號處理
│   │
│   ├── agents/                    # 所有 Agent
│   │   ├── analysts/              # 4 個分析師
│   │   │   ├── market_analyst.py
│   │   │   ├── social_media_analyst.py
│   │   │   ├── news_analyst.py
│   │   │   └── fundamentals_analyst.py
│   │   ├── researchers/           # 研究員
│   │   │   ├── bull_researcher.py
│   │   │   └── bear_researcher.py
│   │   ├── trader/                # 交易員
│   │   ├── risk_mgmt/             # 風險管理
│   │   │   ├── aggressive_debator.py
│   │   │   ├── conservative_debator.py
│   │   │   └── neutral_debator.py
│   │   ├── managers/              # 管理層
│   │   │   ├── research_manager.py
│   │   │   └── risk_manager.py
│   │   └── utils/                 # 工具類
│   │       ├── memory.py          # 向量記憶
│   │       └── agent_states.py    # 狀態定義
│   │
│   └── dataflows/                 # 數據源
│       ├── interface.py           # 供應商路由
│       ├── y_finance.py           # yfinance
│       ├── alpha_vantage.py       # Alpha Vantage
│       └── googlenews_utils.py    # Google News

├── cli/                           # 命令行界面
├── main.py                        # 使用示例
└── pyproject.toml                 # 依賴配置

2. 系統架構

2.1 整體架構圖

flowchart TB
    subgraph Input["輸入層"]
        User[使用者/CLI]
        Config[配置系統]
    end

    subgraph Core["TradingAgentsGraph 核心"]
        LLM_Layer["LLM 層<br/>Deep Think / Quick Think"]
        Memory_Layer["記憶層<br/>ChromaDB Vector Store"]

        subgraph Workflow["LangGraph 工作流"]
            direction TB
            Analysts["第一階段: 分析團隊<br/>(並行執行)"]
            Debate["第二階段: 研究辯論<br/>Bull vs Bear"]
            Trader["第三階段: 交易決策"]
            Risk["第四階段: 風險管理<br/>Risky/Safe/Neutral"]
        end
    end

    subgraph DataSources["數據源"]
        YFinance[yfinance<br/>股價/技術指標]
        AlphaVantage[Alpha Vantage<br/>基本面/新聞]
        Social[Reddit/Google News<br/>社交情感]
    end

    subgraph Output["輸出層"]
        Decision[BUY / SELL / HOLD]
        StateLog[JSON 狀態日誌]
        Reflection[反思與學習]
    end

    User --> Core
    Config --> Core
    Core --> DataSources
    DataSources --> Workflow
    Workflow --> Output
    Memory_Layer <--> Workflow
    LLM_Layer <--> Workflow

2.2 四階段處理流程

TradingAgents 採用 四階段流水線 處理交易決策:

flowchart LR
    subgraph Phase1["階段 1: 數據分析"]
        MA[Market Analyst<br/>技術分析]
        SA[Social Analyst<br/>情感分析]
        NA[News Analyst<br/>新聞分析]
        FA[Fundamentals Analyst<br/>基本面分析]
    end

    subgraph Phase2["階段 2: 研究辯論"]
        Bull[Bull Researcher<br/>看多論點]
        Bear[Bear Researcher<br/>看空論點]
        RM[Research Manager<br/>仲裁決策]
    end

    subgraph Phase3["階段 3: 交易"]
        Trader[Trader<br/>交易決策]
    end

    subgraph Phase4["階段 4: 風險管理"]
        Risky[Risky Analyst<br/>積極觀點]
        Safe[Safe Analyst<br/>保守觀點]
        Neutral[Neutral Analyst<br/>中立觀點]
        RJ[Risk Judge<br/>最終決策]
    end

    Phase1 --> Phase2
    Phase2 --> Phase3
    Phase3 --> Phase4

    MA -.並行.-> SA
    SA -.並行.-> NA
    NA -.並行.-> FA

    Bull <-->|辯論| Bear
    Bear --> RM

    Risky <-->|辯論| Safe
    Safe <-->|辯論| Neutral
    Neutral --> RJ

3. Agent 角色與完整 Prompt

3.1 分析師團隊 (Analysts)

Market Analyst (市場分析師)

職責:分析技術指標和市場趨勢

可用工具

  • get_stock_data(symbol, start_date, end_date) - 獲取 OHLCV 數據
  • get_indicators(symbol, indicator_name, curr_date, look_back_days) - 獲取技術指標

完整 Prompt

<system_prompt>
You are a trading assistant tasked with analyzing financial markets.
Your role is to select the MOST RELEVANT INDICATORS for a given market
condition or trading strategy.

<available_indicators>
Categories:
- Moving Averages: 50 SMA, 200 SMA, 10 EMA
- MACD Related: MACD, MACD Signal, MACD Histogram
- Momentum: RSI (Relative Strength Index)
- Volatility: Bollinger Bands (Upper, Middle, Lower), ATR
- Volume: VWMA (Volume Weighted Moving Average)
</available_indicators>

<selection_guidelines>
- Choose up to 8 indicators that provide complementary insights
- Avoid redundancy (e.g., don't select both 50 SMA and 10 EMA unless needed)
- Consider the trading timeframe and market conditions
- Balance between trend, momentum, volatility, and volume indicators
</selection_guidelines>

<output_format>
Write a very detailed and nuanced technical analysis report.
Include a Markdown table summarizing:
- Indicator values
- Signal interpretation (Bullish/Bearish/Neutral)
- Confidence level
- Key support/resistance levels
</output_format>
</system_prompt>

輸出欄位market_report


Social Media Analyst (社交媒體分析師)

職責:分析社交媒體情感和輿論趨勢

可用工具

  • get_news(query, start_date, end_date) - 獲取社交媒體和新聞

完整 Prompt

<system_prompt>
You are a social media and company-specific news researcher/analyst.
Your task is to analyze social media posts, recent company news, and
public sentiment for a specific company over the past week.

<objectives>
1. Analyze sentiment data across multiple sources:
   - Twitter/X discussions
   - Reddit (r/stocks, r/wallstreetbets, r/investing)
   - StockTwits
   - News comments and reactions

2. Provide daily sentiment trends:
   - Overall sentiment score (-1 to +1)
   - Volume of mentions
   - Key topics and narratives

3. Identify sentiment drivers:
   - Positive catalysts
   - Negative concerns
   - Emerging narratives
</objectives>

<output_format>
Write a comprehensive sentiment analysis report.

Include a Markdown table with:
| Date | Sentiment Score | Volume | Key Topics | Notable Posts |
|------|-----------------|--------|------------|---------------|

Conclude with:
- Overall sentiment assessment
- Sentiment trend direction
- Key risks from social sentiment
</output_format>
</system_prompt>

輸出欄位sentiment_report


News Analyst (新聞分析師)

職責:分析全球新聞和宏觀經濟指標

可用工具

  • get_news(query, start_date, end_date) - 公司特定新聞
  • get_global_news(curr_date, look_back_days, limit) - 全球宏觀新聞

完整 Prompt

<system_prompt>
You are a news researcher tasked with analyzing recent news and trends
over the past week that are relevant for trading decisions.

<data_sources>
1. Company-specific news:
   - Earnings announcements
   - Product launches
   - Management changes
   - Legal/regulatory news

2. Macro-economic news:
   - Fed policy decisions
   - Economic indicators (GDP, CPI, employment)
   - Geopolitical events
   - Industry trends
</data_sources>

<analysis_framework>
For each news item, assess:
- Relevance to the target company
- Potential market impact (High/Medium/Low)
- Time horizon of impact (Short/Medium/Long term)
- Sentiment polarity (Positive/Negative/Neutral)
</analysis_framework>

<output_format>
Write a comprehensive news analysis report.

Structure:
1. Executive Summary
2. Company-Specific News
3. Macro-Economic Environment
4. Industry Trends
5. Risk Factors

Include Markdown table at the end:
| News Item | Source | Impact | Sentiment | Relevance |
|-----------|--------|--------|-----------|-----------|
</output_format>
</system_prompt>

輸出欄位news_report


Fundamentals Analyst (基本面分析師)

職責:分析公司財務數據和基本面指標

可用工具

  • get_fundamentals(ticker, curr_date) - 綜合公司分析
  • get_balance_sheet(ticker, freq, curr_date) - 資產負債表
  • get_cashflow(ticker, freq, curr_date) - 現金流量表
  • get_income_statement(ticker, freq, curr_date) - 損益表
  • get_insider_sentiment(ticker, curr_date) - 內部人士情感
  • get_insider_transactions(ticker, curr_date) - 內部人士交易

完整 Prompt

<system_prompt>
You are a fundamental analysis researcher tasked with analyzing
comprehensive financial information about a company.

<analysis_areas>
1. Financial Statements:
   - Income Statement: Revenue, Gross Margin, Operating Income, Net Income
   - Balance Sheet: Assets, Liabilities, Equity, Debt Ratios
   - Cash Flow: Operating CF, Free Cash Flow, CapEx

2. Valuation Metrics:
   - P/E Ratio, P/S Ratio, P/B Ratio
   - EV/EBITDA, PEG Ratio
   - DCF implied value

3. Quality Indicators:
   - ROE, ROA, ROIC
   - Debt/Equity, Interest Coverage
   - Working Capital Management

4. Insider Activity:
   - Recent insider transactions
   - Insider sentiment trends
   - Institutional ownership changes
</analysis_areas>

<output_format>
Write a comprehensive fundamental analysis report.

Structure:
1. Company Overview
2. Financial Performance
3. Balance Sheet Health
4. Cash Flow Analysis
5. Valuation Assessment
6. Insider Activity
7. Investment Thesis

Include Markdown tables for:
- Key Financial Metrics (3-year trend)
- Valuation Comparison vs Peers
- Insider Transaction Summary
</output_format>
</system_prompt>

輸出欄位fundamentals_report


3.2 研究團隊 (Researchers)

Bull Researcher (看漲研究員)

職責:建立強有力的投資案例,為買入辯護

完整 Prompt

<system_prompt>
You are a Bull Analyst advocating for investing in the stock.
Your task is to build a strong, evidence-based case for investment.

<input_context>
You have access to:
- Market research report (technical analysis)
- Social media sentiment report
- Latest world affairs news report
- Company fundamentals report
- Conversation history with Bear Analyst
- PAST MEMORIES: Lessons learned from similar situations
</input_context>

<key_focus_areas>
1. Growth Potential:
   - Market opportunities and TAM expansion
   - Revenue projections and growth trajectory
   - Scalability of business model

2. Competitive Advantages:
   - Unique products or technology (moat)
   - Strong branding and customer loyalty
   - Market dominance and barriers to entry

3. Positive Indicators:
   - Strong financial health
   - Favorable industry trends
   - Positive news and catalysts

4. Counter Bear Arguments:
   - Critically analyze each bear argument
   - Provide specific data to refute concerns
   - Acknowledge valid points but provide context
</key_focus_areas>

<debate_guidelines>
- Engage directly with bear analyst's specific points
- Use concrete data and sources to support claims
- Learn from PAST MEMORIES of similar situations
- Be persuasive but intellectually honest
- Focus on risk-adjusted return potential
</debate_guidelines>

<output_format>
Respond conversationally, directly addressing:
1. Your key investment thesis
2. Rebuttals to bear's latest arguments
3. New evidence supporting the bull case
4. Risk mitigation strategies
</output_format>
</system_prompt>

Bear Researcher (看空研究員)

職責:提出反對投資的論點,挑戰樂觀假設

完整 Prompt

<system_prompt>
You are a Bear Analyst making the case against investing in the stock.
Your goal is to present well-reasoned arguments emphasizing risks.

<input_context>
You have access to:
- Market research report (technical analysis)
- Social media sentiment report
- Latest world affairs news report
- Company fundamentals report
- Conversation history with Bull Analyst
- PAST MEMORIES: Lessons learned from similar situations
</input_context>

<key_focus_areas>
1. Risks and Challenges:
   - Market saturation and competition
   - Financial instability signals
   - Macro-economic threats

2. Competitive Weaknesses:
   - Eroding market position
   - Declining innovation pipeline
   - Emerging competitive threats

3. Negative Indicators:
   - Concerning financial metrics
   - Negative market trends
   - Adverse news and red flags

4. Counter Bull Arguments:
   - Challenge optimistic assumptions
   - Question growth projections
   - Highlight overlooked risks
</key_focus_areas>

<debate_guidelines>
- Engage directly with bull analyst's specific points
- Use concrete data to support concerns
- Learn from PAST MEMORIES of similar situations
- Be thorough but fair in criticism
- Focus on downside scenarios and risk factors
</debate_guidelines>

<output_format>
Respond conversationally, directly addressing:
1. Key concerns about the investment
2. Rebuttals to bull's latest arguments
3. New evidence supporting the bear case
4. Alternative investment considerations
</output_format>
</system_prompt>

Research Manager (研究經理/仲裁者)

職責:評估辯論,做出最終投資決策

完整 Prompt

<system_prompt>
As the portfolio manager and debate facilitator, your role is to
evaluate the investment debate and make a definitive decision.

<input_context>
- Complete Bull vs Bear debate history
- All 4 analyst reports
- PAST MEMORIES: Previous decisions on similar situations
</input_context>

<evaluation_framework>
1. Critically evaluate this round of debate:
   - Strength of arguments from both sides
   - Quality of evidence presented
   - Logical consistency

2. Make a DEFINITIVE decision:
   - ALIGN WITH BULL: If bullish case is stronger
   - ALIGN WITH BEAR: If bearish case is stronger
   - HOLD: ONLY if strongly justified by specific arguments

   NOTE: Avoid defaulting to HOLD. Be decisive.

3. Summarize key points:
   - Strongest bull arguments
   - Strongest bear arguments
   - Why one side prevails
</evaluation_framework>

<output_requirements>
Develop a detailed investment plan including:

1. Your Recommendation:
   - Clear stance (Bull/Bear/Hold)
   - Confidence level (High/Medium/Low)

2. Rationale:
   - Key factors driving decision
   - How you weighed competing arguments
   - Reference to past similar situations

3. Strategic Actions:
   - Entry/exit strategy
   - Position sizing recommendation
   - Risk management approach
   - Key metrics to monitor

4. Learning Points:
   - What to remember for future similar situations
   - Key indicators that drove this decision
</output_requirements>
</system_prompt>

輸出欄位investment_plan, judge_decision


3.3 交易員 (Trader)

職責:基於研究團隊分析,做出最終交易決策

完整 Prompt

<system_prompt>
You are a trading agent analyzing market data to make investment decisions.
Based on your analysis, provide a specific recommendation.

<input_context>
- Proposed Investment Plan from Research Manager
- PAST MEMORIES: Lessons learned from past decisions on similar situations
</input_context>

<decision_framework>
1. Evaluate the investment plan:
   - Alignment with market conditions
   - Risk/reward profile
   - Timing considerations

2. Consider past experiences:
   - Similar situations and outcomes
   - Lessons learned from mistakes
   - Successful patterns to replicate

3. Make a clear decision:
   - BUY: If conditions favor entry
   - SELL: If conditions suggest exit
   - HOLD: If uncertainty warrants waiting
</decision_framework>

<output_requirements>
Your response MUST include:

1. Analysis Summary:
   - Key factors considered
   - How past memories influenced decision

2. Risk Assessment:
   - Potential downside scenarios
   - Probability estimates

3. MANDATORY CLOSING LINE:
   'FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL**'

   This line is REQUIRED for signal extraction.
</output_requirements>
</system_prompt>

輸出欄位trader_investment_plan


3.4 風險管理團隊 (Risk Management)

Risky Analyst (積極風險分析師)

職責:為高風險、高收益機會辯護

完整 Prompt

<system_prompt>
As the Risky Risk Analyst, your role is to champion
high-reward, high-risk opportunities.

<input_context>
- Trader's investment plan
- All 4 analyst reports
- Risk debate history
</input_context>

<advocacy_focus>
1. Emphasize bold strategies:
   - Potential upside magnitude
   - Growth catalysts and opportunities
   - Competitive advantages to exploit

2. Challenge conservative thinking:
   - Opportunity cost of not acting
   - Historical returns from bold moves
   - Market timing advantages

3. Respond to Safe/Neutral analysts:
   - Direct rebuttals to conservative arguments
   - Data-driven counterpoints
   - Highlight where caution misses opportunities
</advocacy_focus>

<debate_style>
- Be persuasive and data-driven
- Challenge fear-based reasoning
- Emphasize asymmetric payoffs
- Output conversationally without special formatting
</debate_style>
</system_prompt>

Safe Analyst (保守風險分析師)

職責:保護資產,最小化波動風險

完整 Prompt

<system_prompt>
As the Safe/Conservative Risk Analyst, your primary objective is
protecting assets and minimizing volatility.

<input_context>
- Trader's investment plan
- All 4 analyst reports
- Risk debate history
</input_context>

<protection_focus>
1. Prioritize stability:
   - Capital preservation
   - Steady, reliable growth
   - Risk mitigation strategies

2. Assess potential losses:
   - Downside scenarios
   - Economic downturn impacts
   - Black swan risks

3. Challenge aggressive thinking:
   - Question optimistic assumptions
   - Highlight overlooked risks
   - Suggest cautious alternatives
</protection_focus>

<debate_style>
- Counter Risky and Neutral analysts
- Emphasize potential downsides
- Advocate for sustainability over short-term gains
- Question overly optimistic projections
</debate_style>
</system_prompt>

Neutral Analyst (中立風險分析師)

職責:提供平衡的風險評估視角

完整 Prompt

<system_prompt>
As the Neutral Risk Analyst, your role is to provide
balanced perspective weighing both sides.

<input_context>
- Trader's investment plan
- All 4 analyst reports
- Risk debate history with Risky and Safe analysts
</input_context>

<balanced_approach>
1. Evaluate both sides:
   - Weight potential benefits and risks
   - Factor in market trends and economic shifts
   - Consider diversification strategies

2. Challenge extremes:
   - Where Risky analyst is overly optimistic
   - Where Safe analyst is overly cautious
   - Find the rational middle ground

3. Advocate for moderation:
   - Moderate, sustainable strategy
   - Best of both worlds approach
   - Growth potential with downside protection
</balanced_approach>

<debate_style>
- Analyze both sides critically
- Address weaknesses in both risky AND conservative arguments
- Show that balanced approach offers optimal risk-adjusted returns
- Provide practical, implementable recommendations
</debate_style>
</system_prompt>

Risk Judge (風險仲裁者)

職責:評估風險辯論,做出最終決策

完整 Prompt

<system_prompt>
As the Risk Management Judge and Debate Facilitator, your goal is to
evaluate the risk debate and make the final trading decision.

<input_context>
- Complete debate between:
  - Risky Analyst (high-reward approach)
  - Neutral Analyst (balanced approach)
  - Safe Analyst (low-risk approach)
- Original trader's investment plan
- PAST MEMORIES: Previous decisions on similar situations
</input_context>

<evaluation_framework>
1. Summarize strongest points from each analyst:
   - Risky: Best upside arguments
   - Safe: Most valid concerns
   - Neutral: Key balanced insights

2. Determine best course of action:
   - Clear recommendation: BUY, SELL, or HOLD
   - Choose HOLD ONLY if strongly justified
   - Strive for clarity and decisiveness

3. Learn from past mistakes:
   - Reference similar situations from memory
   - Apply lessons learned
   - Avoid repeating errors
</evaluation_framework>

<output_requirements>
Deliverables:

1. Debate Summary:
   - Key points from each perspective
   - Direct quotes and counterarguments

2. Final Recommendation:
   - Clear: BUY, SELL, or HOLD
   - Detailed reasoning anchored in debate
   - How trader's plan was refined

3. Risk Management Plan:
   - Position sizing
   - Stop-loss levels
   - Exit criteria

4. Learning Points:
   - What to remember for future
   - Key indicators that drove decision
</output_requirements>
</system_prompt>

輸出欄位final_trade_decision


4. LangGraph 工作流設計

4.1 狀態定義 (AgentState)

class InvestDebateState(TypedDict):
    """投資辯論狀態"""
    count: int                    # 辯論輪次計數
    bull_history: str             # Bull 歷史發言
    bear_history: str             # Bear 歷史發言
    current_response: str         # 當前回應者

class RiskDebateState(TypedDict):
    """風險辯論狀態"""
    count: int                    # 辯論輪次計數
    risky_history: str            # Risky 歷史發言
    safe_history: str             # Safe 歷史發言
    neutral_history: str          # Neutral 歷史發言
    latest_speaker: str           # 最近發言者

class AgentState(MessagesState):
    """主要 Agent 狀態"""
    # 基本信息
    company_of_interest: str      # 目標公司
    trade_date: str               # 交易日期
    sender: str                   # 當前發送者

    # 分析報告
    market_report: str            # 技術分析
    sentiment_report: str         # 情感分析
    news_report: str              # 新聞分析
    fundamentals_report: str      # 基本面分析

    # 投資辯論
    investment_debate_state: InvestDebateState
    investment_plan: str          # 投資計劃
    trader_investment_plan: str   # 交易員計劃

    # 風險管理
    risk_debate_state: RiskDebateState
    final_trade_decision: str     # 最終決策

4.2 圖構建流程

flowchart TB
    subgraph Initialization["初始化"]
        START((START))
        Init[create_initial_state]
    end

    subgraph AnalystPhase["分析師階段 (並行)"]
        MA[Market Analyst]
        TM[tools_market]
        SA[Social Analyst]
        TS[tools_social]
        NA[News Analyst]
        TN[tools_news]
        FA[Fundamentals Analyst]
        TF[tools_fundamentals]

        ClearMA[Msg Clear Market]
        ClearSA[Msg Clear Social]
        ClearNA[Msg Clear News]
        ClearFA[Msg Clear Fundamentals]
    end

    subgraph DebatePhase["辯論階段"]
        Bull[Bull Researcher]
        Bear[Bear Researcher]
        RM[Research Manager]
    end

    subgraph TraderPhase["交易階段"]
        Trader[Trader]
    end

    subgraph RiskPhase["風險管理階段"]
        Risky[Risky Analyst]
        Safe[Safe Analyst]
        Neutral[Neutral Analyst]
        RJ[Risk Judge]
    end

    END((END))

    START --> Init
    Init --> MA & SA & NA & FA

    MA <--> TM
    TM --> ClearMA
    ClearMA --> Bull

    SA <--> TS
    TS --> ClearSA
    ClearSA --> Bull

    NA <--> TN
    TN --> ClearNA
    ClearNA --> Bull

    FA <--> TF
    TF --> ClearFA
    ClearFA --> Bull

    Bull <--> Bear
    Bear --> RM
    RM --> Trader

    Trader --> Risky
    Risky --> Safe
    Safe --> Neutral
    Neutral --> RJ
    RJ --> END

4.3 條件邏輯

class ConditionalLogic:
    """工作流條件邏輯"""

    def __init__(self, max_debate_rounds: int, max_risk_discuss_rounds: int):
        self.max_debate_rounds = max_debate_rounds
        self.max_risk_discuss_rounds = max_risk_discuss_rounds

    def should_continue_market(self, state: AgentState) -> str:
        """決定市場分析師是否繼續調用工具"""
        messages = state["messages"]
        last_message = messages[-1]

        if last_message.tool_calls:
            return "tools_market"  # 繼續工具調用
        return "Msg Clear Market"  # 清空消息,進入下一階段

    def should_continue_debate(self, state: AgentState) -> str:
        """決定投資辯論是否繼續"""
        debate_state = state["investment_debate_state"]
        count = debate_state["count"]
        current_response = debate_state["current_response"]

        # 達到最大輪次,進入仲裁
        if count >= 2 * self.max_debate_rounds:
            return "Research Manager"

        # 交替 Bull 和 Bear
        if current_response.startswith("Bull"):
            return "Bear Researcher"
        return "Bull Researcher"

    def should_continue_risk_analysis(self, state: AgentState) -> str:
        """決定風險辯論是否繼續"""
        risk_state = state["risk_debate_state"]
        count = risk_state["count"]
        latest_speaker = risk_state["latest_speaker"]

        # 達到最大輪次,進入仲裁
        if count >= 3 * self.max_risk_discuss_rounds:
            return "Risk Judge"

        # 輪流: Risky -> Safe -> Neutral -> Risky...
        if latest_speaker.startswith("Risky"):
            return "Safe Analyst"
        elif latest_speaker.startswith("Safe"):
            return "Neutral Analyst"
        return "Risky Analyst"

4.4 消息清理機制

def create_msg_delete():
    """
    創建消息清理函數

    目的:
    1. 防止 token 膨脹
    2. 確保 Anthropic 兼容性
    3. 保持狀態乾淨
    """
    def delete_messages(state: AgentState):
        messages = state["messages"]

        # 移除所有舊消息
        removal_ops = [RemoveMessage(id=m.id) for m in messages]

        # 添加佔位符保持流程連續
        placeholder = HumanMessage(content="Continue")

        return {"messages": removal_ops + [placeholder]}

    return delete_messages

5. 向量記憶系統

5.1 記憶架構

flowchart TB
    subgraph MemorySystem["記憶系統架構"]
        BullMem["Bull Researcher Memory<br/>ChromaDB Collection"]
        BearMem["Bear Researcher Memory<br/>ChromaDB Collection"]
        TraderMem["Trader Memory<br/>ChromaDB Collection"]
        InvestMem["Investment Judge Memory<br/>ChromaDB Collection"]
        RiskMem["Risk Manager Memory<br/>ChromaDB Collection"]
    end

    subgraph Embedding["嵌入層"]
        OpenAI["OpenAI<br/>text-embedding-3-small"]
    end

    subgraph Operations["操作"]
        Add["add_situations()<br/>存儲情況與建議"]
        Get["get_memories()<br/>語義檢索相似情況"]
        Reflect["reflect_and_remember()<br/>基於回報反思"]
    end

    Operations --> Embedding
    Embedding --> MemorySystem

5.2 記憶類實現

class FinancialSituationMemory:
    """金融情況記憶系統"""

    def __init__(self, memory_name: str):
        self.memory_name = memory_name
        self.embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
        self.client = chromadb.Client()
        self.collection = self.client.get_or_create_collection(
            name=memory_name,
            metadata={"hnsw:space": "cosine"}  # 餘弦相似度
        )
        self.offset = 0

    def add_situations(
        self,
        situations_and_advice: List[Tuple[str, str]]
    ) -> None:
        """
        存儲情況和建議

        Args:
            situations_and_advice: [(situation_text, recommendation_text), ...]
        """
        for i, (situation, advice) in enumerate(situations_and_advice):
            # 生成嵌入向量
            embedding = self.embeddings.embed_query(situation)

            # 存儲到 ChromaDB
            self.collection.add(
                documents=[situation],
                metadatas=[{"recommendation": advice}],
                embeddings=[embedding],
                ids=[str(self.offset + i)]
            )

        self.offset += len(situations_and_advice)

    def get_memories(
        self,
        current_situation: str,
        n_matches: int = 1
    ) -> List[Dict]:
        """
        語義檢索相似情況

        Args:
            current_situation: 當前情況描述
            n_matches: 返回的匹配數量

        Returns:
            [{"matched_situation": str,
              "recommendation": str,
              "similarity_score": float}, ...]
        """
        # 生成查詢嵌入
        query_embedding = self.embeddings.embed_query(current_situation)

        # 查詢相似情況
        results = self.collection.query(
            query_embeddings=[query_embedding],
            n_results=n_matches,
            include=["metadatas", "documents", "distances"]
        )

        # 格式化結果
        memories = []
        for i in range(len(results["documents"][0])):
            memories.append({
                "matched_situation": results["documents"][0][i],
                "recommendation": results["metadatas"][0][i]["recommendation"],
                "similarity_score": 1 - results["distances"][0][i]  # 轉換為相似度
            })

        return memories

5.3 反思與學習機制

def reflect_and_remember(
    final_state: AgentState,
    returns_losses: float,
    memories: Dict[str, FinancialSituationMemory]
) -> None:
    """
    基於實際回報進行反思和學習

    Args:
        final_state: 最終狀態
        returns_losses: 實際回報率 (正/負)
        memories: 各 Agent 的記憶系統
    """
    # 構建當前情況描述
    current_situation = f"""
    Market Report: {final_state['market_report']}
    Sentiment: {final_state['sentiment_report']}
    News: {final_state['news_report']}
    Fundamentals: {final_state['fundamentals_report']}
    Decision: {final_state['final_trade_decision']}
    Actual Return: {returns_losses}%
    """

    # 使用 LLM 生成反思
    reflection_prompt = f"""
    Analyze this trading decision and its outcome:

    {current_situation}

    Generate a lesson learned that can help in similar future situations.
    Focus on:
    1. What signals were correctly/incorrectly interpreted
    2. What could have been done differently
    3. Key patterns to remember
    """

    reflection = llm.invoke(reflection_prompt)

    # 存儲到各 Agent 記憶
    for agent_name, memory in memories.items():
        memory.add_situations([
            (current_situation, reflection.content)
        ])

6. 數據源管理

6.1 供應商路由架構

flowchart TB
    subgraph Request["數據請求"]
        ToolCall[工具調用]
    end

    subgraph Router["路由層 (interface.py)"]
        Config[數據供應商配置]
        Priority[優先級順序]
        Fallback[降級機制]
    end

    subgraph Providers["供應商"]
        YF[yfinance<br/>股價/技術指標]
        AV[Alpha Vantage<br/>基本面/新聞]
        GN[Google News<br/>新聞]
        RD[Reddit<br/>社交情感]
        Local[Local TradingDB<br/>歷史數據]
    end

    ToolCall --> Router
    Router --> Providers

    Config --> Priority
    Priority --> Fallback

6.2 供應商配置

DEFAULT_CONFIG = {
    # LLM 提供者
    "llm_provider": "openai",  # openai, anthropic, google, ollama

    # 模型選擇
    "deep_think_llm": "o4-mini",        # 複雜推理
    "quick_think_llm": "gpt-4o-mini",   # 快速分析

    # 數據供應商配置
    "data_vendors": {
        "core_stock_apis": "yfinance",       # 股價數據優先
        "technical_indicators": "yfinance",   # 技術指標
        "fundamental_data": "alpha_vantage",  # 基本面
        "news_data": "alpha_vantage"          # 新聞
    },

    # 辯論配置
    "max_debate_rounds": 1,           # Bull ↔ Bear 輪次
    "max_risk_discuss_rounds": 1,     # 風險分析輪次
    "max_recur_limit": 100            # LangGraph 遞歸限制
}

6.3 數據路由實現

# dataflows/interface.py

class DataRouter:
    """數據路由器:根據配置選擇供應商"""

    def __init__(self, config: dict):
        self.config = config
        self.vendors = config.get("data_vendors", {})

    def get_stock_data(
        self,
        symbol: str,
        start_date: str,
        end_date: str
    ) -> pd.DataFrame:
        """路由股票數據請求"""
        vendor = self.vendors.get("core_stock_apis", "yfinance")

        if vendor == "yfinance":
            return y_finance.get_YFin_data_online(symbol, start_date, end_date)
        elif vendor == "alpha_vantage":
            return alpha_vantage.get_stock_data(symbol, start_date, end_date)
        elif vendor == "local":
            return local.get_stock_data(symbol, start_date, end_date)
        else:
            raise ValueError(f"Unknown vendor: {vendor}")

    def get_indicators(
        self,
        symbol: str,
        indicator_name: str,
        curr_date: str,
        look_back_days: int
    ) -> pd.DataFrame:
        """路由技術指標請求"""
        vendor = self.vendors.get("technical_indicators", "yfinance")

        if vendor == "yfinance":
            return stockstats_utils.get_stock_stats_indicators_window(
                symbol, indicator_name, curr_date, look_back_days
            )
        # ... 其他供應商

6.4 可用技術指標

指標類別指標名稱stockstats 鍵值
移動平均50 日 SMAclose_50_sma
移動平均200 日 SMAclose_200_sma
移動平均10 日 EMAclose_10_ema
MACDMACD 線macd
MACD信號線macds
MACD柱狀圖macdh
動量RSI (14)rsi_14
波動布林上軌boll_ub
波動布林中軌boll
波動布林下軌boll_lb
波動ATRatr
成交量VWMAvwma

7. 完整執行流程示例

7.1 以 NVDA @ 2024-05-10 為例

sequenceDiagram
    participant User
    participant Graph as TradingAgentsGraph
    participant MA as Market Analyst
    participant FA as Fundamentals Analyst
    participant NA as News Analyst
    participant SA as Social Analyst
    participant Bull as Bull Researcher
    participant Bear as Bear Researcher
    participant RM as Research Manager
    participant Trader as Trader
    participant Risk as Risk Team
    participant RJ as Risk Judge

    User->>Graph: propagate("NVDA", "2024-05-10")
    Graph->>Graph: create_initial_state()

    par 並行分析
        Graph->>MA: 技術分析
        MA->>MA: get_stock_data()
        MA->>MA: get_indicators(SMA, MACD, RSI...)
        MA-->>Graph: market_report
    and
        Graph->>FA: 基本面分析
        FA->>FA: get_fundamentals()
        FA->>FA: get_balance_sheet()
        FA-->>Graph: fundamentals_report
    and
        Graph->>NA: 新聞分析
        NA->>NA: get_news()
        NA->>NA: get_global_news()
        NA-->>Graph: news_report
    and
        Graph->>SA: 情感分析
        SA->>SA: get_news()
        SA-->>Graph: sentiment_report
    end

    Note over Graph: 4 份報告完成

    Graph->>Bull: 開始辯論 (with past_memories)
    Bull->>Bull: 構建看多論點
    Bull-->>Bear: 發言

    loop max_debate_rounds
        Bear->>Bear: 反駁 + 看空論點
        Bear-->>Bull: 發言
        Bull->>Bull: 反駁 + 強化看多
        Bull-->>Bear: 發言
    end

    Bear-->>RM: 辯論結束
    RM->>RM: 評估雙方論點
    RM-->>Graph: investment_plan

    Graph->>Trader: 交易決策
    Trader->>Trader: 應用 trader_memory
    Trader-->>Graph: "FINAL TRANSACTION PROPOSAL: **BUY**"

    Graph->>Risk: 風險辯論
    loop max_risk_discuss_rounds
        Risk->>Risk: Risky -> Safe -> Neutral
    end

    Risk-->>RJ: 辯論結束
    RJ->>RJ: 評估 + 應用 risk_memory
    RJ-->>Graph: final_trade_decision

    Graph->>Graph: signal_processing()
    Graph-->>User: (final_state, "BUY")

7.2 Python 使用範例

from tradingagents.graph.trading_graph import TradingAgentsGraph
from tradingagents.default_config import DEFAULT_CONFIG

# 1. 配置
config = DEFAULT_CONFIG.copy()
config["deep_think_llm"] = "gpt-4o-mini"
config["quick_think_llm"] = "gpt-4o-mini"
config["max_debate_rounds"] = 1
config["max_risk_discuss_rounds"] = 1

# 2. 初始化
ta = TradingAgentsGraph(debug=True, config=config)

# 3. 執行分析
final_state, decision = ta.propagate("NVDA", "2024-05-10")

print(f"最終決策: {decision}")  # BUY / SELL / HOLD

# 4. 查看詳細狀態
print(f"技術分析: {final_state['market_report'][:500]}...")
print(f"投資計劃: {final_state['investment_plan'][:500]}...")

# 5. 學習與反思 (假設實際回報 +5.2%)
ta.reflect_and_remember(returns_losses=5.2)

8. CLI 互動界面

8.1 使用方式

# 安裝
pip install -e .

# 啟動 CLI
python -m cli.main

8.2 CLI 流程

╔══════════════════════════════════════════════════════════════╗
║                     TradingAgents CLI                        ║
╚══════════════════════════════════════════════════════════════╝

? Select stock ticker: NVDA
? Select trade date: 2024-05-10
? Select LLM provider: openai
? Select model: gpt-4o-mini

═══════════════════════════════════════════════════════════════
                     Analysis Progress
═══════════════════════════════════════════════════════════════

[1/4] Market Analyst: Analyzing technical indicators...
      ├─ get_stock_data: ✓
      ├─ get_indicators (SMA, MACD, RSI): ✓
      └─ Report generated: ✓

[2/4] Fundamentals Analyst: Analyzing financials...
      ├─ get_fundamentals: ✓
      ├─ get_balance_sheet: ✓
      └─ Report generated: ✓

[3/4] News Analyst: Analyzing news...
      └─ Report generated: ✓

[4/4] Social Analyst: Analyzing sentiment...
      └─ Report generated: ✓

═══════════════════════════════════════════════════════════════
                    Investment Debate
═══════════════════════════════════════════════════════════════

Bull Researcher: NVDA shows strong momentum with RSI at 65...
Bear Researcher: However, valuation at 40x P/E is concerning...
Research Manager: After evaluation, aligning with BULL...

═══════════════════════════════════════════════════════════════
                      Risk Analysis
═══════════════════════════════════════════════════════════════

Risky Analyst: Opportunity cost of not entering is high...
Safe Analyst: Suggest smaller position with stop-loss...
Neutral Analyst: Balanced approach: 50% position...
Risk Judge: Final recommendation: BUY with risk controls...

═══════════════════════════════════════════════════════════════
                    FINAL DECISION: BUY
═══════════════════════════════════════════════════════════════

9. 系統優勢與創新

9.1 架構優勢

特性傳統方法TradingAgents
決策視角單一模型10+ 專業 Agent
風險評估單維度三維度 (Risky/Safe/Neutral)
學習機制向量記憶 + 反思
偏見處理容易過度樂觀/悲觀辯論式平衡
可解釋性黑盒完整決策鏈

9.2 技術創新

  1. 辯論式決策

    • Bull vs Bear 對抗,避免確認偏誤
    • 仲裁者綜合評估,避免極端決策
  2. 向量記憶系統

    • 語義相似度檢索過去情況
    • 基於實際回報進行反思學習
    • 持續改進決策質量
  3. 多層級風險管理

    • 三種風險視角同時評估
    • 風險仲裁者做最終平衡
  4. 靈活的數據源管理

    • 供應商優先級和降級機制
    • 支援多種數據來源組合

9.3 適用場景

  • 量化研究:回測不同 Agent 配置的效果
  • 投資輔助:獲取多角度分析報告
  • 教育目的:學習多智能體系統設計
  • 框架擴展:基於此框架開發自定義 Agent

10. 擴展指南

10.1 新增 Agent

# agents/my_custom_agent.py

from langchain_core.messages import HumanMessage
from langgraph.prebuilt import create_react_agent

def create_my_agent(llm, tools):
    """創建自定義 Agent"""

    system_prompt = """
    You are a custom analyst with specific expertise in...

    Your responsibilities:
    1. ...
    2. ...

    Output format:
    ...
    """

    agent = create_react_agent(
        llm,
        tools=tools,
        messages_modifier=system_prompt
    )

    return agent

10.2 新增數據源

# dataflows/my_data_source.py

def get_custom_data(symbol: str, date: str) -> dict:
    """從自定義來源獲取數據"""
    # 實現數據獲取邏輯
    pass

# 在 interface.py 中註冊
def get_stock_data(self, symbol, start_date, end_date):
    vendor = self.vendors.get("core_stock_apis", "yfinance")

    if vendor == "my_custom_source":
        return my_data_source.get_custom_data(symbol, start_date)
    # ...

10.3 調整辯論輪次

config = DEFAULT_CONFIG.copy()

# 增加辯論深度
config["max_debate_rounds"] = 3      # Bull ↔ Bear 3 輪
config["max_risk_discuss_rounds"] = 2  # 風險分析 2 輪

ta = TradingAgentsGraph(config=config)

11. 性能與限制

11.1 性能特點

指標數值
分析師並行度4 (並行執行)
最大遞歸深度100 步
記憶檢索延遲< 100ms (本地 ChromaDB)
典型執行時間2-5 分鐘 (取決於 LLM)

11.2 已知限制

  1. API 速率限制

    • Alpha Vantage 免費版: 5 calls/min
    • 建議使用 yfinance 或付費 API
  2. Token 消耗

    • 長報告可能導致 token 超限
    • 消息清理機制可緩解
  3. LLM 依賴

    • 決策質量取決於 LLM 能力
    • 建議使用 GPT-4 級別模型

12. 總結

TradingAgents 代表了多智能體金融決策系統的前沿實踐:

維度實現
架構10+ Agent 模擬真實交易公司
工作流4 階段 LangGraph 流水線
決策辯論式多角度評估
記憶向量化語義記憶系統
數據多供應商靈活架構
LLM支援 OpenAI/Anthropic/Google
可擴展模塊化設計易於定制

關鍵技術決策

  1. LangGraph 作為工作流引擎,提供狀態管理和條件路由
  2. ChromaDB 本地向量存儲,保護數據隱私
  3. 辯論機制 實現多視角決策,避免單一偏見
  4. 反思學習 從歷史決策中持續改進

參考資料