从0到1构建多Agent智能投研系统:架构、研报与风控实战
1. 从策略脚本到 Agent 系统我为什么放弃自动执行这条路先聊点背景。我自己的编程底子凑合炒过几年股也写过一些所谓的量化策略。坦白说市面上大多数个人量化框架核心思路都是写好规则定时执行。均线金叉买入MACD 死叉卖出RSI 超过 70 减仓。这类东西跑起来并不难难的是它根本没有思考能力。行情是活的市场是变的。2023 年那波 AI 行情靠传统指标能抓到吗能但更多时候是刚金叉就碰上高开低走刚死叉又来个V型反弹。规则是死的盘面是活的这个矛盾我深有感触。到了后来我甚至怀疑自己写策略到底是在做投资决策还是在写一堆条件触发器。真正让我转向 AI Agent 的是去年在一个技术社群里看到有人分享的多 Agent 辩论式研报生成 Demo。几个智能体扮演不同角色为同一只股票写分析然后互相提问、修正结论。当时我就意识到这东西的价值不在预测涨跌而在把过去依赖个人经验和盘感的分析流程变成一群有角色分工、有推理过程、能自我修正的数字化研究员和交易员。我最初的想法很简单把分析、决策、风控、执行拆成不同的 Agent。分析 Agent 负责读数据和新闻决策 Agent 负责给出买卖建议风控 Agent 负责盯着仓位和回撤。听起来很美好但真正落地的时候问题一个接一个。这篇文章就是记录我从 0 到 1 搭完这个系统的全过程包括架构怎么拆、Agent 之间怎么协作、风控怎么嵌进去、以及模拟交易怎么对接。需要先说明一点这套系统从头到尾都是在模拟环境里跑的我没有拿真金白银去验证也不建议大家直接把它接到实盘。用它来做研究、练手、验证思路绰绰有余。真要上实盘涉及的合规、资金安全、系统稳定性完全是另一个量级的问题。2. 整体架构四个 Agent 加一个调度核心我是怎么拆解的2.1 为什么不用一个超大 Agent搞定所有事最开始我确实图省事想用一个 Agent把研报、决策、风控全部塞进去。做法也简单给一个大模型写一大段 System Prompt让它既当分析师又当交易员还要当风控员。结果跑了几天问题很明显。一是上下文太长。一份完整的研报本身就有一两千个字再加上行情数据、历史交易记录、实时持仓一次对话很容易超过几万 token。大模型在长上下文里经常忘記前面的细节而且响应速度明显变慢。二是角色互相污染。让同一个模型既负责找机会又负责控风险它往往会在分析的时候就已经开始想要不要买心态上和真正的分岗制完全是两码事。三是最重要的出错了不好修。如果研报部分写崩了你没法单独重启分析师这个角色只能整个流程重来一遍浪费时间和 token。后来我换成了多 Agent 架构拆成四个角色各管一段研究 Agent研究员负责收集行情、财务、新闻数据输出结构化研报不负责给买卖结论。策略 Agent交易员读研报 当前持仓给出明确的买卖建议附带仓位和价格区间。风控 Agent风控官独立于策略 Agent 运行检查建议是否触碰持仓集中度、回撤限制、单笔亏损上限等规则。执行 Agent下单员对接模拟交易接口根据最终确认的指令执行下单并在成交后回报结果。四个 Agent 全部挂在一个调度核心下面调度器控制它们什么时候该出场、数据怎么流转、中途出错怎么重试。这个分工方式有点像公司里投研、交易、风控三个岗位互相牵制的设置各角色说话之前都得先过一道流程不能越权。2.2 调度核心流程编排不是简单地依次调用调度核心是整套系统的骨架我的第一版写得很粗糙research() → strategy() → risk_check() → execute()四个函数按顺序跑一遍完事。但跑起来之后发现真实场景远没有这么线性。一个典型的完整调度流程是这样的这是简化版描述实际代码里用状态机来管理启动信号触发研究 Agent先拉取目标股票最近 120 个交易日的日线数据加上当天的新闻标题用新闻 API 抓取不涉及任何非公开信息。研究 Agent 生成研报输出格式是 JSON包含基本面评分、技术面评分、消息面评分、风险提示、PE/PB 分位数等字段。策略 Agent 读取研报结合当前账户持仓和现金余额输出买入 XX 股限价 XX 元或卖出 XX 股这样的结构化指令。风控 Agent 接到指令后先检查账户当前的回撤、持仓占比、单笔亏损预算再决定放行还是打回。如果风控打回调度器把打回原因返回给策略 Agent让它重新提一个更保守的方案。如果放行执行 Agent 把指令翻译成模拟交易平台能识别的订单格式发送并等待回报。这里最关键的设计是每个 Agent 的输入输出都是结构化数据不是自然语言聊天。一开始我犯过错误让 Agent 之间直接用对话文本传递信息结果解析文本就把人逼疯了。后来统一改成 JSON schema每个 Agent 只输出指定字段调度器再做必要的校验和转换。这样做的好处是链路清晰、出错了能定位到具体环节也方便给后面接回测逻辑留接口。2.3 Agent 的工作方式ReAct 模式与工具调用我给每个 Agent 都开了工具调用权限而不是让它们只靠模型内置知识硬想。研究 Agent 可以调起的工具有获取K线数据、获取财务指标、搜索新闻并生成摘要风控 Agent 可以调用账户信息查询接口执行 Agent 只能调用下单和撤单两个函数。从实现上讲这就是标准的 ReActReason Act模式模型先根据用户请求决定调用哪个工具拿到工具返回的结果后再决定下一步是继续调用还是输出最终答案。大模型在这里扮演的不再是答案生成器而是决策调度器——它决定用什么工具、以什么顺序用、怎么解释结果。举个例子研究 Agent 在分析一家公司时会先调一个函数获取近一年财务数据发现营收增速不错但毛利率在下滑又会接着调另一个函数去查最近三个季度的毛利率变化最后把数据整理进研报。整个过程是自主的不需要人为干预每一小步。这也是Agent和普通函数调用最大的区别前者有推理过程后者只是机械执行。2.4 技术栈选型与跑通最低成本方案这一节写一点务实的东西毕竟很多人问的最多的就是用什么技术能搭出来。我的方案不算豪华核心组件就四样组件选择说明大模型接口兼容 OpenAI 格式的通用 API先后换过几家最终用了一个支持函数调用的推理模型不绑定特定厂商方便切换开发框架Python 自研轻量 Agent 调度器没有用现成的 Agent 框架因为我的调度流程比较特殊自研反而更简单数据源开源数据库 行情 API 缓存日线数据自己从公开接口抓存 SQLite新闻走通用搜索 API模拟交易某券商的模拟交易开放接口有完整的 REST API支持限价单、市价单、持仓查询方便对接整个系统跑在本地一台 Linux 服务器上数据库就是 SQLiteAgent 服务用 FastAPI 包了一层 HTTP 接口前端写了个最简单的 HTML 页面用来观察状态。说实话这套东西总代码量大概三千行出头不算复杂但每一步都在解决实际痛点。3. 多 Agent 研报管线从数据采集到决策建议的完整链路3.1 研究 Agent 的 Prompt 设计让角色真正立起来Prompt 是 Agent 的灵魂它的设计决定了 Agent 是有脑子的分析师还是高级聊天机器人。我写研究 Agent 的 System Prompt 时重点做了三件事。第一件事是明确角色边界。我在 prompt 里直接写了你是某机构的研究员你的职责是输出客观、可验证的分析报告。你不提供买卖建议不判断目标价位。买卖建议由策略模型负责。这句话看着简单实际作用很大。没有这个边界研究 Agent 经常会在研报后半段自己加上因此建议买入这种越权结论把后续决策流程打乱。第二件事是指定研究框架。我不让它自由发挥而是给它一个固定的分析维度基本面营收、利润、ROE、负债率、技术面趋势、均线、成交量、相对强弱、消息面近一周新闻情绪。每个维度都要给出 1 到 5 的评分并附上支撑数据。这样出来的研报不是一篇散文而是一张结构化的体检表后面的策略 Agent 读起来效率会高很多。第三件事是强调不确定要说明。prompt 里专门加了一段如果某项数据缺失或存在明显矛盾请在研报中注明不要用推测填补空缺。这句话最初是后来才加的是因为我发现研究 Agent 在没有数据的情况下会一本正经地编造财务指标看起来很像真的但实际上不可靠。加了这句之后报告质量提升得非常明显宁可缺数据也不让模型编数据。3.2 研报生成的实测效果评分不是玄学是数据对齐跑通研报管线之后我看了一份完整的输出示例以某只消费类股票为例股票名字就隐去了不影响理解逻辑。研究 Agent 一开始拉取了最近 120 个交易日的收盘价数据计算了 20 日与 60 日均线的相对位置判断处于多头排列状态又调财务接口发现营收增速连续两期超过 15%但销售毛利率从 45% 下滑到 41%最后抓了 10 条新闻标题情绪分析结果偏正面但有一条关于某核心单品被竞品模仿的负面消息。最终研报输出核心字段简化版大致是基本面评分4/5理由营收增长稳定、盈利质量中等、毛利率下行需关注技术面评分4/5理由趋势向上、量价配合尚可、短期无超买信号消息面评分3/5理由整体偏正面、存在个别竞争风险综合风险提示毛利率连续下滑 单品竞争压力数据完整度85%缺失部分为北向资金流向数据接口暂不支持这份研报最大的价值不是评了几分而是每个评分都有数据支撑。策略 Agent 在后续推理时可以明确看到4 分是基于什么算出来的而不是一个凭空冒出来的神秘数字。这也意味着任何人拿到这份研报都能倒回去检查数据源做所谓的可追溯分析。3.3 多 Agent 辩论机制我是怎么加了一层对抗性检查的光有一份研报策略 Agent 就可以直接用了但我觉得不够味。既然是多 Agent 系统就应该让冲突和修正发生在决策之前。于是我加了一个轻量级的辩论模块。流程是这样的研究 Agent 产出一份初步研报后会有一个质询 Agent我偷懒直接复用策略 Agent 的角色对它提出质疑。质疑不是随便写两句而是从研报里找漏洞。常见问题是技术面给了 4 分但成交量在最近 5 天持续萎缩量价是否真的配合请补充量能数据。毛利率下滑的驱动因素是原材料涨价还是产品结构变化如果是原材料涨价是否具有持续性某条新闻的负面消息对单季度利润影响估计有多大被质询之后研究 Agent 会重新审视自己的研报要么补充数据要么修改评分生成第二版。我统计过大概有 60% 的质询会触发数据补充30% 会触发评分修正剩下 10% 是质询 Agent 自己理解错了。这个对抗过程虽然增加了分析耗时和 token 消耗但换来的报告质量提升非常明显。至少在我后续的回测里经过辩论的研报比单遍生成的研报胜率更高——这个数据我后面会专门写。4. 策略 Agent 与决策引擎仓位管理才是真正的技术活4.1 策略 Agent 是怎么把研报变成具体买卖指令的如果说研报是情报那策略 Agent 就是指挥官。它的输入包括三样东西最新研报、当前账户持仓、近期的交易记录。输出只有一种格式指令集。指令集里每条指令包含方向买入/卖出、数量股数、订单类型限价/市价、限价如果有限价、有效期当日有效/撤单。先说一个很容易踩坑的细节策略 Agent 不能只看研报就给仓位建议。第一版我让它输出买入 XX结果它忽略了账户里根本没那么多现金给出的买入数量超过了实际可用余额。后来我在输入里强制加上了当前现金余额和当前持仓市值两个字段并在 prompt 里规定下单数量不得超过可用余额对应的最大股数保留至少 5% 现金作为缓冲。加了这行之后策略 Agent 的输出才变得可执行。策略 Agent 的推理逻辑大致分三步根据研报的综合评分决定动作倾向高分4-5倾向加仓中分3-4倾向持仓观察低分3以下倾向减仓。根据当前仓位决定动作幅度如果股票已经是第一大持仓即使评分偏高也只会小幅加仓如果仓位很低、现金充足加仓幅度可以大一些。参考风险提示调整参数研报里明确写了毛利率下滑风险策略 Agent 会在买入指令里额外附一句建议设置 5% 止损线。4.2 组合层面的仓位管理单只股票永远不超过 30%这里必须多说一句单只股票的决策做得再好如果组合层面没有约束整个系统仍然是裸奔状态。我在策略 Agent 的 prompt 里写了三条硬规则优先级高于其他一切单只股票市值占账户总资产比例不超过 30%。单一行业持仓市值占比不超过 50%。账户回撤达到 8% 时自动触发只减不加模式直到回撤收窄到 3% 以内。这三条规则不是在策略 Agent 内部自检而是在调度核心层做强制校验。也就是说即使策略 Agent 冒出来一个买入到 50% 仓位的建议调度器会在它到达风控 Agent 之前就把它拦下来要求策略 Agent 重新生成。这是我在实际测试中发现的漏洞——模型是会被带跑偏的尤其是连续几次决策对了之后策略 Agent 会变得激进仓位建议往往超出安全边界。硬编码在调度层比让模型自我约束可靠得多。4.3 从研报到指令的实测输出一个完整的决策样例再给一个实际跑出来的决策示例方便理解整个链路。某次策略 Agent 拿到一份评分偏正面的研报后输出如下简化后[ { action: buy, symbol: 000XXX, quantity: 500, order_type: limit, limit_price: 18.55, reason: 研报综合评分4.2分当前仓位仅占账户5%安全边际充足, risk_flags: [建议止损线5%, 注意毛利率下行风险] } ]执行这条指令前的调度过程是调度核心先检查当前持仓与现金——现金余额 11.2 万500 股 × 18.55 元 9275 元加上手续费也不超过现金限制仓位加完后这只股票约占总资产的 12%远低于 30% 上限校验通过转发风控。这条链路每一次都会完整走一遍不是省略步骤的自动信任。我当时特意用日志记录下了每次决策的 reason 字段方便后面回查它为什么这么买。这种做法在实盘里同样重要——没有决策日志的系统等于没有记忆的账户。5. 风控 Agent 与模拟交易执行在真实摩擦成本下跑完闭环5.1 风控 Agent 检查的不只是风险还有规则一致性风控 Agent 可能是整套系统里架构最特殊的一个模块因为它不是把 prompt 写好就完事的而是要同时跑两类检查一类基于硬规则一类基于模型判断。硬规则直接写在代码里不走大模型调用包括止损检查如果当前持仓收益率低于 -7%风控直接发出强制平仓指令跳过策略 Agent 的建议。回撤检查账户最高净值回撤超过 8% 时拒绝所有新建仓指令只允许减仓或清仓。集中度检查单股、单行业占比超过阈值时拒绝相关加仓指令。单笔亏损预算每次下单估算的最大亏损限价与止损线之间的差额 × 股数不得超过账户净值的 2%。这些硬规则不走模型的原因很简单风控必须确定性 100%不能依赖大模型的概率判断。你说应该回撤超了模型可能给你分析出一篇论文来但风控要的是是或否。模型判断部分则处理那些不容易规则化的场景。比如研报里写了应收账款周转天数连续三个季度上升风控 Agent 会给策略 Agent 打回一条补充意见现金流质量存在隐患建议降低目标仓位或者等待更明确的现金流改善信号。这种软性风险提示策略 Agent 会作为重要参考去调整输出。5.2 模拟交易执行与摩擦成本滑点和手续费不能只看热闹说一句实话一开始我把模拟交易接口对接完之后特别兴奋想着这下闭环跑通了直接开始自动交易。但跑了几天之后我发现了模拟盘和纸面计算之间最大的差距摩擦成本。摩擦成本包含三部分手续费、滑点实际成交价与预期价格的偏差、以及冲击成本大单对盘口的影响。我用的某券商模拟交易接口支持市价单和限价单。市价单的问题在于如果盘口卖一档量很小而我的订单量很大系统会按多档价格依次成交平均成交价可能比最新价高出一截。限价单相对可控但存在挂单不成交的问题。我在测试中最明显的一次滑点经历是某股票当时最新价 20.10我挂了一笔 3000 股的限价买单价格设在 20.15。盘口卖一到卖五加起来只有 1500 股的量剩下的 1500 股被分了三档成交最贵的成交在 20.23加权平均成交价变成了 20.185。相比最新价每股价差 0.0853000 股就是 255 元的额外成本。这个体验让我真正理解了为什么实盘交易系统要把滑点模型内置到策略回测里。我后面在系统里加了一个滑点估计函数估算方式是当订单量超过盘口前三档总量时自动把成交价上调 0.2% 作为保守估计并在策略 Agent 的输入里显示出来。这么做的意义是让策略 Agent 在做仓位决策时就已经意识到大单不是免费的从而缩减过大的买入数量。5.3 执行结果回报确认、补单、撤单的处理逻辑执行 Agent 在真正下单之后还有一个容易被忽略的步骤确认回报。模拟交易接口虽然不会真假作废但成交结果需要轮询获取。如果下的是限价单盘口价格没到订单会一直挂着这时候系统不能干等着。我设计了三种处理路径订单在 60 秒内完全成交执行 Agent 记录成交均价更新持仓快照流程结束。订单部分成交剩余未成交执行 Agent 询问调度核心是否追加限价或改为市价追击。这个决策如果发生会再走一遍策略 Agent 风控 Agent 的校验流程不会直接由执行 Agent 决定。订单始终未成交默认在收盘前 30 分钟撤单并在日志里记录未成交原因价格未触及。这个未成交与撤单的处理逻辑在回测里不会暴露问题但在模拟交易里真的很影响体验。如果限价单挂一整天都没成交资金占用着又干不了别的事账户里的很多东西都会显得不对劲。加入撤单机制后至少保证了资金不会被僵尸订单套住。5.4 模拟交易平台的接口对接细节鉴权、频率限制、字段匹配最后写一点点接口对接的细节因为很多人卡在这一步。模拟交易接口一般会提供 REST API核心就四组查账户、查持仓、下单、查订单状态。鉴权方面用的是 OAuth token每次请求带在 header 里。要注意 token 有过期时间我最初忽略了这一点导致系统跑了两天之后突然报 401 错误后来写了一个 token 刷新函数在过期前 5 分钟自动重新获取。频率限制方面模拟接口一般限制每秒最多 5 次请求。我因为下市价单后高频轮询订单状态每秒一次结果触发了限流订单查询直接失败。解决方案很简单轮询间隔改为 5 秒查询前加了一个本地缓存60 秒内同一订单不重复查询。字段匹配方面不同平台字段命名差异挺大有的叫volume有的叫entrust_amount都是数量。我写了一个适配层把平台返回的字段统一映射成系统内部的标准字段。这样换平台的时候只需要改适配层不用动上层逻辑。6. 实测回测结果与复盘从看着能跑到策略真的更稳了6.1 回测跑出来的数据单 Agent vs 多 Agent 的差异系统搭建完成之后我做了两周的模拟交易和一次半年的历史回测。数据不能全信毕竟市场行情和运气成分都在里面但至少可以观察到一个明显的趋势多 Agent 系统相比单 Agent 方案确实在控制回撤上表现更好。我把多 Agent 完整链路和同一个策略 Agent 单独交易跳过研报、跳过风控做了对比。回测区间选了 2023 年 7 月到 2024 年 1 月半年的 A 股行情标的池就是沪深 300 成分股里我比较熟悉的几十只股票。结果如下仅代表我的测试环境不构成投资参考指标单 Agent 直接交易多 Agent 完整链路累计收益率8.2%10.7%最大回撤-12.5%-7.8%交易次数2819单笔平均亏损-3.8%-2.3%胜率按笔数46%52%多 Agent 的累计收益率略高但最明显的是最大回撤从 -12.5% 降到了 -7.8%。这个变化不是策略 Agent 变聪明了而是风控 Agent 在关键节点踩了刹车。我翻了一下交易日志回撤控制贡献最大的两次操作分别是在某股单日暴跌 4% 时风控触发强制止损在某股加仓后回撤逼近阈值时风控拒绝了一次看起来很有吸引力但会突破集中度限制的加仓指令。6.2 一次真实的模拟交易复盘为什么我决定让系统少交易有一笔交易让我印象很深。系统在某股票研报出来之后给出了一次买入决策买入理由是基本面 4.5 分趋势向上消息面偏正面。两天后该股因为一条行业监管信息跳空低开 3%策略 Agent 给出的建议是加仓摊薄成本。但风控 Agent 检查后发现账户已经处于最大回撤接近 5%的状态加仓会导致单股仓位突破 30%。风控直接打回并附注当前处于回撤恢复期禁止新增风险暴露。事后行情继续下行该股又跌了 5%。如果当时执行了加仓账户回撤会直接扩大到 9%触发更严重的风险状态。这笔没执行的交易恰恰是整个系统里最有价值的决策之一。这让我深刻地认识到系统的价值不在于多交易、不在于抓住每一个机会而在于在最不该出手的时候能忍住不出手——这不是策略逻辑写出来的而是风控边界硬性保证的。6.3 我踩过的五个最关键的坑附带解决方案最后整理一下我在整个项目里踩过的最值得分享的坑希望能帮后来者少走弯路。第一个坑Agent 直接输出自然语言作为中间产物导致解析困难。解决方案所有中间通信强制使用 JSON schema并在调度核心做 Schema 校验失败时自动重试一次。第二个坑策略 Agent 不读账户总资产就开始给仓位建议导致下单数量超过余额。解决方案在策略 Agent 的输入里固定拼上现金余额 持仓市值两个字段prompt 里明确限制不得下单超过可用现金对应数量。第三个坑多 Agent 辩论环节在某些极端行情下耗时过长。也就是行情剧烈波动时研究 Agent 和质询 Agent 可能会争论很多轮导致系统在最佳交易时间点上反应迟钝。解决方案给辩论环节设置轮次上限最多两轮超时直接进入下一阶段。第四个坑风控 Agent 的硬规则和策略 Agent 的建议发生冲突时曾经出现过死循环。策略 Agent 被风控打回后重新生成一个建议但生成出来还是类似方案再次被打回无限循环。解决方案调度核心增加了重试计数逻辑策略 Agent 被连续打回两次后直接强制跳过该标的转入下一个候选。第五个坑模拟交易接口偶发超时导致系统误判为下单失败重复提交订单。解决方案在下单 API 调用前生成唯一的 client_order_id接口超时后先查询该 ID 的状态确认是否已成交再决定是否需要补单。这个方案基本上避免了重复下单的隐患。7. 这套系统后续还能怎么扩展我的下一步计划整个项目跑通之后我最大的感受是AI Agent 在投资研究这个场景里目前最有价值的地方不在于替代人类做决策而在于把过去没法标准化的研究过程变成了可追溯、可复盘、可迭代的数据管道。过去的我写一篇研报靠的是盘感和经验现在这套系统每一条结论都有数据索引每一次决策都有完整日志。光是这一点就已经超过了大多数个人研究工具。接下来我的计划有三个方向。第一个方向是让研究 Agent 覆盖更多的另类数据比如产业链上下游的价格数据、政策文件的文本分析。这些信息单纯靠财务指标很难捕获但大模型的文本理解能力正好能派上用场。第二个方向是给决策引擎加一套多策略投票机制。目前只有一套策略 Agent未来可以并行跑趋势型、价值型、反转型三个策略 Agent让它们对同一份研报给出不同意见再由调度核心做综合投票。这会让系统更像一个小型投研团队。第三个方向也是我最近最想做的把整套系统移植到实盘环境之前至少在模拟环境里连续运行三个季度积累足够的跨周期数据再看看风控规则是否需要根据市场状态动态调整。毕竟模拟盘跑得再好和真实资金之间还隔着心态、流动性、合规这三道大关。如果你也想拿这个项目练手我的建议是从最小闭环开始先做研究 Agent 策略 Agent 的两 Agent 研报系统只输出建议不接自动交易。跑通之后再逐步加风控、加执行、加辩论。不要一上来就追求大而全否则问题会多到让你失去调试的信心。慢慢来每一步都验证扎实你会发现多 Agent 系统最大的魅力不是自动赚钱而是逼你把整个投资流程想得更清楚。