TradingAgents 架构与设计思想
> 版本基准:v0.3.0 · 基于源码与 README.md / CHANGELOG.md 整理
TradingAgents 是一个多智能体 LLM 金融分析框架,其设计目标不是「一键量化策略」,而是模拟真实交易机构的决策流程:分工、辩论、风控、终审,并在研究场景下提供可观测、可扩展、可复现(程度有限)的分析管线。
---
1. 项目定位
| 维度 | 定位 |
|---|---|
| 用途 | 学术研究、多 Agent 协作实验、LLM 金融推理脚手架 |
| 非目标 | 实盘交易、保证收益、确定性回测复现 |
| 核心隐喻 | 一家小型 buy-side 研究机构的日内/短期决策会议 |
| 技术栈 | Python 3.10+ · LangGraph · LangChain · Pydantic · Rich/Typer CLI |
---
2. 总体架构
系统采用分层 + 有向工作流架构,自上而下分为五层:
flowchart TB
subgraph Entry["入口层"]
CLI["cli/ — Typer + Rich 交互界面"]
API["main.py / TradingAgentsGraph — 编程接口"]
end
subgraph Orchestration["编排层 tradingagents/graph/"]
TG["TradingAgentsGraph"]
GS["GraphSetup — StateGraph 构建"]
CL["ConditionalLogic — 条件路由"]
PR["Propagator — 初始状态"]
CP["Checkpointer — 断点续跑"]
end
subgraph Agents["智能体层 tradingagents/agents/"]
AN["Analysts — 分析师(Tool Calling)"]
RS["Researchers — 多空辩论"]
MG["Managers — 研究经理 / 组合经理"]
TR["Trader — 交易提案"]
RK["Risk — 三方风控辩论"]
end
subgraph Data["数据层 tradingagents/dataflows/"]
IF["interface.route_to_vendor — 供应商路由"]
V1["yfinance / alpha_vantage"]
V2["fred / polymarket / reddit / stocktwits"]
end
subgraph LLM["模型层 tradingagents/llm_clients/"]
FC["factory.create_llm_client"]
CAP["capabilities — 模型能力表"]
end
subgraph Persist["持久化"]
MEM["TradingMemoryLog — 决策日志 + 反思"]
RPT["reporting.write_report_tree — Markdown 报告树"]
LOG["JSON 全状态日志"]
end
CLI --> TG
API --> TG
TG --> GS
GS --> Agents
Agents --> IF
Agents --> FC
TG --> MEM
TG --> RPT
TG --> CP
2.1 模块职责一览
| 目录 | 职责 |
|---|---|
tradingagents/graph/ | LangGraph 工作流定义、状态传播、条件分支、信号提取、断点恢复 |
tradingagents/agents/ | 各角色 Agent 的 Prompt、节点函数、结构化 Schema |
tradingagents/dataflows/ | 外部数据源适配、符号规范化、供应商路由与错误分类 |
tradingagents/llm_clients/ | 多 Provider LLM 客户端、模型目录、能力声明 |
tradingagents/default_config.py | 默认配置 + TRADINGAGENTS_* 环境变量覆盖 |
cli/ | 交互式配置、实时进度 UI、报告展示 |
tests/ | 单元/集成测试(供应商、配置、结构化输出、防前瞻等) |
3. 核心设计思想
3.1 组织隐喻驱动分解(Organizational Decomposition)
复杂交易决策被拆解为与真实机构对齐的角色,而非单一「超级 Prompt」:
1. 分析师团队 — 并行维度研究(技术面、情绪、新闻宏观、基本面) 2. 研究团队 — 多空研究员结构化辩论 → 研究经理裁决 3. 交易团队 — 将研究计划转为可执行交易提案 4. 风控团队 — 激进 / 保守 / 中性三方辩论 5. 组合经理 — 综合风控辩论与历史教训,输出最终五级评级
这种分解的设计收益:
- 上下文隔离:每位分析师只持有自己工具集相关的消息历史(分析完成后
Msg Clear清空 Tool 消息) - 可替换性:用户可在 CLI/API 中选择启用哪些分析师
- 可解释性:每阶段产出独立 Markdown 报告,便于审计与调试
3.2 双档 LLM 策略(Quick vs Deep)
# default_config.py 核心思想
"deep_think_llm": "gpt-5.5" # 复杂裁决:Research Manager、Portfolio Manager
"quick_think_llm": "gpt-5.4-mini" # 高频节点:分析师、辩论者、Trader
- Quick 模型:Tool Calling 循环、多轮辩论、反思 — 调用次数多,追求延迟与成本平衡
- Deep 模型:需要综合大量上下文的「法官」角色 — 调用次数少,追求推理深度
reasoning_effort、Google thinking_level、Anthropic effort)通过 _get_provider_kwargs() 统一注入,避免各 Agent 重复处理。3.3 LangGraph 作为编排内核
框架不手写 Agent 调度循环,而是将流程建模为 StateGraph(AgentState):
- 节点(Node):每个 Agent 是一个纯函数
(state) -> partial_state - 边(Edge):分析师顺序串联;辩论/风控为条件边(Conditional Edges)
- Tool 子图:分析师节点 ↔
ToolNode形成 ReAct 式循环,直到不再发起tool_calls
flowchart LR
START --> MA[Market Analyst]
MA -->|tools| TM[tools_market]
TM --> MA
MA -->|done| CM[Clear]
CM --> SA[Sentiment Analyst]
SA --> NA[News Analyst]
NA --> FA[Fundamentals Analyst]
FA --> BR[Bull Researcher]
BR <-->|debate| BEAR[Bear Researcher]
BR --> RM[Research Manager]
BEAR --> RM
RM --> TR[Trader]
TR --> AGG[Aggressive]
AGG <-->|risk debate| CON[Conservative]
CON <--> NEU[Neutral]
AGG --> PM[Portfolio Manager]
CON --> PM
NEU --> PM
PM --> END
ConditionalLogic 封装路由规则:
- 分析师:
last_message.tool_calls存在 → 继续 Tool 节点,否则 → Clear 并进入下一分析师 - 多空辩论:
count >= 2 * max_debate_rounds→ Research Manager - 风控辩论:
count >= 3 * max_risk_discuss_rounds→ Portfolio Manager
max_debate_rounds 与 max_risk_discuss_rounds 可通过配置或 TRADINGAGENTS_MAX_* 环境变量控制「研究深度」。3.4 状态即契约(State as Contract)
AgentState 继承 LangGraph 的 MessagesState,并扩展业务字段:
| 字段 | 含义 |
|---|---|
market_report / sentiment_report / news_report / fundamentals_report | 各分析师最终报告 |
investment_debate_state | 多空辩论历史、轮次计数、裁决 |
investment_plan | Research Manager 输出 |
trader_investment_plan | Trader 交易提案 |
risk_debate_state | 风控三方辩论状态 |
final_trade_decision | Portfolio Manager 最终决策(Markdown) |
instrument_context | 运行时解析的标的身份(防幻觉) |
past_context | 记忆日志注入的历史决策与反思 |
- CLI 可订阅
stream_mode="values"实时渲染进度 - Checkpoint 可序列化完整中间状态
write_report_tree()可离线生成报告目录树
3.5 数据访问:显式供应商链 + 类型化错误
数据层核心哲学:用户配置的供应商列表就是解析链,不会静默回退到未选择的供应商(避免跨源数据不一致)。
Agent Tool → route_to_vendor(method) → VENDOR_METHODS[method][vendor] → 具体实现
VendorError 层次结构(dataflows/errors.py):
VendorRateLimitError— 限流,尝试链中下一供应商VendorNotConfiguredError— 缺少 API Key,跳过NoMarketDataError— 无可用数据,返回NO_DATA_AVAILABLE哨兵字符串
- 核心(价格、基本面、新闻):失败时 loud fail 或明确哨兵,阻止 Agent 编造
- 可选(宏观 FRED、Polymarket):降级为
DATA_UNAVAILABLE哨兵,不中断整条管线
data_vendors— 按类别默认供应商(如"yfinance,alpha_vantage"有序回退)tool_vendors— 单工具级覆盖,优先级更高
agents/utils/*_tools.py)与 Vendor 实现(dataflows/y_finance.py 等)解耦:Agent 只认识抽象 Tool 名,路由在 Tool 内部完成。3.6 防幻觉三板斧(Grounding)
LLM 金融分析的最大风险是编造价格、错认标的、虚构指标验证。框架用三道确定性机制应对:
| 机制 | 实现 | 目的 |
|---|---|---|
| 标的身份解析 | resolve_instrument_identity() — yfinance 查公司名/行业/交易所,缓存于 instrument_context | 防止从 K 线形态「猜错公司」(#814) |
| 符号规范化 | symbol_utils.normalize_symbol() — 统一 Yahoo 可识别代码(如 XAUUSD → GC=F) | 身份、价格、收益计算指向同一标的 |
| 验证快照 | get_verified_market_snapshot() — 确定性计算 OHLCV + 指标 | Market Analyst 必须以之为 exact numeric 的 source of truth(#830) |
- 新闻/社交数据有前瞻窗口保护(测试覆盖
test_news_lookahead.py) - OHLCV 陈旧行拒绝(stale guard)
- 数据不可用时返回明确
NO_DATA_AVAILABLE,Prompt 要求 Agent 不得估算
3.7 结构化输出 + Markdown 渲染(Structured Output, Prose Artifact)
Research Manager、Trader、Portfolio Manager(及 Sentiment Analyst)使用 Pydantic Schema + with_structured_output:
1. 模型一次调用产出类型化对象(PortfolioDecision 等)
2. render_*() 函数转回 Markdown(Rating: Buy 等固定标题)
3. 下游(记忆日志、CLI、报告文件)无需感知结构化层变化
structured.py 统一模式:
- 创建时
bind_structured()— 不支持则整 Agent 降级为自由文本 - 调用时
invoke_structured_or_freetext()— 单次失败则 fallback 自由文本,不阻塞管线
capabilities.py 声明各模型 ID 的 structured output 方式(json_schema / function_calling / json_mode / none),避免客户端硬编码 if model == ...。3.8 记忆与反思闭环(Memory & Reflection Loop)
决策日志(TradingMemoryLog)采用追加式 Markdown,分两阶段:
Phase A — 写入(当次运行结束)
store_decision()追加[date | ticker | rating | pending]条目
_fetch_returns()计算 raw return 与 alpha(相对区域基准,如 SPY / ^N225)Reflector.reflect_on_final_decision()生成 2–4 句反思batch_update_with_outcomes()原子更新日志
get_past_context() 提取同 ticker 最近 N 条完整记录 + 跨 ticker 反思摘要 → 注入 Portfolio Manager Prompt。设计取舍:
- 反思延迟而非即时 — 需要持有期价格数据,避免同步 LLM 调用拖慢主流程
- 仅同 ticker 运行时解析 pending — 其他 ticker 的 pending 累积至该 ticker 再次分析
- 原子写入(temp + replace)— 崩溃不损坏日志
3.9 配置与环境变量优先
default_config.py 是单一配置源:
DEFAULT_CONFIG字典定义全部默认值_ENV_OVERRIDES映射TRADINGAGENTS_*→ 配置键,启动时_apply_env_overrides()合并- 类型强制(bool/int/float)失败即报错,避免
treu等拼写静默 misconfigure
tradingagents/__init__.py 在包导入时加载 .env,使 CLI 与 main.py 行为一致。dataflows/config.py 提供运行时可变配置的 deep-merge(set_config),供 TradingAgentsGraph.__init__ 注入。
3.10 可恢复性与可观测性
| 能力 | 机制 |
|---|---|
| 断点续跑 | LangGraph SqliteSaver,per-ticker DB,thread_id = hash(ticker:date) |
| 全状态日志 | results_dir/ |
| 报告树 | 1_analysts/ → 2_research/ → 3_trading/ → 4_risk/ → 5_portfolio/ + complete_report.md |
| CLI 实时 UI | Rich Live + MessageBuffer 追踪 Agent 状态与 Tool Call |
| Debug 模式 | graph.stream() 打印消息流 |
clear_checkpoint(),避免 stale state 污染下次运行。---
4. 智能体层详解
4.1 分析师(Analysts)
每位分析师遵循相同模式:
1. 从 state 读取 trade_date、instrument_context
2. 绑定专属 Tool 列表
3. ChatPromptTemplate + llm.bind_tools(tools) 进入 Tool Calling 循环
4. 完成后将报告写入对应 *_report 字段
| 分析师 | 工具集 | 报告字段 |
|---|---|---|
| Market | get_stock_data, get_indicators, get_verified_market_snapshot | market_report |
| Sentiment | get_news(含 StockTwits/Reddit 聚合逻辑) | sentiment_report |
| News | get_news, get_global_news, get_insider_transactions, get_macro_indicators, get_prediction_markets | news_report |
| Fundamentals | get_fundamentals, get_balance_sheet, get_cashflow, get_income_statement | fundamentals_report |
AnalystExecutionPlan(analyst_execution.py)将 wire key(如 "social")与用户可见名(Sentiment Analyst)解耦,保证配置向后兼容。
4.2 研究团队(Researchers + Research Manager)
- Bull / Bear Researcher:纯 LLM 辩论,无 Tool;读取四份分析师报告 + 辩论历史
- Research Manager:Deep LLM +
ResearchPlan结构化输出 → 五级PortfolioRating+ 战略行动
ConditionalLogic.should_continue_debate 控制,以 current_response 前缀(Bull / Bear)决定下一发言方。4.3 交易团队(Trader)
- 输入:Research Manager 的
investment_plan+ 分析师报告摘要 - 输出:
TraderProposal— 三级动作(Buy/Hold/Sell)+ 可选价位/仓位 - 保留
FINAL TRANSACTION PROPOSAL: BUY/HOLD/SELL行以兼容旧版 stop-signal 逻辑
4.4 风控与组合管理(Risk + Portfolio Manager)
- Aggressive / Conservative / Neutral:三角辩论,模拟 sell-side 与 buy-side 风险视角分歧
- Portfolio Manager:Deep LLM +
PortfolioDecision;注入past_context历史教训;输出五级评级
SignalProcessor.process_signal() → parse_rating() 从 Markdown 解析评级(无需二次 LLM 调用)。---
5. LLM 抽象层
5.1 工厂与懒加载
create_llm_client(provider, model, base_url, **kwargs) -> BaseLLMClient
- 原生 API:
anthropic,google,azure,bedrock— 独立 Client 类 - OpenAI 兼容:
openai,deepseek,ollama,openai_compatible等 — 统一走OpenAIClient+ Provider Registry
5.2 能力表驱动(Capabilities Table)
capabilities.get_capabilities(model_name) 返回:
preferred_structured_methodsupports_tool_choice/supports_json_schema等- Provider quirks:
requires_reasoning_content_roundtrip(DeepSeek)、requires_reasoning_split(MiniMax)
5.3 模型目录(Model Catalog)
llm_clients/model_catalog.py 为 CLI 提供 curated 模型列表;高频变化 Provider(OpenRouter 等)仅提供「Custom model ID」选项,避免 dropdown 过期。
---
6. 入口与集成方式
6.1 编程接口(推荐集成点)
from tradingagents.graph.trading_graph import TradingAgentsGraph
from tradingagents.default_config import DEFAULT_CONFIG
config = DEFAULT_CONFIG.copy()
config["llm_provider"] = "openai"
config["max_debate_rounds"] = 2
ta = TradingAgentsGraph(debug=True, config=config)
final_state, rating = ta.propagate("NVDA", "2026-01-15")
ta.save_reports(final_state, "NVDA") # 与 CLI 相同的报告树
6.2 CLI
tradingagents→cli.main:app(Typer)- 交互式选择:Ticker、日期、Provider、模型、分析师组合、研究深度、输出语言
StatsCallbackHandler统计 Token/Tool 调用--checkpoint/--clear-checkpoints控制断点行为
6.3 Docker
docker compose run tradingagents— 标准镜像--profile ollama— 本地模型 sidecar
7. 横切关注点
7.1 国际化
output_language配置非 English 时,各 Agent Prompt 追加「全文使用该语言输出」- 内部辩论仍默认英文 — README 明确:英文推理质量更稳定
7.2 安全
safe_ticker_component()— 防止 ticker 路径穿越 results/checkpoint 目录- API Key 通过环境变量 /
.env,不入库 .env.enterprise.example分离企业 Azure 配置
7.3 可复现性声明
框架诚实暴露 LLM 非确定性:
- 采样随机性 + 推理模型内部链式思考
- 实时新闻/社交源随时间变化
- 缓解:
temperature降低、非推理模型、固定分析日期 - 不保证回测结果与论文/演示一致 — 定位为 research scaffold
7.4 测试哲学
tests/ 覆盖:
- 供应商路由与错误分类
- 配置 precedence(CLI vs env)
- 结构化输出 fallback
- 前瞻偏差、符号规范化、checkpoint 恢复
- 各 Provider 集成 smoke
---
8. 扩展指南
8.1 新增分析师
1. 在 agents/analysts/ 实现 create_*_analyst(llm) 节点函数
2. 在 ANALYST_NODE_SPECS 注册 wire key 与 report 字段
3. 在 TradingAgentsGraph._create_tool_nodes() 添加 ToolNode
4. 在 ConditionalLogic 添加 should_continue_* 方法
5. 在 GraphSetup.setup_graph() 的 factory dict 注册
8.2 新增数据供应商
1. 在 dataflows/ 实现 vendor 函数
2. 注册到 VENDOR_METHODS 与 TOOLS_CATEGORIES
3. 抛出自定义 VendorError 子类 — 路由层自动处理
4. 在 default_config.data_vendors 暴露配置项
8.3 新增 LLM Provider
- 原生 API:新增
*_client.py+factory.py分支 - OpenAI 兼容:注册到 Provider Registry(
openai_client.py内) - 更新
model_catalog.py与capabilities.py
9. 设计原则总结
| 原则 | 体现 |
|---|---|
| 组织隐喻优先 | 角色拆分对应真实机构流程,而非技术便利 |
| 编排与智能分离 | LangGraph 管流程,Agent 管 Prompt+逻辑,Data 管 IO |
| Grounding over Generation | 身份解析、验证快照、NO_DATA 哨兵 |
| 显式优于隐式 | 供应商链、配置 precedence、错误类型 |
| 渐进增强 | 结构化输出、checkpoint、记忆反思均可 opt-in |
| 失败有语义 | 核心数据 loud fail;可选数据 graceful degrade |
| Markdown 为稳定接口 | 结构化层可换,报告格式保持兼容 |
| 研究诚实 | 文档与代码均声明非确定性与非投资建议 |
10. 关键文件索引
| 文件 | 说明 |
|---|---|
tradingagents/graph/trading_graph.py | 框架总入口,组件装配 |
tradingagents/graph/setup.py | StateGraph 拓扑定义 |
tradingagents/agents/utils/agent_states.py | 全局状态 Schema |
tradingagents/dataflows/interface.py | 数据供应商路由核心 |
tradingagents/default_config.py | 默认配置与环境变量 |
tradingagents/agents/schemas.py | 结构化输出 Pydantic 模型 |
tradingagents/agents/utils/memory.py | 决策日志与反思 |
tradingagents/llm_clients/factory.py | LLM 客户端工厂 |
cli/main.py | CLI 主程序 |
参考文献
- 论文:TradingAgents: Multi-Agents LLM Financial Trading Framework (arXiv:2412.20138)
- 上游仓库:TauricResearch/TradingAgents