☰
基于多Agent的股票分析模拟交易系统:架构设计与避坑实践
2026/10/21 7:34:38 网站建设 项目流程

先说说这个项目的定位:它不是那种让大模型聊聊天、生成几段股评的玩具。它的目标是,让 AI Agent 真正把股票分析这个流程跑起来——从抓取行情数据、生成多份专题研报,到开一个“模拟资金账户”自主买卖,全程带风控约束,并把每一笔决策记录下来方便回测和复盘。你可以把它理解成一个武装了外挂大脑的模拟交易员。

这个系统有人会觉得难,其实拆开看就是几块积木:数据层、多 Agent 研报层、决策交易层、风控层、回测复盘层。难的地方在于把这几块拼成一条能稳定跑、能解释、能迭代的流水线。我最初也天真地以为,一个 Agent 扔进去就能输出完美操作建议,后来发现还是要老老实实按工程思路做,该拆就拆,该硬编码就硬编码。下面把整套搭建过程、参数设定和踩过的坑都摊开讲。

1. 项目定位与整体架构:不做一个“会聊天的股评机器人”

1.1 从单 Agent 到多 Agent:我踩过的第一个坑

最早一版我做得很简单:一个 Agent,把一堆历史 K 线、财务数据、新闻文本全扔进同一个上下文,然后让它直接回答“明天该买还是卖、买多少、止损设在哪”。结果很快暴露问题,而且不是偶发,是结构性的。

第一个问题是上下文互相污染。宏观分析、技术面、基本面、舆情信号全塞在一起后,模型经常顾此失彼:看到一两则短期利空新闻,就给长期稳健的公司基本面打了偏空结论;看到均线多头排列,又把高估值风险抛到脑后。这不是模型不聪明,而是这种“大杂烩”的输入方式本身并不符合复杂决策的分工规律。第二个问题是无法追溯。系统输出一个买入决策后,我想知道它到底基于哪条信息得出的,结果看不出是哪一步出了问题——是数据缺失,是宏观判断错了,还是情绪信号权重过高?这种不可解释的系统,跑得越久越不放心。

于是我把单个 Agent 拆成多个专职角色。每个 Agent 只负责一块领域,输出统一格式的“观点 + 置信度”,最后再由一个类似“投委会”的 Agent 做汇总决策。改动之后,系统的可解释性和稳定性都明显提升,这也是整个项目最关键的一次架构调整。

1.2 系统里最核心的三条流水线

整体架构可以分为三层,也可以看作三条不断循环的流水线。

数据流水线负责把外部行情、基本面、新闻等原始信息采集下来,清洗后转换成结构化的、模型友好的数据切片。没有这一层,后面所有 Agent 都是无源之水。分析决策流水线负责把数据切片送入多个分析 Agent,形成独立观点,再由投委会 Agent 合成为资产配置建议,接着由交易引擎做仓位计算和模拟下单。复盘回测流水线负责把每一笔模拟交易、每一日的 Agent 观点和当时的市场状态都记录下来,定期复盘、回测验证,并把结论反馈回参数设定。

这三条流水线串起来,其实就是一个完整的“感知—分析—决策—行动—复盘”闭环。

1.3 核心设计原则:数据管道化、决策可追溯、风控硬约束

我给自己定了三条不能妥协的原则。第一条,数据必须管道化,也就是每个 Agent 拿到的不是乱糟糟的原始爬虫结果,而是经过清洗、去重、格式统一的标准化数据切片。第二条,决策必须可追溯:任何一个交易操作,都能回溯到对应研报、对应输入数据、对应模型置信度。第三条,风控必须硬约束:Agent 只能提建议,真正执行下单前必须经过独立的、写死在代码里的风控规则校验。

这三条听起来像废话,但真正做到位并不简单。尤其是硬约束这条,我见过不少人的实现是把风控要求写进提示词,让模型“自觉遵守”。这在真实资金面前是完全不可接受的,因为提示词本质上只是建议,不是规则。风控必须落在执行器里,作为不可绕过的门槛。

2. 数据层:让 Agent 吃上干净的行情、基本面和新闻

2.1 行情数据的获取与清洗

股票分析离不开行情数据,但这部分的工作量往往被严重低估。你需要日线、分钟线、复权价、成交量、涨跌停状态等等。我一开始偷懒,直接把接口返回的 JSON 原样塞给 Agent,结果发现模型经常被一些脏字段干扰,比如无意义的后缀、字符串类型的价格、缺少时间戳的 record。

