TradingAgents源码深度解析:多智能体LLM框架如何重构金融交易决策
2026/9/17 9:46:09 网站建设 项目流程

最近我把 TradingAgents 的源码完整过了一遍,前前后后花了一个多星期。这个项目在 GitHub 上的定位很有意思:它不是又一个“用大模型预测涨跌”的玩具,而是一个把完整交易团队的工作流搬进多智能体 LLM 框架里的开源实现。你输入一只股票代码,它会自动完成研究、多空辩论、交易决策、风险控制这四个环节,最后输出一份带理由、带仓位、带止损建议的投资分析报告。如果你一直在追 LLM Agent 工程化、多智能体协作、或者大模型在金融场景的落地,这个项目非常值得静下心来读一读。本篇文章我就把自己读代码过程中梳理出来的架构、关键机制、实操方式以及踩过的坑,一次性讲清楚。

先说一个背景判断:金融交易决策天然就是多角色的协作过程。研究员负责收集信息,分析师负责从不同立场解读,交易员负责做执行决策,风控负责踩刹车。这种金字塔式的信息流转和制衡机制,恰恰是多智能体系统最擅长模拟的场景。TradingAgents 把这一套流程用代码固化下来,让独立的 Agent 各自扮演一个角色,再通过消息传递和有限轮数的辩论完成决策闭环。理解它,顺便也能理解多智能体框架在面对复杂任务时,到底比单次调用大模型强在哪里、又有哪些绕不开的坑。

1. 为什么要读 TradingAgents:它到底解决什么问题

1.1 金融决策场景里的“单一大模型”为什么不够用

先看一个很现实的痛点。如果你直接把“帮我分析一下英伟达这只股票,给出交易建议”丢给 GPT-4 这类大模型,它通常会给你一段非常流畅、逻辑自洽但无法真正指导操作的文字。它会说“英伟达在 AI 浪潮中处于核心地位,估值偏高但增长强劲”,然后给出一个模棱两可的结论。问题在于,真实的交易决策不是写作文,它需要明确几件事:基于哪个时间周期的数据、多头逻辑和空头逻辑各自的权重、当前价位的止损空间、仓位占总投资的比例、以及如果判断错了最大损失是多少。

单次调用大模型很难同时处理好这层约束。它没有外部数据,只能依赖训练时的记忆,所以公司新闻、技术指标这类时效性数据基本是幻觉重灾区。它也没有对抗性验证机制,一个模型既当运动员又当裁判,很容易陷入确认偏误,顺着自己提出的观点一路论证下去,完全没人反驳。而 TradingAgents 的做法是用多智能体结构把任务拆开:研究员拿到外部工具的数据,分析师分别从多空两个方向撰写报告,交易员综合辩论结果做决策,风控再从风险角度做最终制衡。本质上,它模拟的是一套“团队做决策”的流程,用角色分工来对冲单模型的不确定性和偏见。

1.2 它读起来又是一份多智能体框架的“样板工程”

第二个让我觉得值得认真读的原因是,TradingAgents 的代码结构非常清晰,几乎可以作为多智能体 LLM 应用的入门范本。它没有把几十个 Agent 的逻辑全都写在一个巨型 Python 文件里,而是按照角色划分模块:research、analyst、trader、risk_management,每个模块只负责自己的那部分职责。消息流转由 AutoGen 的 GroupChat 机制管理,Agent 之间通过自然语言文本传递分析结果,不需要额外设计复杂的协议格式。

这种分层方式对读代码的人非常友好。你需要理解的核心概念其实就两个:一是提示词工程,每个角色的大段 System Prompt 决定了它的立场和输出格式;二是会话编排,GroupChat 里的消息如何在各个 Agent 之间轮转。把这两条线捋清楚,整个项目就基本拿下了。我一直觉得,多智能体最难的部分从来不是单点能力的调用,而是任务如何拆分、消息如何流转、以及最终如何收敛。TradingAgents 恰好把这三个问题都给出了一个可以运行、可以复现的答案。

读完之后,这套流程还可以迁移到很多非金融场景,比如市场调研、竞品分析、甚至企业内部的多部门评审。你要在意的不是“它能不能赚钱”,而是“一套复杂的协作任务是怎么被设计成多个 LLM Agent 协作流程的”,这套方法论本身就是最大的收获。

2. 整体架构拆解:源码里的角色分工与消息流转

2.1 代码仓库结构一览

我在阅读时基于当前仓库的 master 分支,整体目录结构大致如下:

