简介:这是一套多智能体AI金融交易框架的完整源代码包,特别针对中文用户做了增强,适合专业投资者、量化研究人员与金融科技开发者用于学习多智能体协作在股票分析中的应用。框架依托大语言模型,通过可配置的多智能体流程完成从数据获取、分析研究到报告导出的闭环,支持A股、港股、美股等多个市场,并兼容Tushare、AKShare、BaoStock等数据源以及DeepSeek、Claude、GPT等主流大模型。包内共计2000个文件,压缩后大小约17.43MB,其中Python源码约1055个,Markdown文档约658个,此外还包含Vue前端组件、TypeScript类型文件、Shell/Bat脚本以及Docker部署配置,整体目录结构清晰,便于按模块阅读和二次开发。通过文件可完整了解前端Vue3与Element Plus界面、后端FastAPI服务、MongoDB与Redis存储方案,以及基于LangGraph和LangChain的多智能体编排实现,附带的多套启动脚本也能帮助快速搭建本地环境。已有104人学习,值得正在研究AI驱动金融决策系统的开发者深入剖析。 做量化交易好几年了,从最开始用单一策略模型在市场上“裸奔”,到后来接触多智能体AI框架,我最大的感受是:交易这行,单打独斗的时代确实在慢慢过去。哪怕你用的是最新的大模型,让它一个人既看大盘、又管仓位、还要下单风控,结果往往是顾此失彼——看对了方向,却因为仓位管理失误亏钱;或者风控设得死死的,行情来了又抓不住。于是我开始研究多智能体AI金融交易框架,把不同的任务拆分给不同的AI角色去执行,让它们各司其职、相互协作。这篇文章就基于我自己跑通的一套框架来拆解,讲一讲整体设计、核心代码、踩过的坑,以及怎么避免这些坑。
这个框架适合谁?说直白点,适合已经有Python基础、跑过简单量化策略、现在想往AI Agent方向进阶的朋友。如果你只是听说过“多智能体”这个词,还没概念,那这篇文章也能帮你建立整体认知——我会尽量把原理讲明白,不搞玄学。
1. 多智能体AI交易框架的整体设计与思路拆解
1.1 为什么交易系统需要“多智能体”而不是一个大模型
先把一个核心问题说清楚:为什么不用一个大模型把交易决策全都干了?
我在早期做过一个实验,把行情数据、持仓信息、技术指标一股脑塞给GPT-4,让它直接给出“买、卖、持有”的操作建议。结果很不稳定:有时候它分析得头头是道,有时候却犯低级错误,比如把均线金叉说成死叉,甚至忽略了我给它的仓位限制。后来我才意识到,问题不在模型本身,而在任务耦合——交易决策其实是多个子任务的组合,包括行情解读、风险度量、机会挖掘、执行纪律等等。
这就好比一家公司不能只有CEO,还得有分析师、风控官、交易员。CEO再厉害,也不可能一个人把所有环节都做到极致。多智能体框架的本质,就是把复杂的交易流程拆解成多个专业角色,每个角色由独立的大模型实例(或用不同Prompt驱动的Agent)承担,角色之间通过消息互通、相互制衡。这样做的好处有三个:
- 责任隔离:某一个Agent出错时,其他Agent可以兜底,不会让错误决策直接进入交易环节。
- 上下文聚焦:每个Agent只需要关注自己需要的信息,输入变短、输出更稳定,不会因为“上下文太长导致注意力稀释”。
- 可扩展性强:想加一个新策略维度,比如舆情分析,只需加一个Agent,不用重写整个系统。
1.2 多智能体的四种交互模式与交易场景的对应关系
近段时间AI Agent圈子里经常聊“多智能体的四种交互模式”,我在设计交易框架时也对号入座了:
| 交互模式 | 交易系统里的体现 |
|---|---|
| 协作模式(Collaboration) | 多个Agent分工处理同一任务的不同部分,比如行情Agent负责数据,风控Agent负责仓位,执行Agent负责下单 |
| 竞争模式(Competition) | 多个Agent给出不同建议,由仲裁机制选出最优方案,比如多头Agent和空头Agent同时分析,最终投票决定 |
| 层级模式(Hierarchy) | 上级Agent做任务分解,下级Agent执行并反馈结果,比如决策Agent分配任务给数据Agent、风控Agent |
| 递归模式(Recursive) | Agent把复杂任务拆解为更小的子任务,不断调用自身或子Agent完成深度分析 |
实际交易系统里,最常用的是协作模式和层级模式的混合体。我的框架中,主控Agent负责统筹,市场分析Agent、风险管理Agent、交易执行Agent各司其职,而风险管理Agent对交易执行Agent有“一票否决权”——这本质上就是层级关系里的制衡机制。竞争模式通常用在更复杂的策略研究里,比如多种因子模型互相PK,但实时交易场景下,竞争模式的延迟成本太高了,一般不做首选。
1.3 一个功能完备的框架应该包含哪些模块
从工程实现角度,一套能真正跑起来的框架至少需要四个模块:
- 数据层:负责拉取行情数据、处理K线、技术指标计算。可以是真实行情源,也可以是回测数据。
- 决策层:多个Agent核心逻辑所在地,每个Agent有自己的角色设定、输入输出格式、决策逻辑。
- 通信层:Agent之间的消息渠道。最简单的实现是共享内存加消息队列,也可以用框架自带的通信机制。
- 执行层:对最终决策做订单生成、仓位计算、虚拟撮合(回测)或实盘接口对接。
2. 核心细节解析与实操要点
2.1 每个Agent的职责边界与输入输出设计
多智能体系统最容易翻车的点,就是Agent的职责边界设计不到位。如果你的每个Agent什么都能干,那和单个大模型就没有本质区别了。我的设计原则是“单职单责”,每个Agent只做一件事,但要做到极致。
拿我的框架来说,核心Agent有三类:
- 市场分析Agent(MarketAgent):只负责解读当前行情状态,输入是K线数据、技术指标(RSI、MACD、布林带等),输出是一个结构化的市场观点,比如“趋势向上,短期回调风险中等”,并附上置信度。
- 风险管理Agent(RiskAgent):只负责评估“当前这笔交易能亏多少”,输入是当前持仓、波动率、账户净值,输出是最大可接受仓位比例。它不对行情做任何预测。
- 交易执行Agent(ExecutionAgent):负责把分析意见和风控限额转化为具体订单。输入是市场观点、仓位限额、当前价格,输出是具体的交易动作(买入/卖出/持有)、数量和价格类型。
这三者之间通过一个协调器(Coordinator)串起来,协调器是框架的“心脏”,它决定调用顺序、处理各Agent的反馈、最终确认动作。
2.2 技术栈选型:LangGraph还是自研Pipeline
多智能体框架的搭建,目前主流有两条路:一是用现成的编排框架,比如LangGraph、AutoGen、CrewAI;二是完全自己写Pipeline。两种方案我都试过,各有取舍。
用LangGraph的好处是,它天然支持图结构的任务编排,Agent之间的状态管理和条件跳转很方便,适合复杂工作流。缺点是抽象层比较重,学习成本高,而且调试的时候,你很难直观看到“到底哪个Agent在什么时间说了什么”。对于金融这种对确定性要求很高的场景,可观测性非常重要。
自研Pipeline的好处是逻辑透明,你清楚每一步数据怎么流转,出了问题好排查。缺点是重复造轮子,消息通信、状态管理都得自己写。我最终选择的是“半自研”方案:核心通信用Python的asyncio.Queue实现,Agent之间的消息走队列,状态的传递用共享的DataFrame结构,整体足够轻量,又保留了灵活的扩展空间。
2.3 Agent的Prompt设计——这里决定了系统的“智商”
很多人低估了Prompt设计在多智能体系统里的重要性。每个Agent的效果,80%由它的System Prompt决定。我前前后后迭代了几十版Prompt,总结了几个关键原则:
- 角色定义必须具体到“决策边界”。比如RiskAgent的Prompt里我会写:“你是风控经理,你的职责是控制最大回撤,你没有权限直接买卖股票,但你可以在信号危险时输出SELL建议,这个建议会覆盖市场分析Agent的建议。”边界不清晰,Agent就会越权做其他角色的事。
- 输出结构化,强制JSON格式。如果让Agent输出自然语言,后续解析就非常痛苦。我会在Prompt里明确输出schema,要求返回标准的JSON对象,包含
action、confidence、reason字段。 - 给它上下文不是越多越好。太多历史K线数据反而会让模型迷失重点。我一般只给最近20根日线和当前关键指标值,让Agent做“快照式判断”,而不是让它看完整长周期。
3. 实操过程与核心环节实现
3.1 基础代码骨架:Agent基类和消息队列
下面我直接给出一个可跑的简化版本,用Python实现。完整版还涉及数据源和策略细节,这里把最关键的部分拆开讲。
第一步是定义Agent基类和消息通信模块。我统一用asyncio.Queue做消息中间件,每个Agent从自己的队列里取消息,处理完把结果发给下一个Agent的队列。
import asyncio import json from abc import ABC, abstractmethod class BaseAgent(ABC): def __init__(self, name): self.name = name self.inbox = asyncio.Queue() self.outbox = asyncio.Queue() @abstractmethod async def process(self, message): pass async def run(self): while True: msg = await self.inbox.get() if msg.get("type") == "STOP": break result = await self.process(msg) if result: await self.outbox.put(result) async def send(self, recipient_agent, message): await recipient_agent.inbox.put(message)这个基类每个Agent都会继承。run方法是一个无限循环,监听自己的inbox队列,处理完消息后,把结果放到outbox。外部协调器会决定把outbox的消息发送给谁。
3.2 市场分析Agent的实现
接下来是一个简化版的市场分析Agent,它会接收最新的K线数据和技术指标,然后调用大模型生成结构化观点。
import pandas as pd import json from openai import AsyncOpenAI class MarketAgent(BaseAgent): def __init__(self, name, llm_client, model="gpt-4o-mini"): super().__init__(name) self.llm = llm_client self.model = model async def process(self, message): if message["type"] == "ANALYZE_MARKET": df = message["data"]["df"] indicators = message["data"]["indicators"] # 构造给LLM的上下文 recent_df = df.tail(20).to_string() prompt = f""" 你是市场分析Agent。请根据以下技术指标和最近K线数据,输出市场趋势判断。 K线数据: {recent_df} 当前指标: - RSI: {indicators['rsi']:.2f} - MACD: {indicators['macd']:.4f} - 布林带上轨: {indicators['bb_upper']:.2f} - 布林带下轨: {indicators['bb_lower']:.2f} 只输出JSON格式,格式如下: {{ "trend": "up/down/sideways", "strength": 0-100, "confidence": 0-1, "summary": "一句话总结" }} """ resp = await self.llm.chat.completions.create( model=self.model, response_format={"type": "json_object"}, messages=[ {"role": "system", "content": "你是专业的技术分析师,输出严格遵循用户要求的JSON格式。"}, {"role": "user", "content": prompt} ] ) result = json.loads(resp.choices[0].message.content) return { "type": "MARKET_ANALYSIS_DONE", "agent": self.name, "data": result } return None这段代码有几个细节值得注意:
response_format={"type": "json_object"},这是强制OpenAI返回JSON格式的方法,能大幅减少解析出错概率。实测没有这个参数时,偶尔会出现多余文字。- 只取最近20根K线,是为了控制输入长度,让模型聚焦在近期行情上,避免历史噪音。
- 返回结果带
type字段,这是消息路由的关键标识,协调器根据这个字段决定消息往哪儿发。
3.3 风险管理Agent与执行Agent的联动
风险管理Agent的输入是账户净值、当前持仓、历史波动率。它的核心逻辑是计算一个“最大允许仓位比例”。我一开始用的是固定公式,比如“单笔风险不超过账户净值的1%”,但后来发现把波动率加进去更合理——波动大的时候低仓位,波动小的时候可以适当放大仓位,这就是著名的波动率目标策略。
import numpy as np class RiskAgent(BaseAgent): def __init__(self, name, max_drawdown=0.1): super().__init__(name) self.max_drawdown = max_drawdown async def process(self, message): if message["type"] == "CALCULATE_RISK": equity = message["data"]["equity"] position = message["data"]["position"] volatility = message["data"]["volatility"] # 波动率目标:设定目标年化波动率15%,反推仓位 target_vol = 0.15 annual_vol = volatility * np.sqrt(252) if annual_vol == 0: max_position = 1.0 else: max_position = max(0, min(1.0, target_vol / annual_vol)) # 最大回撤限制:如果接近回撤上限,强制减仓 drawdown = message["data"].get("drawdown", 0) if drawdown > self.max_drawdown * 0.8: max_position *= 0.5 return { "type": "RISK_CHECK_DONE", "agent": self.name, "data": {"max_position": max_position} } return None这个RiskAgent的逻辑思路是,账户的杠杆比率跟波动率成反比。比如现在年化波动率20%,而目标波动率是15%,那仓位就应该控制在0.75倍以下。这个思路在全天候策略、风险平价策略里都很常用。加上回撤限制之后,系统在极端行情下会自动降杠杆,这是保护账户的关键一公里。
3.4 协调器:把Agent串成一条流水线
协调器是整个框架里唯一的“上帝视角”。它的职责是:触发信号、调用Agent、汇总结果、决定最终动作。这里我用一个简化示意来说明它的工作流程。
class Coordinator: def __init__(self, market_agent, risk_agent, exec_agent): self.market_agent = market_agent self.risk_agent = risk_agent self.exec_agent = exec_agent async def run_cycle(self, df, indicators, equity, position, volatility, drawdown): # Step1: 市场分析 market_result = await self.market_agent.process({ "type": "ANALYZE_MARKET", "data": {"df": df, "indicators": indicators} }) print(f"[市场Agent] {market_result['data']['summary']}") # Step2: 风险评估 risk_result = await self.risk_agent.process({ "type": "CALCULATE_RISK", "data": { "equity": equity, "position": position, "volatility": volatility, "drawdown": drawdown } }) max_position = risk_result["data"]["max_position"] print(f"[风控Agent] 最大仓位建议: {max_position:.2%}") # Step3: 执行决策 exec_result = await self.exec_agent.process({ "type": "GENERATE_ORDER", "data": { "market": market_result["data"], "max_position": max_position, "current_position": position, "equity": equity, "price": df["close"].iloc[-1] } }) return exec_result这里有一个比较微妙的设计:执行Agent在生成订单前,必须把市场分析结果和风控限额同时纳入考量。如果市场Agent说“强烈看涨”,但风控Agent只给了0.2倍的仓位上限,那执行Agent只能用小仓位进场,而不是放弃交易。这就实现了“分析归分析,风险归风险”的隔离逻辑。
3.5 大模型参数配置:温度、上下文长度与成本控制
金融场景下大模型的调用参数不能随便设。我实测下来的经验值如下:
| 参数 | 推荐值 | 原因 |
|---|---|---|
| temperature | 0.2~0.3 | 交易决策要的是稳定性,不是创造性。温度调高会出现同一个信号不同决策的问题 |
| max_tokens | 200~500 | Agent输出是结构化JSON,不需要长篇大论,限制token能降低成本和延迟 |
| top_p | 0.9 | 在保持稳定性和语义多样性之间取平衡 |
| 上下文窗口 | min(8000, 实际量) | 金融场景不需要长上下文,给多了反而分散注意力 |
成本方面,如果按每天交易20个标的、每标的每轮3次LLM调用计算,用gpt-4o-mini模型,每天大约消耗3000~5000个输入token和1000~2000个输出token,成本在小几美元以内,个人投资者完全可以承受。如果用更大的模型如claude-3.5-sonnet或者gpt-4o,成本会上涨7~10倍,回测阶段建议先用小模型验证逻辑,实盘再视情况加大。
4. 常见问题与排查技巧实录
4.1 问题一:Agent之间上下文信息丢失
多智能体系统最常见的坑,就是Agent之间传递数据时,用了字典结构但没有定义好key命名。刚开始我遇到过,市场Agent明明输出了trend字段,结果执行Agent把它当成signal字段来读,直接导致order为空。这种问题最好的排查手段,是在每个Agent的process方法入口处打印收到的message,写日志。我后期给框架加了一个LoggingMiddleware,每次消息进出都记录到数据库,再跑回测就不怕找不到谁出问题了。
4.2 问题二:LLM响应延迟导致错过行情
实时行情交易中,一个很大的痛点是LLM推理时间太长。单次调用OpenAI接口,最快也要1~3秒,再加上网络波动,一个交易周期可能耗时5~10秒。对于分钟级甚至秒级策略来说,这个延迟是不可接受的。我有两个解决办法:
- 把交易周期拉长到15分钟或小时级别,给LLM充足的反应时间。
- 引入“预判缓存”机制:在信号发生前,先异步触发Agent分析,等K线收盘时直接取结果。实际测试中,这种方式能把决策延迟从3秒压缩到100毫秒以内。
4.3 问题四:幻觉——AI“编造”技术指标
大模型幻觉是金融AI绕不开的话题。我在测试中发现,当Prompt里给Agent的指标数据不完整时,它有时会“脑补”一个RSI值,甚至输出一个本来不存在的金叉信号。解决手段有两个:一是用代码在输入侧做校验,确保传入的指标数据是最新计算出来的,而不是来自已有上下文;二是在Agent的system prompt里强调“如果数据缺失,必须输出data_incomplete,禁止猜测”。
4.4 决策冲突与仲裁机制
当多个Agent意见不一致的时候,比如市场Agent强烈看多,但风险Agent因为回撤问题要求清仓,这时候谁来拍板?我的做法是:给每个Agent定义不同的“否决权级别”。RiskAgent拥有最高优先级的否决权,它的输出直接覆盖MarketAgent的结论。这是风控优先原则。其次才是交易结果,如果市场信号和风控限额冲突,执行Agent只能做一个“减仓”或“空仓”决定,不能逆风控而行。
4.5 回测环境与实盘的差异问题
最后一条是回测框架的坑。很多人在回测里跑得很漂亮,一上实盘就崩,原因往往在于回测时没模拟真实的滑点和手续费。我的建议是:回测环境里至少加入“买卖价差+单边0.1%手续费+最小成交单位”这三个约束,别把代码写得太理想。我自己就吃过亏,回测年化20%的策略,实盘跑下来只有8%,主要就是滑点吃掉了大量利润。
5. 一点实操体会
多智能体AI金融交易框架,本质上不是“用一个更聪明的大模型”,而是“把交易问题拆成多个可验证的环节,每个环节用最合适的模型和逻辑去解决”。拆完之后,整个系统的透明度大大提升,哪个环节出了问题,直接看那个Agent的日志就行,这是单一大模型做不到的。
我个人的体会是,如果你想入门这个方向,千万别一上来就搞复杂架构。先用最简单的方式搭一个三Agent的闭环——一个看盘、一个算风险、一个下单——跑通再逐步迭代。这个过程中你最大的收获不是那个最终的收益数字,而是对“AI Agent在真实决策场景下边界在哪里”的理解。
最后再分享一个小技巧:把你每次Agent的输入输出都留档保存。隔一段时间复盘,你会发现哪些Prompt设计让Agent在特定行情下表现得特别好,哪些历史案例是它的盲区。这些一手数据,比任何论文和课程都值钱。
本文还有配套的精品资源,点击获取