后来我把行情数据统一存进本地数据库,以“代码 + 周期 + 日期”做唯一键,写入前做基础清洗:价格字段全部转成浮点,时间统一成标准格式,删除停牌期间的无效交易记录,并且把复权处理做成一个显式步骤。这里有一个容易被忽略的关键点:计算技术指标时用后复权,查看历史真实价格时用前复权。如果混用,均线、MACD 这类依赖连续价格的指标会产生严重偏差。

获取数据时还要考虑接口限流和增量同步。我写了一个简单的增量抓取逻辑,只拉取本地数据库里缺失的日期区间,避免每天全量重新下载。伪代码如下:

def sync_kline(symbol, freq): latest_bar = storage.get_latest_bar(symbol, freq) start_date = latest_bar + 1个交易日 bars = quote_api.fetch_kline(symbol, freq, start_date=start_date) storage.bulk_upsert(bars)

这个过程的收益是隐性的,但它是整个系统能稳定跑一个月不出幺蛾子的基础。

2.2 结构化喂给模型:统一 JSON Schema

Agent 读数据的方式,直接决定了它的分析质量。我自己实测下来,模型读结构化的 JSON 或表格,比读长篇自然语言要可靠得多,幻觉率和答非所问的情况都显著下降。所以我没有把财报摘要写成一大段文字,而是转成一个紧凑的 JSON 结构。

{ "symbol": "000001", "date": "2025-01-10", "roe": 12.3, "pe_ttm": 18.9, "pb": 2.1, "income_growth_3y": 15.4, "debt_ratio": 45.6, "industry": "banking" }

这种做法的本质是“减少模型的推理负担”:它不需要从散文里自己提取关键事实,而是直接基于明确字段做判断。同样的思路应用到其他数据切片上:技术面提供均线值、量能比值、波动率、ATR,宏观层面提供利率区间、市场情绪指标、指数估值分位,舆情层面提供情感分数和事件标签。所有层级的 Agent 拿到的都是同一个“契约”,后续扩展会非常方便。

2.3 新闻和事件信号的接入

新闻数据是最难处理的一类,因为它是非结构化的,噪声极大,而且同一个事件会被多家媒体重复报道,直接丢给模型会造成严重的重复计数。我先是抓新闻,然后做标题和正文的相似度去重,再让一个小模型做情感打标,最后按股票代码聚合。

具体来说,每个事件会归一化成“时间 + 主题标签 + 情感分数 + 重要程度”。比如“公司发布业绩预增公告”会被打上“业绩”标签,情感分在 0.8 左右,重要程度高。这样投委会 Agent 不需要阅读几十条原始新闻,只需要看聚合后的事件摘要。这里也涉及成本控制:新闻过滤这类高频低难度任务,用一个小模型就能完成;深度研报这类低频高难度任务,才值得动用更强的模型。

2.4 数据更新的调度与成本控制

数据层还需要一个稳定的调度逻辑。我是用一个每日定时任务把所有流程串起来:先同步行情和新闻,再清洗入库,然后触发多 Agent 分析。为了避免重复分析浪费成本,同一只股票在同一天内只做一次完整分析,结果缓存到本地;只有在新闻、行情或财务数据发生实质变化时才刷新缓存。这个简单的缓存策略,让我的 API 成本直接降到了原来的三分之一。

这里要特别提醒:数据质量问题往往不是一眼能看出来的。你以为是模型判断错了,实际可能是某个日期的数据重复了,或者复权价格计算错了。所以我在数据入库环节加了几条基础校验规则,比如“单日涨跌幅超过 20% 时告警”“成交量不能为负数”“日期不能出现跳变”,这样至少在问题发酵前能及时发现。

3. 多 Agent 研报模块:专业分工与观点合成

3.1 五个 Agent 角色与各自职责

多 Agent 研报模块是整个系统的核心,我把它拆成了五个固定角色。宏观环境 Agent 负责评估市场整体风险偏好、利率方向、社融节奏和指数估值分位,它的输出不是“预测涨跌”,而是给出一个市场情绪温度值;基本面 Agent 专注财务质量、成长性、估值分位,判断公司自身价值是否被低估;技术面 Agent 只分析趋势、均线排列、量价关系和动量,不看新闻,不看财务;舆情事件 Agent 负责把新闻聚合结果和突发公告消化成事件层面的冲击力度;最后一个风控 Agent 比较特殊,它不输出买卖方向,只计算“当前波动率环境下,单只股票和整个组合的仓位边界”。

