
1. 从单打独斗到团队作战TradingAgents到底在解决什么问题量化交易这个圈子有个很有意思的现象策略研究员花三个月打磨出来的因子模型实盘跑两周就失效回测曲线漂亮得像艺术品一上模拟盘就原形毕露。问题出在哪大多数时候不是模型不够复杂而是整个决策链条太脆弱——一个模型既要判断趋势又要评估风险还得决定仓位最后还要择时进出。这就像让一个刚毕业的实习生同时干交易员、风控总监和基金经理的活不出事才怪。TradingAgents这个框架的核心思路就是把量化交易从“单模型包打天下”变成“多智能体分工协作”。它基于LangGraph构建用LLM驱动的多个Agent分别扮演基本面分析师、技术面分析师、情绪分析师、研究员、交易员和风控经理等角色每个Agent只负责自己最擅长的环节最后通过一套结构化的协作机制汇总成交易决策。这套东西适合谁看如果你正在做量化策略开发或者对多智能体系统在金融场景的落地感兴趣又或者你单纯想搞清楚LangGraph到底怎么用来搭一个真实可用的Agent系统那这篇内容应该能给你不少可直接抄作业的细节。我第一次接触这个框架的时候最直观的感受是它把“交易决策”这件事拆得足够细细到每个环节都可以独立优化、独立回测、独立替换。这跟传统量化框架的思路完全不同——传统框架追求的是端到端的信号生成而TradingAgents追求的是决策过程的模块化和可解释性。这个区别很关键因为它直接决定了你后续能不能快速定位问题、迭代策略。2. 多智能体协作的架构设计为什么这么拆2.1 核心Agent角色划分与职责边界TradingAgents的Agent划分不是拍脑袋决定的它对应的是真实交易团队里的岗位分工。我把它拆成四层来看会更清楚第一层分析师团队Analyst Team基本面分析师负责拉取财报数据、估值指标、行业对比输出的是“这家公司值不值得关注”的判断。它调用的工具通常是财务数据API和新闻摘要接口。技术面分析师盯着K线形态、均线系统、成交量变化、MACD/RSI等指标输出的是“当前价格走势处于什么阶段”的判断。情绪分析师抓取社交媒体讨论热度、新闻情感倾向、分析师评级变化输出的是“市场情绪偏多还是偏空”的判断。新闻分析师专门处理宏观事件、行业政策、公司公告输出的是“近期有没有重大事件会影响价格”的判断。这四个分析师各跑各的互不干扰。为什么要这么设计因为如果你让一个模型同时看财报和K线它很容易被其中一种信息带偏。分开之后每个Agent的prompt可以写得非常聚焦输出的质量会稳定很多。第二层研究员团队Researcher Team研究员分两个角色看多研究员和看空研究员。这两个Agent会分别拿到分析师团队的输出然后各自站在多头和空头的立场上展开辩论。看多研究员会强调所有利好因素看空研究员会放大所有风险点。这个设计非常巧妙——它模拟了真实投研团队里的多空辩论机制通过对抗性讨论来暴露决策盲区。第三层交易员AgentTrader Agent交易员拿到研究员辩论的汇总结果结合当前持仓状态和市场流动性情况输出具体的交易提案买还是卖、买多少、什么价格区间、止损止盈设在哪。这个Agent的prompt里通常会嵌入一套仓位管理规则比如单笔风险不超过总资金的2%。第四层风控与组合管理Risk Manager Portfolio Manager风控经理会从多个维度评估交易提案的风险敞口行业集中度、单票仓位上限、最大回撤容忍度、流动性冲击成本。组合经理则负责最终拍板决定是否执行交易提案以及如何在多个标的之间分配资金。注意Agent的数量不是越多越好。我见过有人把Agent拆到十几个结果每个Agent拿到的上下文都碎片化反而导致决策质量下降。TradingAgents的这套划分之所以有效是因为每个角色的输入输出边界非常清晰信息在Agent之间的流转是有向无环的。2.2 为什么选LangGraph而不是LangChain这是被问得最多的问题之一。LangChain和LangGraph的区别用一句话说就是LangChain适合做线性的链式调用LangGraph适合做有状态、有分支、有循环的图结构编排。量化交易决策天然就是一个图结构——分析师并行跑研究员辩论可能来回好几轮风控可能打回交易提案要求修改这些都不是线性链能表达的。LangGraph的几个核心概念在这里用得恰到好处StateGraph整个决策流程的状态机每个节点是一个Agent边定义了状态流转的条件。State一个共享的字典结构所有Agent的输入输出都往里面读写。TradingAgents里State通常包含市场数据快照、各分析师的报告、研究员辩论记录、交易提案、风控意见、最终决策。Conditional Edge条件边用来实现“如果风控不通过就回到交易员重新生成提案”这种循环逻辑。Checkpoint检查点机制支持中断后恢复这对长时间运行的交易决策流程很重要。我实测下来LangGraph的State管理机制比LangChain的Memory系统要清晰得多。LangChain的Memory经常出现上下文丢失或者串台的问题而LangGraph的State是显式定义的每个节点读写哪些字段一目了然调试起来方便很多。2.3 数据流与决策链路设计整个决策链路的数据流是这样的市场数据层拉取OHLCV、财报、新闻、社交媒体数据写入State的market_data字段。四个分析师Agent并行执行各自读取market_data把分析报告写入State的analyst_reports字段。看多和看空研究员分别读取analyst_reports进行第一轮辩论把论点写入debate_history。如果辩论轮次未达到预设上限通常2-3轮两个研究员继续读取对方的论点进行反驳。交易员读取debate_history和当前持仓状态生成交易提案写入trade_proposal。风控经理读取trade_proposal评估风险后写入risk_assessment。如果不通过条件边会把流程打回交易员。组合经理读取所有信息输出最终决策final_decision。这个链路里有一个很关键的设计所有Agent之间的通信都是通过State结构化的而不是通过自然语言对话。这意味着每个Agent的输出格式是固定的下游Agent解析起来不会出现歧义。这一点在实盘环境里特别重要——你不能指望LLM每次都能输出格式完全一致的JSON所以TradingAgents在每个Agent的输出层都加了格式校验和重试机制。3. 核心模块拆解与实操配置3.1 环境搭建与依赖安装先把基础环境跑起来。Python版本建议3.10以上低于这个版本有些LangGraph的特性不支持。# 创建虚拟环境 python -m venv trading_agents_env source trading_agents_env/bin/activate # Windows用 trading_agents_env\Scripts\activate # 安装核心依赖 pip install langgraph langchain langchain-openai langchain-community pip install pandas numpy yfinance ta-lib pip install fastapi uvicorn # 如果要暴露API接口这里有个坑要注意ta-lib这个技术指标库在Windows上安装经常出问题因为它依赖C语言库。我的建议是直接用pandas-ta替代纯Python实现安装零痛苦pip install pandas-taLLM的选择上TradingAgents默认支持OpenAI的模型但实际用下来如果你要做高频决策GPT-4o-mini的性价比最高如果做日线级别的策略GPT-4o或者Claude 3.5 Sonnet的输出质量更稳定。温度参数建议设在0.1-0.3之间太高了输出会飘太低了又缺乏灵活性。from langchain_openai import ChatOpenAI llm ChatOpenAI( modelgpt-4o-mini, temperature0.2, max_tokens2000, timeout30, max_retries3 )提示LLM的API调用一定要加超时和重试。实盘环境里网络抖动是常态没有重试机制的话一个Agent卡住整个决策链路就断了。3.2 State结构定义与Agent基类State是整个框架的骨架定义得好不好直接决定了后续扩展的难易程度。我参考TradingAgents的设计把State定义成这样from typing import TypedDict, Annotated, List, Dict, Optional from langgraph.graph import add_messages class TradingState(TypedDict): # 市场数据 ticker: str market_data: Dict news_data: List[Dict] social_data: List[Dict] # 分析师报告 fundamental_report: Optional[str] technical_report: Optional[str] sentiment_report: Optional[str] news_report: Optional[str] # 研究员辩论 debate_history: Annotated[List[Dict], add_messages] debate_round: int # 交易决策 trade_proposal: Optional[Dict] risk_assessment: Optional[Dict] final_decision: Optional[Dict] # 元信息 messages: Annotated[List, add_messages] error_log: List[str]这里用Annotated配合add_messages是为了让LangGraph自动处理消息的追加逻辑不用手动维护列表。debate_round用来控制辩论轮次防止无限循环。Agent基类的设计上我建议每个Agent都继承同一个基类统一处理LLM调用、格式校验和错误重试class BaseAgent: def __init__(self, llm, system_prompt: str, output_schema: dict): self.llm llm self.system_prompt system_prompt self.output_schema output_schema def invoke(self, state: TradingState) - dict: prompt self._build_prompt(state) for attempt in range(3): try: response self.llm.invoke([ {role: system, content: self.system_prompt}, {role: user, content: prompt} ]) parsed self._parse_output(response.content) return parsed except Exception as e: if attempt 2: return {error: str(e)} continue这个基类里最关键的是_parse_output方法。LLM返回的JSON经常会有格式问题——多一个逗号、少一个引号、或者干脆在JSON外面包了一层markdown代码块。我的处理方式是先用正则把JSON提取出来再用json.loads解析失败的话用json_repair库兜底import json import re from json_repair import repair_json def _parse_output(self, content: str) - dict: # 去掉markdown代码块标记 content re.sub(rjson\s*|\s*, , content) # 提取JSON部分 match re.search(r\{.*\}, content, re.DOTALL) if match: try: return json.loads(match.group()) except json.JSONDecodeError: return json.loads(repair_json(match.group())) raise ValueError(No valid JSON found in response)3.3 分析师Agent的Prompt工程细节分析师Agent的输出质量直接决定了整个决策链路的上限。我踩过的坑是prompt写得太笼统Agent会输出一堆正确的废话。比如你问“当前技术面怎么样”它可能回你“根据MACD和RSI指标当前市场处于震荡状态”——这种输出对交易决策毫无价值。有效的做法是给每个分析师Agent设定明确的输出模板和判断标准。以技术面分析师为例TECHNICAL_ANALYST_PROMPT 你是一名资深技术分析师负责对{ticker}进行技术面分析。 请基于以下数据进行分析 - 近60日OHLCV数据 - 当前均线系统MA5/MA20/MA60 - MACD、RSI、布林带指标值 - 成交量变化趋势 输出要求严格按JSON格式 {{ trend: 上升/下降/震荡, trend_strength: 强/中/弱, key_levels: {{ support: [支撑位1, 支撑位2], resistance: [阻力位1, 阻力位2] }}, indicators: {{ macd_signal: 金叉/死叉/中性, rsi_value: 数值, rsi_signal: 超买/超卖/中性, volume_signal: 放量/缩量/平量 }}, summary: 一句话总结技术面判断, confidence: 0.0-1.0 }} 这个prompt里有几个关键设计第一明确列出了输入数据的具体内容避免Agent去“猜”第二输出格式是结构化的JSON下游Agent可以直接解析第三加了confidence字段让Agent自己评估判断的置信度这个值后续可以用来做加权。情绪分析师的prompt又不一样它需要处理的是非结构化文本SENTIMENT_ANALYST_PROMPT 你是一名市场情绪分析师负责评估{ticker}当前的市场情绪。 输入数据包括 - 近3日社交媒体提及量和情感倾向 - 近5条相关新闻标题及摘要 - 分析师评级变化上调/下调/维持 分析要求 1. 统计正面/负面/中性提及的比例 2. 识别情绪极端值如恐慌性抛售或FOMO买入 3. 判断情绪是否与价格走势背离 输出JSON格式 {{ sentiment_score: -1.0到1.0, sentiment_label: 极度悲观/悲观/中性/乐观/极度乐观, mention_volume_change: 上升/下降/持平, divergence_detected: true/false, key_narratives: [主要叙事1, 主要叙事2], summary: 一句话总结 }} 实操心得情绪分析最容易出现的问题是LLM对反讽和隐喻的误判。比如“这股票真是稳如泰山”在特定语境下可能是反话。我的处理方式是在prompt里明确要求Agent对每条文本标注“字面情感”和“实际情感”如果两者不一致就标记为“需人工复核”。3.4 研究员辩论机制的具体实现研究员辩论是TradingAgents里最有意思的部分。它的实现逻辑是看多和看空两个Agent轮流发言每一轮都要针对对方的论点进行反驳。class BullResearcher(BaseAgent): def invoke(self, state: TradingState) - dict: # 获取所有分析师报告 reports { fundamental: state[fundamental_report], technical: state[technical_report], sentiment: state[sentiment_report], news: state[news_report] } # 获取上一轮辩论记录 last_bear_argument if state[debate_history]: last_bear_argument state[debate_history][-1].get(bear_argument, ) prompt f 你是看多研究员。基于以下分析师报告构建看多论据。 分析师报告{json.dumps(reports, ensure_asciiFalse)} 看空方上一轮论点{last_bear_argument} 要求 1. 列出3个最强看多理由 2. 逐条反驳看空方论点 3. 给出目标价区间和置信度 输出JSON {{ bull_arguments: [论据1, 论据2, 论据3], rebuttals: [反驳1, 反驳2], target_price: [下限, 上限], confidence: 0.0-1.0 }} return self._parse_output(self.llm.invoke(prompt).content)辩论轮次的控制在LangGraph的条件边里实现def should_continue_debate(state: TradingState) - str: if state[debate_round] 3: return trader if state[debate_round] 1: # 检查双方论点是否还有实质性分歧 last_round state[debate_history][-1] if last_round.get(consensus_reached, False): return trader return continue_debate这里有个经验辩论轮次不是越多越好。我实测下来2-3轮是最优的。超过3轮之后两个Agent开始重复之前的论点边际信息量急剧下降反而浪费token。4. 实操全流程从数据拉取到决策输出4.1 数据层配置与API选型量化交易的数据源选择是个老生常谈的问题。我的建议是分层配置数据类型推荐方案备选方案更新频率日线OHLCVyfinance免费Alpha Vantage每日收盘后分钟级数据Polygon.io聚宽/米筐实时财报数据Financial Modeling Prep东方财富API季度新闻数据NewsAPI新浪财经爬虫实时社交媒体Reddit API雪球/股吧爬虫实时yfinance虽然免费但有两个坑一是偶尔会返回空数据需要加重试二是它的复权处理有时候不准确做回测的时候要注意。我的做法是在数据层加一层校验import yfinance as yf import pandas as pd def fetch_market_data(ticker: str, period: str 6mo) - pd.DataFrame: for attempt in range(3): try: df yf.download(ticker, periodperiod, progressFalse) if df.empty: raise ValueError(fEmpty data for {ticker}) # 校验数据完整性 if df[Close].isna().sum() len(df) * 0.1: raise ValueError(Too many NaN values) return df except Exception as e: if attempt 2: raise time.sleep(2 ** attempt) # 指数退避4.2 LangGraph图的构建与编译把前面定义的Agent和State组装成完整的图from langgraph.graph import StateGraph, END def build_trading_graph(): workflow StateGraph(TradingState) # 添加节点 workflow.add_node(fetch_data, fetch_data_node) workflow.add_node(fundamental_analyst, fundamental_analyst_node) workflow.add_node(technical_analyst, technical_analyst_node) workflow.add_node(sentiment_analyst, sentiment_analyst_node) workflow.add_node(news_analyst, news_analyst_node) workflow.add_node(bull_researcher, bull_researcher_node) workflow.add_node(bear_researcher, bear_researcher_node) workflow.add_node(trader, trader_node) workflow.add_node(risk_manager, risk_manager_node) workflow.add_node(portfolio_manager, portfolio_manager_node) # 定义边 workflow.set_entry_point(fetch_data) # 数据拉取后并行进入四个分析师 workflow.add_edge(fetch_data, fundamental_analyst) workflow.add_edge(fetch_data, technical_analyst) workflow.add_edge(fetch_data, sentiment_analyst) workflow.add_edge(fetch_data, news_analyst) # 四个分析师汇聚到研究员辩论 workflow.add_edge(fundamental_analyst, bull_researcher) workflow.add_edge(technical_analyst, bull_researcher) workflow.add_edge(sentiment_analyst, bear_researcher) workflow.add_edge(news_analyst, bear_researcher) # 辩论循环 workflow.add_conditional_edges( bull_researcher, should_continue_debate, {continue_debate: bear_researcher, trader: trader} ) workflow.add_conditional_edges( bear_researcher, should_continue_debate, {continue_debate: bull_researcher, trader: trader} ) # 交易决策链路 workflow.add_edge(trader, risk_manager) workflow.add_conditional_edges( risk_manager, should_approve_trade, {approved: portfolio_manager, rejected: trader} ) workflow.add_edge(portfolio_manager, END) return workflow.compile(checkpointerMemorySaver())这里有个细节checkpointer参数一定要加。LangGraph的检查点机制可以在流程中断后从上次的状态恢复这对长时间运行的交易决策流程非常关键。比如你跑了三个小时的分析结果在风控环节网络断了没有检查点的话就得从头再来。4.3 交易员Agent的仓位计算逻辑交易员Agent的输出不能只是“买”或“卖”必须包含具体的仓位计算。我用的是一套基于凯利公式变体的仓位管理方法def calculate_position_size( confidence: float, win_rate: float, risk_reward_ratio: float, total_capital: float, max_risk_per_trade: float 0.02 ) - dict: # 凯利公式f (p * b - q) / b # p 胜率, q 1-p, b 盈亏比 p win_rate q 1 - p b risk_reward_ratio kelly_fraction (p * b - q) / b if b 0 else 0 # 用置信度调整凯利比例 adjusted_fraction kelly_fraction * confidence # 限制单笔最大风险 adjusted_fraction min(adjusted_fraction, max_risk_per_trade) # 计算具体金额 position_value total_capital * adjusted_fraction return { position_fraction: round(adjusted_fraction, 4), position_value: round(position_value, 2), kelly_raw: round(kelly_fraction, 4), confidence_adjusted: round(adjusted_fraction, 4) }这个计算过程要写进交易员Agent的prompt里让LLM在生成交易提案时直接调用。实测下来加了仓位计算之后交易提案的可执行性提升非常明显——之前LLM经常给出“建议买入”这种没有具体仓位的模糊建议现在它会输出“建议买入总资金的1.8%对应金额18,000元止损设在支撑位下方2%”。4.4 风控Agent的多维度评估风控Agent的评估维度我设计了六个RISK_MANAGER_PROMPT 你是一名风控经理负责评估以下交易提案的风险。 交易提案{trade_proposal} 当前组合状态{portfolio_state} 市场环境{market_conditions} 请从以下六个维度评估风险每个维度1-5分5分最高风险 1. 单票集中度风险该标的市值占比是否超过组合的20% 2. 行业集中度风险该标的所属行业占比是否超过组合的40% 3. 流动性风险日均成交额是否足够覆盖计划仓位 4. 波动率风险当前隐含波动率是否处于历史高位 5. 相关性风险该标的与现有持仓的相关性是否过高 6. 事件风险近期是否有财报、解禁、政策等事件 输出JSON {{ risk_scores: {{ concentration: 分数, sector: 分数, liquidity: 分数, volatility: 分数, correlation: 分数, event: 分数 }}, total_risk_score: 加权总分, decision: 通过/有条件通过/拒绝, conditions: [条件1, 条件2], reasoning: 评估理由 }} 风控的阈值设定上我的经验是总分低于2.5直接通过2.5-3.5有条件通过比如要求降低仓位高于3.5直接拒绝。这个阈值可以根据你的风险偏好调整但不要设得太松否则风控就形同虚设了。5. 常见问题与排查技巧实录5.1 LLM输出格式不稳定的修复方案这是最高频的问题。LLM返回的JSON格式错误主要有几种表现问题类型具体表现修复方案多余文本JSON前后有解释性文字正则提取{...}尾随逗号最后一个字段后多逗号json_repair库引号缺失key或value没有引号预处理替换嵌套错误括号不匹配栈校验重试类型错误数字被写成字符串Pydantic校验我的标准处理流程是三层防御第一层用正则提取JSON块第二层用json_repair修复常见语法错误第三层用Pydantic做类型校验。如果三层都失败就触发LLM重试并在prompt里加上“上次输出格式有误请严格按JSON格式输出”的提示。from pydantic import BaseModel, ValidationError class TradeProposal(BaseModel): action: str position_fraction: float entry_price: float stop_loss: float take_profit: float reasoning: str def validate_proposal(raw: dict) - TradeProposal: try: return TradeProposal(**raw) except ValidationError as e: raise ValueError(fProposal validation failed: {e})5.2 Agent之间信息传递丢失的排查多智能体系统最常见的问题就是信息在传递过程中丢失。表现是下游Agent说“没有收到上游的分析报告”或者“报告内容为空”。排查思路是这样的首先检查State的字段名是否一致——上游Agent写入的key和下游Agent读取的key必须完全匹配。我踩过的坑是上游写的是fundamental_report下游读的是fundamental_analysis结果下游一直拿到None。其次检查LangGraph的边定义是否正确。如果两个节点之间没有边连接State的更新不会自动传播。特别是并行节点汇聚的时候要确保所有上游节点都指向了下游节点。最后检查State的reducer函数。LangGraph默认对State的更新是覆盖式的如果你用了Annotated[List, add_messages]那列表是追加的如果没有加annotation那每次更新都会覆盖之前的值。实操心得在开发阶段我建议在每个Agent的入口和出口都加日志打印当前State的关键字段。这样一旦出问题看日志就能快速定位是哪个环节断了。5.3 辩论环节陷入死循环的处理研究员辩论有时候会陷入“你说A我说B你说B我说A”的死循环。我的处理方式是在条件边里加三个判断def should_continue_debate(state: TradingState) - str: # 判断1轮次上限 if state[debate_round] 3: return trader # 判断2论点相似度 if len(state[debate_history]) 2: last state[debate_history][-1] prev state[debate_history][-2] similarity compute_similarity(last[argument], prev[argument]) if similarity 0.85: return trader # 判断3置信度收敛 if len(state[debate_history]) 2: confidences [h.get(confidence, 0.5) for h in state[debate_history][-2:]] if abs(confidences[0] - confidences[1]) 0.1: return trader return continue_debate论点相似度用简单的Jaccard相似度或者余弦相似度就行不需要上BERT。实测下来加了这三个判断之后辩论环节的平均轮次从4.2轮降到了2.3轮token消耗减少了将近一半。5.4 实盘环境下的延迟优化LLM驱动的多智能体系统有个天然缺陷慢。四个分析师并行跑每个Agent的LLM调用要3-5秒辩论两轮又是10秒加上交易员和风控整个决策链路跑下来要30-60秒。对于日线级别的策略这没问题但如果你想做日内交易这个延迟就不可接受了。我的优化方案是分层处理高频决策用规则引擎把LLM的决策结果缓存起来在缓存有效期内的相同市场条件下直接复用不走LLM。异步并行调用四个分析师的LLM调用用asyncio.gather并行执行而不是串行。小模型做初筛用GPT-4o-mini做第一轮分析只有置信度低于阈值的才升级到GPT-4o重新分析。预计算技术指标、财务比率这些确定性计算提前算好不要塞给LLM去算。import asyncio async def run_analysts_parallel(state: TradingState) - dict: tasks [ fundamental_analyst.ainvoke(state), technical_analyst.ainvoke(state), sentiment_analyst.ainvoke(state), news_analyst.ainvoke(state) ] results await asyncio.gather(*tasks, return_exceptionsTrue) return merge_analyst_results(results)这套优化下来整个决策链路的延迟可以从60秒压到15秒以内对于分钟级别的策略已经够用了。5.5 回测与实盘的一致性保障多智能体系统的回测有个特殊难点LLM的输出具有随机性同样的输入跑两次可能得到不同的输出。这导致回测结果不可复现。我的解决方案是在回测模式下把LLM的temperature设为0并且固定随机种子。同时把所有LLM的输入输出都记录到日志里回测结束后可以逐条复盘。如果发现某个决策明显不合理可以针对性地调整那个Agent的prompt。另外回测的时候要注意时间对齐问题。分析师Agent拿到的数据必须是当时那个时间点能拿到的数据不能有未来函数。比如你做2023年1月的回测就不能把2023年2月的财报数据喂给基本面分析师。这个在代码层面要做好数据切片。def get_historical_data(ticker: str, as_of_date: str) - dict: 获取截至as_of_date的历史数据确保无未来函数 df fetch_market_data(ticker) df df[df.index as_of_date] # 财报数据要检查发布日期 financials fetch_financials(ticker) financials financials[financials[report_date] as_of_date] return {price: df, financials: financials}6. 扩展方向与个人实践体会这套框架跑通之后我陆续做了几个扩展效果都还不错。一个是把宏观分析师加进来专门处理利率、汇率、大宗商品这些宏观因子对标的的影响。另一个是把组合层面的优化加进来让组合经理不只是决定单笔交易是否执行还要考虑整个组合的风险平价和行业轮动。还有一个比较有意思的扩展是给每个Agent加记忆。LangGraph本身支持checkpoint但那是流程级别的记忆。我额外给每个Agent加了一个向量数据库存储历史决策和对应的市场结果。当下次遇到类似市场环境时Agent可以先检索历史相似场景的决策和结果作为参考。这个机制让Agent的决策质量随着运行时间增长而逐步提升。我个人在实际操作中的体会是多智能体系统的价值不在于单个Agent有多聪明而在于整个协作机制能不能把每个Agent的局部最优汇聚成全局最优。TradingAgents这套框架最值得借鉴的地方是它用结构化的State和明确的角色边界把LLM的不确定性限制在了一个可控的范围内。你不需要指望LLM每次都给出完美答案你只需要保证每个环节的输出格式正确、逻辑自洽整个系统就能稳定运转。最后分享一个小技巧如果你觉得四个分析师Agent的token消耗太大可以先跑一个“路由Agent”让它根据当前市场环境判断哪些分析师的意见最关键只激活相关的分析师。比如在市场平稳期技术面和情绪面的权重可以降低只跑基本面和新闻分析就够了。这个路由机制能省下30%-40%的token成本对长期运行的策略来说很可观。