资讯动态

多Agent协作的股票模拟交易系统:架构设计与风控实践

发布时间:2026/10/22 19:22:17 来源:尧图企业网站定制
1. 从盯盘焦虑到多Agent协作这套模拟交易系统到底在解决什么问题做股票研究的人大概都有过这种体验早上开盘前刷一遍研报盘中盯着几个指标来回切换收盘后再复盘一遍资金流向和板块轮动一天下来信息过载真正沉淀下来的判断却没几条。更麻烦的是人的情绪会干扰决策——涨了想追跌了想割明明设好的止损位手一抖就撤了。我搭这套多Agent股票分析模拟交易系统的初衷就是想把这套信息收集—分析研判—决策执行—风险控制的流程拆解成几个各司其职的智能体让它们像一个小型投研团队一样协作而我只需要在最后做一次审核。需要先明确一点这是一个模拟交易系统所有下单动作都发生在虚拟账户里不接入任何真实券商接口也不构成任何投资建议。它的价值在于验证策略逻辑、观察Agent协作效果、积累复盘数据而不是让你躺着赚钱。如果你是想找一个自动炒股神器那这篇内容可能不适合你但如果你对多Agent架构、任务编排、风控规则引擎这些工程问题感兴趣或者想给自己的量化研究搭一个可扩展的试验台那接下来的内容应该能给你不少参考。整套系统的核心思路可以用一句话概括用多个职责单一的Agent替代一个人的多个思维角色。具体来说我设计了四个核心Agent——研报分析Agent、行情研判Agent、交易决策Agent、风控审核Agent再加上一个协调全局的调度Agent。它们之间通过结构化的消息传递协作每个Agent只关心自己那部分输入输出互不越界。这样做的好处是当某个环节出问题时我能快速定位是哪个Agent的判断逻辑有偏差而不是面对一个黑盒干瞪眼。关键词里提到的多Agent研报自主交易风控其实对应了系统的三个层次信息层负责把非结构化的研报、公告、新闻转成结构化信号决策层负责综合信号生成买卖意图执行层负责在风控约束下把意图转成模拟订单。这三层之间是单向依赖的信息层不知道决策层的存在决策层也不直接操作账户所有交易指令必须经过风控审核才能落地。这种分层设计是我踩了不少坑之后才定下来的后面会详细讲为什么。适合阅读这篇内容的人我大致分三类一是对多Agent系统感兴趣、想找个真实场景练手的开发者二是做量化研究、想给自己的策略加一层AI研判的爱好者三是对交易系统架构好奇、想了解风控模块怎么设计的技术人员。不管你属于哪一类我都建议你先把整体架构理解清楚再动手复现因为这套系统的难点不在单个Agent有多聪明而在于它们之间的协作协议和边界划分。2. 四个Agent的职责边界与协作协议设计2.1 为什么不是一个万能Agent而是四个专职Agent最开始我确实试过用一个Agent包打天下——给它一段提示词让它同时做研报解读、行情判断、下单决策和风险检查。结果很快就暴露了问题这个Agent在分析研报时表现不错但一到决策环节就开始幻觉经常编造出根本不存在的技术指标而且它的输出格式极不稳定有时候返回JSON有时候返回一段散文下游根本没法解析。更致命的是当它同时承担进攻找买点和防守控风险两个矛盾角色时往往会偏向进攻因为提示词里赚钱的诱惑太大了。拆成四个Agent之后每个Agent的提示词可以写得非常聚焦。研报分析Agent只做一件事把一段文本里的关键信息抽成结构化字段比如业绩超预期行业政策利好大股东减持这类标签再附上情绪倾向和置信度。它不需要知道当前股价是多少也不需要判断该不该买。行情研判Agent只负责看K线、均线、成交量、资金流向这些量价数据输出技术面的多空信号。交易决策Agent拿到前两者的信号后按照预设的权重和规则生成买卖意图。风控审核Agent则站在对立面专门挑刺——仓位是不是超了、单笔亏损是不是触及上限、当天交易次数是不是太频繁。这种职责单一的设计还有一个隐性好处每个Agent都可以独立替换和升级。比如我后来把研报分析Agent从规则抽取换成了大模型抽取其他三个Agent完全不用改只要保证输入输出格式不变就行。这在快速迭代阶段非常关键。2.2 Agent之间的消息格式用结构化协议代替自然语言四个Agent之间如果直接用自然语言对话很快就会乱套——A说我觉得可以买B回但是风险有点大C再插一句要不再看看最后谁也没法做决定。所以我定了一套简单的结构化消息协议所有Agent之间的通信都必须遵守。研报分析Agent的输出长这样{ agent: research_analyst, timestamp: 2025-01-15T09:30:00, signals: [ {type: earnings, sentiment: positive, confidence: 0.82, summary: 季度营收同比增长超预期}, {type: policy, sentiment: neutral, confidence: 0.65, summary: 行业新规落地短期影响有限} ], overall_score: 0.74 }行情研判Agent的输出类似但字段换成技术指标{ agent: market_analyst, timestamp: 2025-01-15T09:30:00, signals: [ {indicator: ma_cross, direction: bullish, strength: 0.7}, {indicator: volume, direction: bullish, strength: 0.6}, {indicator: rsi, direction: neutral, strength: 0.5} ], overall_score: 0.63 }交易决策Agent拿到这两个分数后按权重合成一个综合分。我目前用的权重是研报0.4、行情0.6因为模拟盘里量价信号的时效性更强。综合分超过0.7触发买入意图低于0.3触发卖出意图中间区域观望。这个阈值不是拍脑袋定的是我用历史数据回测了大概三个月才调出来的后面会讲怎么调。风控审核Agent收到的则是决策Agent的意图加上当前账户状态{ intent: {action: buy, symbol: SIM001, target_position: 0.15}, account: {total_value: 1000000, current_position: 0.08, daily_trades: 2, daily_pnl: -0.01} }它检查的规则包括单票仓位不超过20%、总仓位不超过80%、单日交易不超过5笔、单日亏损超过3%则暂停开仓。任何一条不满足意图就被打回并附上拒绝原因。只有全部通过才会生成模拟订单。2.3 调度Agent不做事只协调除了四个业务Agent还有一个调度Agent它本身不做任何分析只负责按时间顺序触发各个Agent、传递消息、记录日志。我把它单独拆出来是因为如果让业务Agent互相直接调用依赖关系会变成一张网改一个地方牵一发而动全身。有了调度Agent所有业务Agent都只跟它打交道协作流程变成一条清晰的流水线。调度逻辑用伪代码表示大概是这样def daily_workflow(symbol): research_msg research_agent.run(symbol) market_msg market_agent.run(symbol) decision decision_agent.run(research_msg, market_msg) if decision.action ! hold: approved risk_agent.review(decision, account_state) if approved: execute_simulated_order(decision) else: log_rejection(decision, approved.reason)这段逻辑看起来简单但实际跑起来要考虑的细节很多比如某个Agent超时了怎么办、返回格式不对怎么办、当天数据缺失怎么办。我的做法是给每个Agent调用加超时和重试重试两次还失败就跳过当天决策宁可错过也不做错误决策。3. 研报分析Agent把非结构化文本变成可计算的信号3.1 输入源的清洗比模型选择更重要研报分析Agent的输入主要是三类文本券商研报摘要、公司公告、行业新闻。这三类文本的质量参差不齐直接丢给模型效果很差。我做的第一件事是清洗去掉页眉页脚、免责声明、重复段落把长文本按段落切分每段控制在500字以内。这一步看起来不起眼但实测下来对抽取准确率的提升非常明显——未清洗时关键信息召回率大概只有六成清洗后能到八成五以上。清洗之后还要做一层相关性过滤。不是每段文字都值得分析比如本报告仅供参考这种句子直接丢弃。我用了一个简单的关键词白名单加黑名单机制包含营收利润订单政策产能等词的段落保留包含免责风险提示分析师声明的段落丢弃。这个规则很粗糙但胜在快且可控比再上一个模型做分类要划算。3.2 抽取字段的设计少即是多最开始我设计了二十多个抽取字段恨不得把研报里所有信息都结构化。结果发现字段越多模型越容易出错而且很多字段下游根本用不上。后来砍到六个核心字段事件类型、情绪倾向、置信度、影响周期、涉及指标、原文摘要。事件类型我限定在几个枚举值里业绩、政策、订单、产能、股东变动、其他。情绪倾向只有正面、中性、负面三档。置信度是0到1的浮点数让模型自己评估对这个判断有多确定。影响周期分短期一周内、中期一个月内、长期季度以上。涉及指标就是营收、利润、毛利率这些具体财务指标。原文摘要保留一句话方便我事后核对模型有没有瞎编。这里有个经验枚举值一定要少。我试过让模型自由输出事件类型结果它给我造出了潜在利好隐性风险这种没法归类的标签下游根本没法用。限定成六个枚举值之后输出稳定性大幅提升。3.3 用规则兜底不让模型裸奔即使提示词写得再好模型偶尔还是会抽风。我的做法是加一层规则校验如果模型输出的置信度低于0.5这条信号直接丢弃如果事件类型不在枚举范围内归入其他如果情绪倾向和原文明显矛盾比如原文说大幅下滑却标成正面用关键词规则强制纠正。这层兜底规则救过我很多次。有一次模型把一条业绩预亏的公告标成了正面原因是公告里有一句公司积极应对市场变化模型被这句话带偏了。规则校验检测到预亏这个关键词和正面情绪冲突自动改成了负面。如果没有这层校验决策Agent就会收到一个完全错误的信号。提示规则兜底不是万能的它只能处理明显的矛盾。更隐蔽的错误还是需要人工抽查。我的习惯是每周随机抽十条信号核对原文发现偏差就调整提示词或规则。4. 行情研判Agent技术指标怎么组合才不互相打架4.1 单指标失效是常态组合才有意义行情研判Agent看的是量价数据我选了四类指标均线系统MA5、MA20、MA60、成交量量比、放量缩量、动量指标RSI、MACD、资金流向大单净流入。单独看任何一个指标都会经常失效——均线金叉了但成交量没跟上RSI超卖了但趋势还在往下这些都是家常便饭。我的处理方式是给每个指标算一个方向分看多、看空、中性和一个强度分0到1然后加权合成。权重不是固定的而是根据市场状态动态调整。比如在趋势明显的行情里均线权重调高在震荡行情里RSI和资金流向权重调高。判断市场状态用的是ADX指标ADX高于25认为是趋势市低于20认为是震荡市。这个动态权重的思路来自一个很朴素的观察没有哪种指标在所有行情下都有效。与其找一个万能指标不如让系统知道现在是什么行情然后切换对应的指标组合。4.2 指标打架时的仲裁逻辑即使做了加权指标之间还是经常打架。比如均线看多、RSI看空、资金流向中性合成出来的分数在0.5附近晃悠决策Agent根本没法用。我的仲裁逻辑是当多空信号强度接近时倾向于观望。具体来说如果看多总分和看空总分的差值小于0.15就输出中性信号不参与决策。这个差值阈值是我调了很久才定下来的。阈值太小系统会频繁交易手续费和滑点吃掉利润阈值太大又会错过不少机会。最后用模拟盘跑了两个月的数据发现0.15是个比较平衡的值——交易频率适中胜率也没有明显下降。4.3 数据缺失和异常值的处理行情数据偶尔会缺失或异常比如某天成交量突然是前一天的十倍很可能是数据源出了问题而不是真的放量。我的处理规则是单日成交量超过过去20日均值5倍以上的标记为异常不参与信号计算价格数据缺失的用前一日收盘价填充但标记为低置信度。这些规则听起来琐碎但如果不处理一个异常值就可能让整个决策链跑偏。我踩过一次坑某天数据源把成交量单位搞错了放大了100倍行情Agent误判为巨量突破决策Agent直接触发买入还好风控Agent发现当天已经交易了4笔触发了频率限制才没酿成大错。从那以后我就加了异常值检测。5. 交易决策Agent从信号到意图的最后一公里5.1 权重合成与阈值触发决策Agent的核心逻辑其实不复杂把研报分和行情分按权重合成一个综合分然后跟阈值比较。但这里的每个参数都需要仔细调。我目前的配置是研报权重0.4、行情权重0.6买入阈值0.7卖出阈值0.3。这些数字不是理论推导出来的而是用历史数据回测加模拟盘实跑调出来的。调参的过程大概是这样的先固定行情权重把研报权重从0.1到0.9遍历一遍看哪个组合的模拟收益曲线最平滑然后固定研报权重调行情权重最后微调阈值。整个过程用网格搜索跑了大概两百组参数选出夏普比率最高的一组。需要说明的是历史回测表现好不代表未来也好所以我又用模拟盘跑了两个月做样本外验证确认没有明显的过拟合才定下来。5.2 仓位计算不要一把梭决策Agent不仅要决定买还是卖还要决定买多少。我的仓位计算用的是固定比例加波动率调整基础仓位是总资金的10%然后根据标的的20日波动率调整——波动率高的少买点波动率低的多买点。具体公式是target_position base_position * (target_volatility / current_volatility)其中target_volatility设为年化20%current_volatility是标的的20日年化波动率。如果算出来的仓位超过20%的上限就截断到20%。这个公式的好处是让不同波动率的标的对账户的风险贡献大致相当不会因为买了一个高波动标的就把整个账户暴露在过大风险下。5.3 决策日志为复盘留下完整证据链每次决策Agent做出判断我都会把完整的输入信号、权重、综合分、最终意图写进日志。这份日志在复盘时非常有用——当某笔模拟交易亏了钱我可以回溯到底是研报信号错了、行情信号错了还是权重配置不合理。没有这份日志复盘就只能靠猜。日志格式我用的是JSON Lines每行一条记录方便后续用脚本分析。字段包括时间戳、标的、研报分、行情分、综合分、意图、目标仓位、风控审核结果。积累几百条之后就能看出一些规律比如研报分和行情分分歧大的时候交易胜率是不是明显更低。6. 风控审核Agent站在决策Agent对立面的找茬者6.1 风控规则清单与优先级风控Agent的规则我列了六条按优先级从高到低优先级规则触发动作1单日亏损超过3%暂停当日所有开仓2单票仓位超过20%拒绝该笔买入3总仓位超过80%拒绝该笔买入4单日交易超过5笔拒绝该笔交易5单笔止损超过2%强制减仓至止损线6连续三笔亏损降低后续仓位至5%优先级的设计逻辑是越靠近保命的规则优先级越高。单日亏损限制排第一因为它直接关系到账户能不能活到明天仓位限制排第二第三控制的是风险敞口交易频率和连续亏损限制排后面属于行为约束。6.2 为什么风控必须独立于决策我见过不少系统把风控逻辑写在决策模块里用几个if-else就打发了。这样做的问题在于决策模块的目标是找到好机会风控模块的目标是避免坏结果这两个目标天然冲突。如果写在同一个模块里代码逻辑会变得非常拧巴而且很容易在优化决策效果时不小心把风控规则改松了。独立成Agent之后风控的规则可以写得很死板不需要考虑机会成本只考虑风险边界。这种死板恰恰是风控需要的品质——它不应该有这次特殊情况通融一下的灵活性。我甚至故意让风控Agent的提示词里不包含任何收益相关的信息只给它账户状态和规则清单避免它被收益诱惑。6.3 风控拒绝后的处理记录、分析、迭代风控拒绝交易不是终点而是复盘的起点。每次拒绝我都会记录拒绝原因每周统计一次各类原因的占比。如果发现某条规则频繁触发就要分析是规则太严还是决策太激进。比如有一段时间单日交易超过5笔这条规则天天触发查下来发现是行情Agent在震荡市里频繁给出弱信号决策Agent又刚好在阈值边缘反复横跳。后来我调高了震荡市的信号阈值交易频率就降下来了。这个迭代过程让我意识到风控规则不是定死的而是需要跟决策逻辑一起演进。规则太松起不到保护作用太严又会把系统管死。找到平衡点的唯一办法就是持续观察数据、持续调整。7. 模拟交易执行与账户管理让虚拟盘尽量接近真实7.1 模拟撮合的细节滑点和手续费不能忽略虽然是模拟盘但我在撮合逻辑上尽量贴近真实。买入价用当日均价加0.1%的滑点卖出价用均价减0.1%的滑点手续费按万分之三算卖出再加千分之一的印花税。这些数字加起来看起来不多但高频交易下对收益的侵蚀非常明显。我做过对比忽略滑点和手续费的模拟收益比考虑之后高出将近15%这个差距足以让一个策略从看起来能赚变成实际亏钱。撮合时机上我用的是次日开盘价成交而不是当日收盘价。因为决策Agent是基于当日收盘后的数据做判断的如果假设当日收盘就能成交就引入了未来函数回测结果会虚高。用次日开盘价虽然保守但更接近真实情况。7.2 账户状态管理持仓、成本、盈亏的实时更新账户模块维护着现金余额、持仓列表、每笔持仓的成本价和当前盈亏。每次模拟成交后这些字段都要更新。听起来简单但边界情况不少部分成交怎么算、分红送股怎么处理、停牌期间持仓怎么估值。我的做法是尽量简化——模拟盘不做部分成交要么全成要么不成分红送股暂时不处理因为模拟周期通常不长停牌期间用停牌前价格估值并标记为不可交易。这些简化会带来一些偏差但对于验证策略逻辑来说够用了。如果你要把这套系统用于更严肃的研究这些细节都需要补上。7.3 每日对账确保账实相符每天收盘后我会跑一次对账脚本检查现金余额加持仓市值是否等于初始资金加累计盈亏。这个检查看起来多余但帮我抓到过好几次bug——有一次是手续费重复扣了有一次是卖出后现金没及时回补。如果没有对账这些bug可能会潜伏很久导致模拟结果完全失真。对账脚本的逻辑很简单遍历所有成交记录重新计算一遍现金和持仓跟账户模块的当前状态对比不一致就报警。这个脚本我建议每个做模拟交易的人都写一个花不了多少时间但能省掉很多排查麻烦。8. 实跑两个月后我总结出的几条经验8.1 Agent不是越多越好边界清晰比数量重要我一开始设计了六个Agent后来砍到四个加一个调度。砍掉的两个一个是情绪分析Agent一个是宏观分析Agent。砍掉的原因不是它们没用而是它们的输出跟研报Agent高度重叠而且经常给出模棱两可的信号反而增加了决策Agent的负担。Agent的价值在于职责不可替代如果一个Agent的工作能被另一个Agent顺带完成那它就没有独立存在的必要。8.2 提示词的稳定性比聪明程度更重要研报分析Agent我换过三版提示词。第一版追求分析深入让模型自由发挥结果输出格式五花八门。第二版加了格式约束但模型经常在约束和内容之间顾此失彼。第三版把任务拆得极细每个字段单独给示例输出才稳定下来。这个过程让我明白对于要接入自动化流程的Agent输出格式的稳定性比单次分析的深度重要得多。一个格式稳定但分析浅显的Agent比一个分析深刻但格式随机的Agent有用十倍。8.3 风控规则要能说话拒绝理由必须具体风控Agent拒绝交易时如果只返回一个拒绝决策Agent和我都不知道问题出在哪。后来我要求风控返回具体的拒绝原因和触发的规则编号比如拒绝单票仓位15%加上本次拟买入8%将超过20%上限。这样决策Agent可以在下一轮调整仓位重新提交我也能在复盘时快速定位问题。可解释性是风控模块的生命线一个说不出理由的风控跟没有风控一样。8.4 模拟盘的收益曲线好看不代表策略有效最后这条可能是最重要的。模拟盘跑出漂亮收益曲线的时候人很容易飘觉得策略成了。但我后来做了个实验把决策Agent的信号随机打乱再跑一遍模拟盘居然也有不错的收益——原因是那段时间大盘整体在涨随便买什么都赚。这个实验给我泼了盆冷水也让我意识到必须用相对收益超额收益而不是绝对收益来评估策略。现在我评估策略时会同时看绝对收益、相对基准的超额收益、最大回撤、夏普比率这几个指标单看任何一个都不够。这套系统我还在持续迭代最近在尝试把研报Agent的抽取模型换成更小的本地模型降低延迟和成本也在考虑给风控Agent加一层压力测试模拟极端行情下账户的表现。如果你也在搭类似的东西我的建议是从最简单的两三个Agent开始先把协作流程跑通再逐步增加复杂度。一上来就追求大而全大概率会在调试各种边界情况中耗尽耐心。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