每个 Agent 的输出格式是统一的,核心是一个“结构化观点”:

{ "agent": "fundamental", "signal": 0.65, "direction": "bullish", "confidence": 0.7, "reason": "ROE稳定在15%以上,PE处于近三年低位", "risks": ["行业政策变化可能影响盈利"] }

统一格式非常重要,它让后续的投委会 Agent 可以像处理数据一样处理观点,而不是去解析一段段风格迥异的散文。我把这种设计叫作“观点即数据”。

3.2 研报生成流程与工具调用

五个 Agent 是并行运行的,相互之间不直接对话,也不会提前看到其他 Agent 的结论。这样设计是为了减少所谓的“信息锚定效应”——如果技术面 Agent 先看到基本面看多,它很容易无意识地向多头倾斜。保持独立性,才能让后续的融合真正有意义。

每个 Agent 内部不是简单的“把数据喂进去、输出观点”,而是可以调用工具的。比如基本面 Agent 发现自己拿到的财务摘要太旧,会触发一次增量财报抓取;技术面 Agent 如果发现均线状态不清晰,会重新拉一份更长周期的 K 线来做趋势确认。这种“分析中按需取数”的机制,比一次性把所有可能用到的数据全部塞进上下文要省很多 token,模型注意力也更集中。

并行完成后,五份结构化观点会进入投委会 Agent。

3.3 投委会 Agent 如何处理冲突信号

为什么不能简单把五个 Agent 的观点加权平均就完事?因为现实中的信号经常是矛盾的。举例来说:基本面 Agent 给出看多信号,置信度 0.7;技术面 Agent 给出看空,置信度 0.6;舆情 Agent 提示市场正在炒作该板块,风险较高。这种情况下简单平均得到的是一个模棱两可的无意义分数,而不是一个可执行的决策。

我的投委会 Agent 使用了这样一套裁决逻辑:先过滤置信度低于 0.5 的观点,因为这些基本属于噪声;再对剩余观点按角色权重加权得到初始信号;然后检查是否存在方向冲突,如果存在明显冲突,则强制降低整体仓位目标,而不是强行把方向判断成“多”或“空”;最后结合风控 Agent 给出的仓位边界,输出最终建议。

这套逻辑巧妙的地方在于:它让模型去扮演仲裁者,而不是计算器。计算层面的加权和边界校验由代码完成,模型只需要基于语义判断“谁的理由在当前市场环境下更有说服力”。这样既避开了模型不擅长精确计算的弱点,又利用了它在抽象推理上的能力。

3.4 提示词设计上的关键细节

多 Agent 系统的提示词设计,跟普通聊天提示词完全是两回事。我踩了不少坑之后总结出三条关键经验。

第一条,必须显式要求 JSON 输出,并给出输出模板。如果不给模板,大模型会自由发挥,输出字段名变来变去,下游解析器迟早会崩。我给每个 Agent 都定义了严格的字段名,包括 agent、signal、direction、confidence、reason、risks,并在提示词里强调只能输出这个结构。

第二条,控制上下文长度,只给必要的切片。不要因为模型支持长上下文就用长上下文,数据太长反而会稀释关键信息。我实测下来,同一个 Agent 用 2000 token 的精选数据和用 10000 token 的原始数据相比,前者在一致性上表现更好,成本还低。

第三条,给 Agent 设置清晰的角色边界。提示词里我会写“你是一个只看技术面的分析师,不关注新闻,不关注基本面”,用这种强约束把角色隔离做彻底,避免模型跨领域发挥。

4. 自主交易引擎:从研报到资金管理的最后一环

4.1 仓位计算公式与参数推导

研报产出的是方向和信号强度,真正决定买多少的算法在交易引擎里。我用的不是简单的一刀切满仓或半仓,而是一个连续的仓位计算公式:

目标仓位 = 基准仓位 × tanh(信号强度 × 强度系数) × 波动率修正系数