TradingAgents/ ├── tradingagents/ │ ├── agents/ │ │ ├── research.py # 研究员 Agent │ │ ├── analyst.py # 多头/空头分析师 Agent │ │ ├── trader.py # 交易员 Agent │ │ ├── risk_management.py # 风控 Agent │ │ ├── investment_committee.py # 投资委员会/辩论管理 │ │ └── __init__.py │ ├── graph/ │ │ ├── workflow.py # 主流程编排 │ │ └── debate.py # 多空辩论逻辑 │ ├── prompts/ │ │ ├── research.py │ │ ├── analyst.py │ │ ├── trader.py │ │ └── risk_management.py │ ├── tools/ │ │ ├── data_tools.py # 数据获取工具封装 │ │ └── __init__.py │ ├── llm.py # LLM 统一封装 │ └── utils.py ├── run.py # 命令行入口 ├── streamlit_app.py # Web 演示入口 └── requirements.txt

第一眼看上去可能觉得文件不多,但每一个 agent 文件里都封装了好几个角色类,所以实际代码量并不小。我最推荐从run.py开始读,它是整个项目的主入口,能帮你快速建立数据流的整体概念。顺着入口进到workflow.py,你就能看到一次完整交易分析是怎么被一步步编排出来的。

2.2 六个核心智能体:从研究员到风控

TradingAgents 里的核心角色大概有六个,我第一次读的时候被这些名字绕了一下,后来对着源码理清了它们的关系。这里用一张表来概括:

角色类名核心职责输入来源输出去向
基础研究员FundamentalResearchAgent获取基本面数据并输出研究报告股票代码、财务数据多头/空头分析师
技术研究员TechnicalResearchAgent分析价格、均线、RSI 等指标股票代码、行情数据多头/空头分析师
新闻情绪研究员NewsSentimentAgent抓取新闻并做情绪分析新闻源、舆情数据多头/空头分析师
多头分析师BullAnalystAgent从乐观视角构建投资论点研究数据投资委员会/辩论
空头分析师BearAnalystAgent从悲观视角提出风险与反驳研究数据投资委员会/辩论
交易员TradingAgent给出买卖方向、仓位、止损止盈辩论结论、研究报告风控经理
风控经理RiskManagementAgent审核风险,给出最终决策建议交易员方案、风险指标最终报告

严格来说它把“研究员”拆分成了三类,每类负责不同的数据源,这样每个 Agent 的 Promot 可以写得足够聚焦。我在读research.py的时候发现,这些研究员 Agent 并不直接调用 API 拉数据,而是通过tools/data_tools.py里的封装函数来获取数据。这种做法的好处很明显:Agent 不关心数据从哪来,只关心拿到结构化数据后怎么分析和输出,数据源的替换与扩展被隔离在工具层。

2.3 消息流转与状态管理:从一个 Agent 到另一个 Agent

理解了这个项目之后,你会发现所谓的“多智能体协作”在代码层面其实是“消息的接力”。Agent A 的输出作为自然语言消息被追加到 GroupChat 的会话历史里,Agent B 读取这段历史,结合自己的 System Prompt 和任务要求,再生成自己的输出。这里没有复杂的内部状态同步,所有共享信息都以文本形式存在于对话上下文中。

我当时在workflow.py里看到的流程大致是这样的:首先创建一组 Agent,每个 Agent 传入对应角色的 Prompt 和 LLM 配置;然后创建一个 GroupChat,把这些 Agent 全部注册进去;接着由 GroupChatManager 控制发言顺序,在辩论阶段让多头、空头交替发言,直到满足终止条件;最后交易员读取整个辩论记录做决策,风控再对决策做最后审核。

这种“无中心状态、纯文本传递”的消息流转模式看起来很简单,但也很容易出现问题:如果历史消息太长,上下文窗口很快会被占满;如果某个 Agent 输出格式不规范,下游 Agent 解析就会出错。关于这些坑,我在第 5 章会专门展开讲。

3. 核心机制深度解析:辩论、决策与提示词工程

3.1 牛熊辩论机制是怎么实现的

多空辩论是整个项目里最有意思的模块,也最能体现多智能体设计的精髓。传统的单个 LLM 做分析,最大的问题就是缺少对抗性校验。多头观点被提出之后,没有角色主动站出来挑毛病;就算模型自己列风险,那些风险往往也只是点缀,不会真正影响结论。TradingAgents 的解决办法是让多头分析师和空头分析师各自成为一个独立的 Agent,带着完全相反的立场参与辩论。