我直接给一个具体计算过程。假设基准仓位是 20%,信号强度得分是 0.65,强度系数设成 2.0,那么 tanh(0.65 × 2.0) = tanh(1.3) ≈ 0.76,所以基础目标仓位约等于 15.2%。然后再看波动率修正:如果目标组合年化波动率设定为 20%,但该股票近 20 日实际年化波动率已经到 32%,那么修正系数就是 20% / 32% ≈ 0.63,目标仓位进一步降到 9.6%。最后再跟风控 Agent 给出的上限取最小值。

我知道这套公式里很多参数是拍脑袋定的,但它最大的价值是让仓位变化有解释性:信号越强仓位越大,但波动率越高仓位反而越小。如果你不喜欢 tanh,也可以用线性映射或 sigmoid,核心逻辑一致。

4.2 止损、回撤与仓位限制的风控硬约束

这部分是整个系统中最不容妥协的一块。我坚持把风控规则写死在交易执行器里,而不是写在大模型的提示词里。提示词再强调“注意风险”,也有概率被模型忽略;而执行器里的规则是枚举型判断,没有任何商量余地。

我实际启用的规则包括:单只股票仓位上限 30%,确保不会因为一个决策就让整个组合暴露在极端风险中;单日最大亏损超过 2% 时,当日停止所有新建仓操作;每笔买入必须同时设置止损价,止损幅度采用 2 倍 ATR 的移动止损,一旦价格触发就立即模拟卖出;组合层面的最大回撤超过 15% 时,整个系统自动停止交易,转入只读复盘模式。

这几条规则里,止损设计尤其重要。我第一版止损直接设成“买入价减 8%”,后来发现这种固定百分比止损容易在正常波动中被扫出场。改用 2 倍 ATR 之后,止损会自适应股票本身的波动程度,明显更合理。风控的本质不是追求每笔都对,而是保证任何单次错误都不会大到无法挽回。

4.3 模拟执行器与交易日志

模拟交易执行器本身并不复杂,但要做得严谨。我用的是本地记账模式:一个数据库维护模拟账户的资金、持仓和流水,下单时按规则扣减可用资金,成交后更新持仓均价,收盘后按照最新市价计算浮动盈亏。为了贴近真实交易,我还加了手续费和滑点模型:手续费按万 2.5 计算,滑点按成交价的 0.1% 估算。

这里有个容易被忽略的细节:每笔模拟交易都必须记录完整的决策上下文,包括当时各 Agent 的观点、置信度、仓位目标、风控校验结果。这样后续复盘时才能回答“为什么买入”甚至“为什么没买入”。我把这个字段设计成一条 JSON 快照,直接存在交易日志表里。

4.4 每日运行循环与异常处理

整个系统的运行节奏是这样:每天收盘后先同步当日行情和新闻;然后对持仓股票和候选股票池跑一遍多 Agent 分析;再让投委会 Agent 生成次日操作建议;交易引擎拿到建议后先做风控校验,通过才模拟下单,不通过就写出跳过日志;最后更新持仓、生成一份当日交易摘要。

异常处理同样重要。我在代码里加入了“人工急停”开关,一旦系统连续出现异常决策或数据源故障,可以一键暂停所有模拟交易。这不是胆小,而是演练真实交易中必备的“熔断”意识。自动化系统跑得越久,你越需要给自己留一个确定的、可手动干预的后门。

5. 回测效果与真实模拟盘的目标差异

5.1 回测框架和参考基准

系统跑出交易记录之后,下一步就是回测验证。我用的方式比较朴素:把一套决策逻辑固定下来,在历史数据上按时间顺序回放,每一步只能用到当时时点之前的信息,禁止引入未来数据。回测区间我分成了训练段和验证段,先在一块历史上调参,再拿另一段数据做无参数调整的验证,防止过拟合。

同时我会把回测结果跟一个基准对比,不是只看“赚钱了”就高兴。如果同期基准涨了很多,而系统只赚了一点,那说明系统的超额收益可能并不存在。我的基准设置包括宽基指数和“持有不动的躺平策略”,这样能比较清楚地判断 Agent 决策是否真的增加了价值。

5.2 不只看收益率,还要看最大回撤和夏普

回测结果不能只看收益率曲线。我统计的指标包括年化收益率、最大回撤、夏普比率、胜率、盈亏比。举个我在模拟系统中的记录:某组合在验证段跑出的年化收益约 18% 左右,最大回撤控制在 11% 上下,夏普比率大约 1.4,胜率不到 60% 但盈亏比接近 1.8。这些数字只能代表该模拟配置下的历史表现,完全不构成任何真实交易建议,但它确实说明整套决策逻辑在统计学上是自洽的。

最大回撤这个指标尤其值得重视。一个年化收益 30% 但最大回撤 50% 的系统,在实际运行中会让人很难坚持执行。宁可收益低一些,也要先把回撤按住。

5.3 回测和模拟盘之间的“温差”及其原因

这里必须说一句实话:回测结果好看的策略,到了实时模拟盘不一定还能保持同样表现。我自己就遇到过几次,原因大致可以归结为三类。

一是数据延迟问题。回测时用的是调校过、无缺失的历史数据,但实时环境里行情刷新、新闻抓取都有延迟,Agent 看到的可能不是当时市场的最新状态。二是模型漂移问题。大模型的输出在不同时间段存在一定的不稳定性,同一套提示词,今天和明天对同样数据的解读可能有细微差别。三是参数过拟合问题。调参调得太细致,回测几乎步步踩在正确节奏上,但一进入真实环境就暴露了脆弱性。

正因为如此,我把整个系统视为一个实验脚手架而不是印钞机。它真正的价值是帮助验证逻辑、暴露缺陷,而不是直接上车赚钱。要经过足够长的模拟周期,观察模型在不同市场阶段下的表现,才能判断这套方法到底靠不靠谱。

6. 常见问题与避坑实录

6.1 典型问题速查表

我整理了这段时间遇到频率最高的几个问题,直接做成一张速查表。

问题现象根本原因解决方案
Agent 输出 JSON 解析失败输出截断或格式漂移增大 token 上限,解析失败自动重试,重试前明确提示“只输出 JSON”
多 Agent 观点高度雷同角色边界不清晰,信息互相渗透严格隔离上下文,分阶段传递数据
同一只股票反复做同样分析缺少结果缓存按“代码+日期”缓存分析结果,数据变化才刷新
风控规则形同虚设风控写在提示词里而非代码里把风控下沉到交易执行器,硬约束必须由代码执行
回测收益很高但模拟盘表现差数据泄漏或参数过拟合独立验证集,参数固定后不再频繁调整
API 调用成本不可控没有分层使用模型高频简单任务用小模型,深度分析才用大模型

每个问题背后都对应一个具体的实现教训,而其中最关键的一条永远是:尽早把确定性逻辑和模型能力分开。

6.2 三条最值得写进所有同类项目的经验

如果只能保留三条经验,我会选这三条。

第一,先把数据层做扎实,再铺 Agent。没有干净、稳定、可复现的数据,后面所有 Agent 的输出都是空中楼阁。数据管道的工作很枯燥,但它是整个系统最值得投入的部分。

第二,坚持写决策日志。交易日志里既要记录买卖操作,也要记录当时的研报观点、置信度、风控校验结果。没有这些沉淀,你永远说不清一个决策是怎么来的,也就谈不上优化。

第三,不要用真实资金做验证。即使是模拟盘,也要把它当成真的一样对待:设好止损、严格执行、记录每一次“该做而没做”的偏差。当你能清楚地说出系统为什么赚钱、为什么亏钱时,这套系统才真正被你看懂了。

6.3 关于 Agent 系统的运行心态

最后再分享一个实操层面的心得。Agent 系统的维护工作和传统程序不太一样,它更像是在带一个团队:需要不断校准角色的分工边界、检查数据输入质量、容忍模型偶发的“不靠谱”,但不能因为它不靠谱就完全放弃架构。我的态度是:模型负责提出判断,规则负责守住底线,数据负责提供事实。三者各司其职,系统才能长期稳定。

如果你也打算搭一套类似的股票分析模拟交易系统,建议从最小的闭环开始:先选一只股票,用一两个 Agent 跑通研报到模拟下单的流程,再逐步扩展到多股票、多角色、多策略。不要一开始就追求大而全,否则你会发现半天时间都在调试数据格式而不是改进决策逻辑。这个项目的真正价值不在于用 AI 赚了多少钱,而在于它逼着你把一套复杂决策过程拆成一个个可以验证、可以追问、可以迭代的环节。对我来说,那个把模糊想法变成清晰流水线的过程,本身就是最大的收获。

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

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

立即咨询