从代码上看,这个辩论过程依赖 AutoGen 的 GroupChat。多头和空头分析师在同一个组里,系统会让它们交替发言,每个 Agent 都能看到对方此前的论点。关键在于“有限轮数”:辩论不是无限进行下去的,workflow.py里通常会设置max_round或者让 Manager 根据轮数决定什么时候终止。我在读的时候把这个逻辑梳理成下面这段伪代码,更直白一些:

def run_debate(chat_manager, bull_agent, bear_agent, research_summary, max_round=3): # 把研究报告作为公共上下文,注入对话 chat_manager.init_chat( message=f"基于以下研究数据进行辩论:\n{research_summary}" ) # 依次让多空双方发言,共进行 max_round 轮 for round_id in range(max_round): bull_message = bull_agent.generate_reply(chat_manager.history) chat_manager.append_message("bull", bull_message) bear_message = bear_agent.generate_reply(chat_manager.history) chat_manager.append_message("bear", bear_message) return chat_manager.history

我读代码时特别注意了一个细节:辩论不是随意的“聊天”,每个分析师都被明确要求输出结构化的投资论点,包括关键数据、逻辑推演和风险提示。这样做的好处是,交易员在最后做决策时不需要从大段口语化文本里手动提取信息,而是可以直接读取已经结构化的论据。对抗性辩论最大的价值,不是让“看多”和“看空”两方强行分出胜负,而是让决策者在有限时间内看到同一个事实的两种解读,从而对不确定性有更充分的认知。

3.2 交易决策与风险控制的代码逻辑

辩论结束之后,流程进入了决策阶段。交易员 Agent 读取完整的辩论记录和研究报告,输出一个包含交易动作(买入、卖出、持有)、仓位比例、止损价格、目标价格和决策理由的报告。我在trader.py里看到它的 Prompt 明确要求“不要给出模糊的建议”,必须给具体数值和可执行方案。这个设计我非常认同,因为模糊的 LLM 输出在真实场景里几乎不可用,反而容易让人误以为它真的给出了参考。

风险控制模块是我认为这个项目最值得借鉴的地方。risk_management.py里的风控 Agent 不是简单地对交易员的结论说“好”或“不好”,而是要基于风险指标做出独立判断。它会检查交易员建议的仓位是否过大、止损设置是否合理、潜在最大回撤是否在可接受范围内。如果风控认为风险过高,它有权给出“缩小仓位”或“放弃交易”的建议,并且最终输出中会明确出现风险等级与风险提示。

这种“决策与风控分离”的设计,在真实金融机构里是标配,但在个人层面的 LLM Agent 项目里很少见。大多数类似的框架都只做到“生成一个答案”,不会去设计一个角色来专门否决这个答案。TradingAgents 把这种制衡思想带到了多智能体系统中,等于给决策流程加了一道纠错机制。

3.3 Prompt 设计:为什么每个角色的 System Prompt 这么长

如果你第一次打开prompts/目录,大概率会被每个 Prompt 的长度惊到。一个分析师角色的 System Prompt 动辄几百上千字,这在普通 LLM 应用里几乎不可想象。我一开始觉得这是不是过度设计,读完之后才意识到,长 Prompt 在这个项目里不是堆砌废话,而是为了让 Agent 的行为边界足够清晰。

比如说研究员角色的 Prompt 里会明确列出它需要输出的字段:公司简介、财务指标分析、行业竞争格局、风险因素等。分析师角色的 Prompt 里会明确交代立场:“你是坚定的多头,你的任务是从所有数据中找到支持上涨的逻辑,但你的论证必须基于引用数据,不能凭空捏造。”这种带立场的角色设定,正是多智能体系统与单次 Prompt 输出最核心的区别。

此外,Prompt 里还有大量的“行为约束”,比如要求 Agent 在证据不足时承认不确定性、不要虚构不存在的新闻、输出格式必须符合 JSON 或 Markdown 结构等。这些约束看似琐碎,实际上是在用提示词工程补 LLM 天生的短板。对普通读者来说,这也是很好的学习材料:想改造成自己的多智能体应用,第一件事不是调模型,而是设计一套能定向约束模型行为的 Prompt。

4. 实操过程:把 TradingAgents 跑起来

4.1 环境准备与依赖安装

纸上谈兵没意思,自己跑一遍才是真读懂。我在本地把整个项目跑通大概用了不到二十分钟,大部分时间花在安装依赖上。环境要求不复杂,Python 3.10 以上即可,不需要 GPU,因为所有推理都是通过调用远程大模型 API 实现的,本地只负责逻辑编排。

依赖安装很简单,进入项目目录后执行:

pip install -r requirements.txt

如果你平时用 Conda,建议先建一个独立环境,避免和已有项目产生依赖冲突。我当时就因为pydantic版本问题踩了一次小坑,后面第 5 章会提到。

4.2 关键配置项:LLM 接口、数据源与运行参数

这个项目默认通过 OpenAI 兼容接口调用大模型,你只需要设置几个环境变量。我实际用的配置是这样的:

export OPENAI_API_KEY="你的APIKey" export OPENAI_API_BASE="https://api.openai.com/v1" export LLM_MODEL="gpt-4o"

官方的 API Key 需要自己准备。如果你接的是本地部署模型或第三方兼容服务,只需要把OPENAI_API_BASE换成对应的接口地址,再把LLM_MODEL改成实际模型名即可。模型选择上,我强烈建议先用便宜的小模型完成流程调试,比如gpt-4o-mini,等确认链路没问题后再切换成强大的大模型跑正式分析,不然一次完整分析下来 API 费用会非常可观。

除了模型配置,run.py里还有一些运行参数可以调整,比如你要分析的股票代码(目前主要支持美股 ticker)、初始资金规模、辩论轮数上限等。辩论轮数是一个需要权衡的参数:轮数太少,多空论点不够充分;轮数太多,API 成本成倍增加,还有可能让上下文窗口被填满。我第一次跑用的默认轮数感觉效果适中,后续如果想深入分析再手动调高。

4.3 运行一次完整交易分析的流程与输出解读

在命令行执行:

python run.py

程序会先让研究员 Agent 抓取目标股票的基本面数据、技术指标和新闻情绪,这个过程能看到多个 Agent 按顺序执行的过程日志。紧接着会进入多空辩论阶段,多头和空头分析师来回输出论点,投资委员会做阶段性总结。最后交易员给出决策,风控审核流程会给出最终的交易建议报告,包括方向、仓位、止损价和风险提示。

我第一次拿到输出的时候,整体感受是“结构很完整,但不要直接拿它做交易决策”。报告读起来逻辑自洽,数据和观点都有来源支撑,但它本质上仍然是对历史数据的综合分析,不具备对未来走势的稳定预测能力。那也是这个项目在 README 里反复强调的:这是一个研究性质的框架,不构成投资建议。它真正的价值在于展示了一套可落地的多智能体决策流程,而不是暗示你可以靠它稳定盈利。

5. 常见问题与排查实录

5.1 问题速查表

我在跑代码的过程中踩了不少坑,有些是配置问题,有些是框架机制本身的设计约束。这里整理成一张表,给准备自己动手尝试的读者做个参考:

问题现象排查思路解决办法
API 调用失败日志中反复出现连接错误或鉴权失败检查环境变量是否设置正确,尤其注意 API Key 前后是否有空格重新 export 环境变量后重启进程
上下文长度溢出辩论到一半报错,提示超过模型 token 上限说明历史消息太长,或者模型上下文窗口较小调低max_round,或切换支持更长上下文的模型
输出格式不规范交易员或风控拿到的是不可解析的文本个别模型对长 Prompt 的服从性较弱,输出结构跑偏切换更强的模型,或在解析代码里加入容错重试逻辑
股票数据获取失败研究员输出为空,或提示找不到数据目标股票代码不在数据源支持范围内,部分数据源对非美股支持较弱改用数据源支持的美股代码测试,或自备数据接口
依赖安装冲突安装或导入时报pydantic版本不兼容不同版本的 autogen 和 langchain 对 pydantic 要求不同用独立 venv,按 requirements.txt 锁定版本安装

5.2 我踩过的几个典型坑

除上面这些相对“标准”的问题之外,有几个坑是我觉得特别值得讲的。第一个是关于数据源的时效性。TradingAgents 默认用的数据获取工具大多依赖公开市场数据接口,但我在实际测试中发现,不同数据源的返回延迟差别很大。如果研究员 Agent 在拿不到数据时选择“根据常识补全”,那后续的分析报告里就会出现模型幻觉内容,而且很难排查。所以在读代码时你会看到工具层有容错处理,但如果想让结果更可靠,我仍然建议自己接一套质量可控的数据源。

第二个坑出在“辩论发散”上。当你把辩论轮数调得过高时,多头和空头分析师会陷入无限循环的“我反驳你的反驳”,聊到最后已经完全脱离原始研究数据。这其实是多智能体系统里的常见问题:对话缺乏收敛机制。TradingAgents 的做法是用轮数和投资委员会总结来终止辩论,但如果你自己改造项目,建议给讨论内容加一个“相关性打分”,或者让委员会在每一轮结束后做中间总结,避免讨论跑偏。

第三个坑是 API 成本。我当时拿gpt-4o连续跑了几十次实验,账单涨得飞快。后来学聪明了:先用小模型验证流程变更的正确性,再挑少量案例用大模型跑正式结果。这个习惯后来被我带到了所有多智能体项目里,非常管用。

6. 关于多智能体框架选型的一些思考

6.1 TradingAgents 为什么选择 AutoGen

读源码的时候我注意到,TradingAgents 的多智能体编排直接使用了 AutoGen 的ConversableAgentGroupChat。这其实是个很务实的选择。AutoGen 提供了开箱即用的“群聊”机制,天然适合多空辩论这种多角色轮流发言的场景。你只需要定义 Agent 和它们的 Prompt,GroupChatManager 就能替你处理发言顺序和轮转逻辑,基本不用自己写状态机。

我同时对比过 AgentScope、LangGraph 这些同样热门的多智能体框架。如果项目本身就是一条固定流水线,AgentScope 的管道式抽象写起来会更直接;如果对控制流有非常精细的要求,LangGraph 那种显式的图结构更可控。但 TradingAgents 的核心场景是“自由讨论 + 有限轮数收敛”,这正好落在 AutoGen 的舒适区里。选择框架不是选最好的,而是选最贴合业务编排逻辑的。

6.2 从 TradingAgents 看多智能体框架的取舍

我自己在做多智能体项目选型时,通常会先问三个问题:第一,Agent 之间是固定顺序协作,还是自由对话?固定流水线优先考虑简单直接的编程模型,自由对话才需要群聊机制。第二,需要精确控制每一步的状态和分支吗?如果需要,图结构框架更合适。第三,团队对框架生态的熟悉程度如何?再强大的框架,如果读代码的人不熟,踩坑成本会抵消它带来的效率。

TradingAgents 现在这套模式的取舍也很明显:换来的是开发效率高、代码直观,付出的是对运行过程的可控性较弱。如果你在调试时想精确控制“哪个 Agent 在什么条件下发言”,AutoGen 的默认群聊机制就不够灵活了。我自己的建议是,不要盲目替换框架,而是先理解你业务里的控制流到底长什么样。想清楚这个问题之后,无论是 AutoGen、AgentScope 还是 LangGraph,选起来都不会纠结。

7. 个人读代码心得:如何理解并改造它

7.1 在陌生项目里快速定位关键代码

如果你准备读 TradingAgents 或者类似的 Agent 项目,我个人的方法是“先跑通、再拆解、最后重写”。第一步一定是把项目跑起来,看它实际输出什么,有了感性认识后,代码读起来才不会迷失方向。第二步是找入口文件,通常是run.pymain.py,从入口追踪一条完整的数据流:输入是什么、经过哪些模块、最终输出是什么。第三步才是去读底层工具和细节实现,这时候你已经知道每个模块在整条链路里的位置,读起来会快很多。

在读 TradingAgents 的过程中,我还习惯性地在笔记里画了一张“数据流图”:研究员的数据怎么流到分析师,分析师怎么流到交易员,交易员怎么流到风控。这对理解多智能体系统的协作方式非常有帮助。多智能体项目最核心的逻辑不在某个文件里,而在文件之间的消息传递路径上。

7.2 最值得改的三个地方

读完一遍之后,如果你想在它基础上做二次开发,我觉得有三个方向最有价值。第一个方向是重接数据源。把工具的默认数据接口替换成更及时、更稳定的行情和新闻接口,分析结果的下限会立刻提升。第二个方向是给 Agent 增加长期记忆,让它在多轮分析之间可以沉淀“上次判断对了什么、错了什么”,而不是每次从零开始。第三个方向是引入更严格的输出校验,比如在交易员和风控的输出环节加一层 JSON Schema 校验,不符合格式就自动重试,能显著降低下游解析的错误率。

还有一个小细节:你在改造时尽量保持每个 Agent 的输出“结构化”。多智能体系统里,自然语言是 Agent 之间交流的载体,但这里的自然语言应该是有格式的、可解析的,否则链路一长,错误会像滚雪球一样越滚越大。

我自己读这类项目最大的收获,不是它能不能真的预测市场,而是它把“复杂任务拆解成多角色协作”这件事做到了可运行、可复现的程度。你在读的时候也不会总想着交易这件事,注意力会更多地被“如何设计 Agent 边界”“如何让辩论收敛”“如何用 Prompt 约束输出”这些问题吸引。如果最后你也能跑通一次完整的分析流程,并且试着自己改一个角色、加一条规则,那这个项目对你来说就没有白读。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询