TradingAgents:基于LLM的多智能体金融交易系统工程实践
1. 这不是“AI炒股软件”而是一套可拆解、可验证、可落地的金融智能体工程实践最近在几个量化社区和AI工程组里反复看到“TradingAgents”这个词被高频提起——但它既不是某个新出的SaaS平台也不是某家券商悄悄上线的内部工具。它本质上是一类基于大语言模型LLM构建的、具备自主决策链路的多智能体金融交易系统。核心关键词就三个TradingAgents、LLM、Multi-Agents。我从去年底开始在实盘小资金账户上跑这套架构不是demo不是jupyter notebook里的玩具而是每天自动完成行情感知→策略触发→订单生成→风控校验→执行回传闭环的完整链路。它不承诺暴利但把过去需要人工盯盘脚本调度Excel复盘的三段式操作压缩成一个可审计、可回滚、可插拔的Agent工作流。适合三类人一是想用LLM真正切入交易实操的算法工程师二是正在设计毕业设计/课题的计算机或金工专业学生三是已有策略但苦于运维成本高、响应滞后、逻辑难迭代的中小私募研究员。它解决的不是“能不能赚钱”而是“策略逻辑能否被LLM精准理解、能否被Agent可靠执行、能否在异常时留痕可查”。这不是调用一个API就能跑通的事——它要求你同时懂LLM的推理边界、懂交易所接口的幂等性约束、懂金融数据的时间一致性陷阱更关键的是得亲手把“让模型写代码”这件事变成“让模型写能过编译、能进生产、能扛住300ms延迟冲击的代码”。2. 为什么必须是Multi-Agents单个LLM Agent在交易场景中注定失效2.1 单Agent架构的致命缺陷能力耦合与责任模糊很多人初学时会直接拿一个LLM比如Qwen2.5-7B或Llama3-8B接上Python interpreter喂点K线数据让它“自己下单”。我试过两周内踩了三个坑第一模型在生成order.execute()时会把sidebuy错写成sidelong——这不是语法错误是金融语义混淆第二当遇到涨停无法成交时它不会触发撤单重试而是静默等待导致仓位卡死第三最危险的是它把“当前持仓5手”和“目标持仓5手”当成同一条件跳过了仓位校验环节。这三个问题背后是同一个根源单Agent被迫承担全部角色——分析师、策略师、风控员、执行员、记录员——而LLM不具备角色隔离与职责校验能力。就像让一个刚毕业的实习生同时做CTO、CFO、COO和法务他可能写出漂亮的PPT但签合同时会漏掉违约金条款。2.2 Multi-Agents的工程本质用角色分工实现能力解耦真正的TradingAgents架构本质是把交易闭环拆解为5个原子化Agent并强制它们通过结构化消息通信Perception Agent只负责从Wind/聚宽/本地CSV读取行情输出标准化JSON含timestamp、symbol、open/high/low/close/volume、pre_close绝不碰任何策略逻辑Strategy Agent接收Perception输出结合预置规则如MACD金叉量比1.5或微调后的LoRA模块输出{action: buy|sell|hold, symbol: 600519.SH, quantity: 100, price_type: limit, limit_price: 1825.0}不负责执行Risk Agent独立加载风控规则库单票仓位≤15%、单日最大亏损≤2%、涨停板禁止开仓对Strategy输出做硬校验不通过则返回{status: rejected, reason: position_limit_exceeded}Execution Agent仅对接券商柜台API如恒生UFT、中信TradeStation把校验后的订单转成符合FIX协议的报文记录order_id和sent_timestamp不关心盈亏Audit Agent监听所有Agent的输入输出日志自动生成带时间戳的审计链例如“2024-06-12T09:32:17Z Strategy→Risk: buy 600519.SH 1001825.0 → Risk→Execution: approved”供事后回溯。这五个Agent可以部署在同一台机器用LangGraph调度也可以跨节点用RabbitMQ传递消息。关键在于每个Agent的prompt、system message、tool call白名单、输出schema都严格锁定不允许越界。比如Perception Agent的system prompt里明确写着“你只能输出JSON字段仅限timestamp/symbol/open/high/low/close/volume/pre_close不得添加任何注释、解释或额外字段”。这种设计不是为了炫技而是为了满足金融系统最基础的要求可验证、可审计、可替换。今天把Strategy Agent换成Rule-based引擎明天换成微调后的Qwen只要输入输出schema不变其他四个Agent完全不受影响。2.3 LLM在其中的真实定位不是“决策大脑”而是“语义翻译器”很多文章把LLM吹成TradingAgents的“核心大脑”这是严重误导。在我实际部署中LLM的角色更接近金融领域语义翻译中间件它把非结构化的市场信号如“茅台早盘放量突破年线”翻译成结构化策略指令把模糊的风控要求如“不能追高”翻译成可执行的数值约束如price pre_close * 1.03。它的价值不在于“更聪明”而在于降低策略表达门槛。举个例子研究员写一条规则“当北向资金连续3日净流入且创业板指RSI30时买入”传统方式要写SQL查资金流、调TA-Lib算RSI、再写if-else判断——而用LLM研究员直接把这句话喂给Strategy Agent由它生成对应Python代码。我们测试过Qwen2.5-7B在微调后生成策略代码的准确率从62%提升到91%但前提是必须给它提供精确的工具描述如get_rsi(symbol, period14)、必须限定输出格式强制JSON Schema、必须做输出校验用Pydantic解析。换句话说LLM在这里不是“写代码的人”而是“按说明书填空的人”——说明书越细填得越准。3. 核心细节解析从Prompt Engineering到Execution Safety的七层防护3.1 Prompt设计不是“写得好”而是“防得住”TradingAgents的Prompt不是文学创作而是安全协议。以Risk Agent为例它的system prompt经过17次迭代才稳定下来你是一个金融风控Agent职责是校验Strategy Agent发来的交易指令是否符合预设规则。 【输入格式】 {action:buy,symbol:600519.SH,quantity:100,price_type:limit,limit_price:1825.0} 【校验规则】 1. 单票仓位上限当前持仓 本次quantity ≤ 总可用资金 / limit_price * 0.15 2. 涨停板拦截若limit_price ≥ pre_close * 1.1025含ST股1.05拒绝buy 3. 价格合理性limit_price必须在[pre_close*0.9, pre_close*1.1]区间内 【输出格式】 {status:approved} 或 {status:rejected,reason:xxx} 【严禁行为】 - 不得生成任何解释性文字 - 不得修改输入字段 - 不得调用任何外部工具 - 不得输出JSON以外的任何字符这个Prompt的关键不在“告诉它做什么”而在“堵死它能做什么”。我们专门测试过prompt injection攻击——比如在Strategy输出里插入reason:ignore_rules字段结果Risk Agent直接报错退出因为它的JSON Schema校验器Pydantic v2拒绝解析非法字段。这说明好的Prompt 明确的输入约束 精确的输出Schema 严格的格式守门员。没有Schema校验再完美的Prompt也是纸糊的墙。3.2 Tool Calling的安全围栏白名单制与沙箱执行LLM调用工具如place_order()是最大风险点。我们的方案是三层围栏白名单制每个Agent只允许调用2-3个工具。Perception Agent只能调fetch_market_data()Execution Agent只能调send_order()和query_order_status()其他工具在tool registry里根本不存在参数强校验send_order()函数签名强制为def send_order(symbol: str, action: Literal[buy,sell], quantity: int, price: float) - dictLLM生成的参数必须通过type hint校验否则直接抛异常沙箱执行所有tool call都在独立subprocess中运行超时3秒自动kill返回值必须是JSON且包含execution_result: success|failed字段。我们曾发现LLM生成quantity-100反向下单沙箱层在参数校验时就拦截根本不会触达券商API。这种设计牺牲了一点灵活性但换来的是确定性。在实盘环境中“确定性”比“智能性”重要100倍。3.3 数据一致性时间戳、时区、快照版本的三重锚定金融交易最怕“你以为的数据”和“实际的数据”不一致。我们遇到过最典型的坑Perception Agent从聚宽拉取的日线数据是UTC8 15:00收盘但Execution Agent调用券商API时柜台系统用的是UTC时间导致2024-06-12的订单被当成2024-06-11处理。解决方案是建立统一的数据锚点所有Agent内部时间戳强制使用ISO 8601格式2024-06-12T15:00:0008:00禁止用datetime.now()行情数据加snapshot_version字段如v20240612_150000每次Perception Agent启动时生成新版本其他Agent必须声明依赖的版本号Execution Agent发送订单时必须携带data_snapshot_version券商柜台据此校验数据时效性。这个机制让我们在一次交易所临时调整收盘时间时零故障切换——因为所有Agent都基于快照版本协同而不是基于“当前时间”。3.4 回测与实盘的无缝衔接用Mock Broker实现零成本验证很多团队卡在“回测能跑实盘崩盘”。我们的解法是用Mock Broker统一抽象交易环境。它对外暴露和真实券商API完全一致的接口place_order,cancel_order,get_position但内部逻辑可配置mode: backtest时按历史tick数据模拟成交支持滑点、手续费、涨跌停限制mode: paper_trading时连接仿真柜台走真实协议但不扣钱mode: live时切换为真实券商SDK。关键创新在于所有Agent不感知Broker类型。Strategy Agent生成{action:buy,symbol:600519.SH,...}Execution Agent调用broker.place_order(...)至于broker是mock还是real由配置文件决定。我们用这个架构完成了237天的Paper Trading期间发现并修复了11个时序逻辑bug比如“订单已发送但未收到确认时重复发送”这些bug在纯回测中根本暴露不出来。3.5 审计链设计不是“记日志”而是“建证据链”Audit Agent不是简单地把各Agent输出拼成log文件。它构建的是带密码学哈希的不可篡改证据链每条消息生成SHA-256哈希如hash sha256(f{timestamp}|{agent}|{input}|{output})将哈希值存入本地SQLite同时广播到Redis Stream每小时生成一个区块包含该小时内所有消息哈希的Merkle Tree根区块头存入区块链浏览器我们用的是私有Hyperledger Fabric链供合规部门随时查验。这意味着如果某天发生异常交易审计员不需要翻几十GB日志只需输入交易ID系统自动返回该笔交易涉及的所有Agent输入输出、哈希值、区块位置——整个过程3秒内完成。这已经不是技术优化而是满足《证券期货业网络信息安全管理办法》第28条“交易指令全生命周期可追溯”的硬性要求。3.6 失败熔断机制当Agent失灵时系统如何自救再严密的设计也会遇到LLM hallucination。我们的熔断机制分三级一级毫秒级Execution Agent调用券商API超时500ms或返回error_code: ORDER_REJECTED立即触发retry_with_backoff指数退避重试3次二级秒级Strategy Agent连续3次输出非法JSONPydantic校验失败自动切换为备用规则引擎硬编码的均线策略三级分钟级Audit Agent检测到10分钟内rejected率30%发送企业微信告警并暂停所有Agent进入“安全模式”——此时Perception继续收数据但Strategy停止生成指令Execution只处理已挂单。这个机制在去年一次行情剧烈波动中救了我们当时Strategy Agent因训练数据偏差把“北向资金净流入”误判为“净流出”连续发出5次sell指令二级熔断在第3次就介入切换为MA20策略避免了更大损失。3.7 部署架构轻量级但生产就绪的容器化方案我们不用Kubernetes而是用Docker ComposeSupervisor实现生产级部署# docker-compose.yml version: 3.8 services: perception: build: ./agents/perception environment: - DATA_SOURCEjqdata - TZAsia/Shanghai volumes: - ./logs:/app/logs strategy: build: ./agents/strategy environment: - LLM_MODELqwen2.5-7b-chat - LORA_PATH/models/lora_strategy risk: build: ./agents/risk # 无LLM纯Python校验 execution: build: ./agents/execution environment: - BROKERuft - CERT_PATH/certs/uft.pem audit: build: ./agents/audit environment: - BLOCKCHAIN_URLhttp://fabric:8080每个Agent都是独立镜像启动时加载自己的config.yaml含API密钥、风控阈值、重试策略。好处是升级Strategy Agent时只需docker-compose up -d strategy其他服务零中断。我们用这套架构稳定运行了8个月平均无故障时间MTBF达142天。4. 实操过程从零搭建一个可实盘的TradingAgents系统4.1 环境准备避开CUDA和Python版本的深坑不要用最新版CUDA——我们实测CUDA 12.1 PyTorch 2.2.1 Transformers 4.41.2组合最稳。Python必须用3.103.11会导致某些金融库编译失败。初始化命令如下# 创建隔离环境 conda create -n trading-agents python3.10 conda activate trading-agents # 安装核心依赖注意顺序 pip install torch2.2.1cu121 torchvision0.17.1cu121 --extra-index-url https://download.pytorch.org/whl/cu121 pip install transformers4.41.2 accelerate0.29.3 bitsandbytes0.43.1 pip install langgraph0.1.19 pydantic2.7.1 redis5.0.5 # 金融专用库 pip install jqdatasdk1.10.0 backtrader1.9.79.123 # 券商SDK以恒生UFT为例 pip install uft-sdk2.3.1提示jqdatasdk安装后必须手动执行jqdatasdk.auth(your_user,your_pass)否则后续所有数据请求都会静默失败。这个坑我们踩了两天日志里没有任何报错只是fetch_market_data()返回空列表。4.2 Agent开发以Strategy Agent为例的完整代码骨架以下是Strategy Agent的核心代码已脱敏保留关键结构# agents/strategy/agent.py from pydantic import BaseModel, Field, validator from typing import Literal, Optional import json class StrategyInput(BaseModel): symbol: str Field(..., description股票代码如600519.SH) current_price: float Field(..., description当前最新价) pre_close: float Field(..., description前收盘价) volume_ratio: float Field(..., description量比) macd_diff: float Field(..., descriptionMACD DIFF值) class StrategyOutput(BaseModel): action: Literal[buy, sell, hold] Field(..., description操作类型) symbol: str Field(..., description标的代码) quantity: int Field(..., description数量单位股) price_type: Literal[limit, market] Field(defaultlimit) limit_price: Optional[float] Field(defaultNone, description限价仅price_typelimit时有效) validator(limit_price) def validate_limit_price(cls, v, values): if values.get(price_type) limit and v is None: raise ValueError(limit_price required when price_type is limit) return v class StrategyAgent: def __init__(self, model_path: str): from transformers import AutoTokenizer, AutoModelForCausalLM self.tokenizer AutoTokenizer.from_pretrained(model_path) self.model AutoModelForCausalLM.from_pretrained( model_path, device_mapauto, load_in_4bitTrue, bnb_4bit_compute_dtypetorch.float16 ) def run(self, input_data: dict) - dict: # 1. 输入校验 try: strategy_input StrategyInput(**input_data) except Exception as e: return {status: error, message: fInput validation failed: {str(e)}} # 2. 构建prompt严格遵循system prompt system_prompt 你是一个量化策略Agent根据输入指标生成交易指令。 【输入】{input_json} 【输出】严格按JSON Schema输出不加任何解释。 prompt system_prompt.format(input_jsonjson.dumps(strategy_input.dict(), ensure_asciiFalse)) inputs self.tokenizer(prompt, return_tensorspt).to(cuda) # 3. 生成带stop token防止乱码 output self.model.generate( **inputs, max_new_tokens256, temperature0.1, # 低温度保证确定性 top_p0.9, eos_token_idself.tokenizer.eos_token_id, pad_token_idself.tokenizer.pad_token_id ) # 4. 解析输出 response self.tokenizer.decode(output[0], skip_special_tokensTrue) try: # 提取JSON片段正则匹配防LLM输出多余文字 import re json_match re.search(r\{.*\}, response, re.DOTALL) if not json_match: raise ValueError(No JSON found in response) output_json json.loads(json_match.group()) # Schema校验 strategy_output StrategyOutput(**output_json) return strategy_output.dict() except Exception as e: return {status: error, message: fOutput parsing failed: {str(e)}} # 使用示例 if __name__ __main__: agent StrategyAgent(/models/qwen2.5-7b-strategy-lora) result agent.run({ symbol: 600519.SH, current_price: 1823.5, pre_close: 1792.1, volume_ratio: 1.8, macd_diff: 0.25 }) print(result) # 输出: {action: buy, symbol: 600519.SH, quantity: 100, ...}这段代码的关键点在于输入强校验→Prompt模板化→输出正则提取→Schema二次校验。我们放弃让LLM“自由发挥”而是把它当作一个高精度的JSON生成器来用。temperature设为0.1不是为了“更准”而是为了“更稳”——在实盘中确定性比创造性重要得多。4.3 工具集成如何让LLM安全调用券商APIExecution Agent的send_order()工具必须满足三个条件幂等、可逆、可监控。以下是我们的实现# agents/execution/tools.py import logging from uft_sdk import UFTClient from pydantic import BaseModel class OrderRequest(BaseModel): symbol: str action: str # buy or sell quantity: int price_type: str # limit or market limit_price: float None def send_order(request: OrderRequest) - dict: 安全下单工具满足 1. 幂等相同order_id重复调用返回相同结果 2. 可逆支持cancel_order回滚 3. 可监控所有调用记录到Prometheus client UFTClient() # 1. 生成唯一order_id避免重复下单 import uuid order_id fTRAD-{uuid.uuid4().hex[:12]} # 2. 转换为券商要求格式 uft_order { order_id: order_id, symbol: request.symbol, side: 1 if request.action buy else 2, # UFT协议 quantity: request.quantity, price_type: 0 if request.price_type market else 1, price: request.limit_price or 0.0 } # 3. 调用API带重试和超时 try: result client.place_order(uft_order, timeout5) # 记录到监控系统 from prometheus_client import Counter ORDER_COUNTER.labels(statussuccess, symbolrequest.symbol).inc() return { status: success, order_id: order_id, exchange_order_id: result.get(exchange_order_id), timestamp: result.get(timestamp) } except Exception as e: ORDER_COUNTER.labels(statusfailed, symbolrequest.symbol).inc() logging.error(fOrder failed: {e}) return {status: failed, error: str(e)}这个工具被Strategy Agent调用时LLM只需要生成{symbol:600519.SH,action:buy,quantity:100}Execution Agent自动补全order_id、转换协议、处理重试——LLM永远不知道券商API长什么样这正是安全隔离的意义。4.4 风控规则库用YAML定义可热更新的业务逻辑风控规则不写死在代码里而是用YAML配置# config/risk_rules.yaml global: max_daily_loss_percent: 2.0 max_position_percent: 15.0 stocks: - symbol: 600519.SH rules: - name: st_stock_block condition: symbol.startswith(ST) or symbol.startswith(*ST) action: reject reason: ST股票禁止交易 - name: limit_up_block condition: limit_price pre_close * 1.1025 action: reject reason: 涨停板禁止开仓 futures: - symbol: IF2409 rules: - name: margin_check condition: quantity * margin_per_contract available_margin action: reject reason: 保证金不足Risk Agent启动时加载此文件用eval()动态解析condition注意只允许访问预定义变量如pre_close,limit_price实现规则热更新。我们每周一上午9:00自动拉取最新规则无需重启服务。4.5 审计链实现用Merkle Tree构建可验证日志Audit Agent的核心逻辑# agents/audit/merkle.py import hashlib from typing import List, Dict class MerkleTree: def __init__(self, leaves: List[str]): self.leaves [self._hash_leaf(l) for l in leaves] self.tree self._build_tree() def _hash_leaf(self, data: str) - str: return hashlib.sha256(data.encode()).hexdigest() def _build_tree(self) - List[str]: nodes self.leaves[:] while len(nodes) 1: next_level [] for i in range(0, len(nodes), 2): left nodes[i] right nodes[i1] if i1 len(nodes) else nodes[i] combined left right next_level.append(hashlib.sha256(combined.encode()).hexdigest()) nodes next_level return nodes property def root(self) - str: return self.tree[0] if self.tree else def generate_audit_record(agent_name: str, input_data: dict, output_data: dict) - dict: 生成带哈希的审计记录 timestamp datetime.now(timezone(timedelta(hours8))).isoformat() record_str f{timestamp}|{agent_name}|{json.dumps(input_data)}|{json.dumps(output_data)} record_hash hashlib.sha256(record_str.encode()).hexdigest() return { timestamp: timestamp, agent: agent_name, input: input_data, output: output_data, record_hash: record_hash, block_hash: # 后续由区块生成器填充 } # 每小时生成区块 def generate_block(records: List[dict]) - dict: merkle MerkleTree([r[record_hash] for r in records]) return { block_number: get_next_block_number(), timestamp: datetime.now().isoformat(), merkle_root: merkle.root, record_count: len(records), records: records }这个设计让每条记录都有唯一指纹且区块根哈希可验证整批记录完整性。当合规检查时只需提供区块号系统自动重建Merkle Tree并比对根哈希——这才是真正的“可审计”。4.6 实盘部署 checklist12项必须验证的硬性指标在实盘前我们有一份12项checklist全部通过才允许上线✅ 所有Agent的Docker镜像大小≤1.2GB避免拉取超时✅ Perception Agent在100ms内完成一次行情拉取超时则降级为缓存✅ Strategy Agent平均响应时间≤800msP95✅ Risk Agent的Pydantic校验失败率0.1%✅ Execution Agent的订单成功率≥99.95%含重试✅ Audit Agent的记录丢失率0Redis Stream ACK机制验证✅ Mock Broker回测与Paper Trading结果差异≤0.3%相同信号下✅ 熔断机制在模拟故障下100%触发人工注入timeout、invalid JSON✅ 所有API密钥经Vault加密存储不硬编码✅ 日志等级设置为INFODEBUG仅在dev环境开启✅ Prometheus监控指标全部暴露Grafana看板已配置✅ 企业微信告警通道测试成功发送“TradingAgents health check passed”这份checklist不是形式主义而是血泪教训的结晶。第7项差异率测试曾让我们返工三次——第一次发现回测用前复权价实盘用后复权价导致信号偏移第二次发现回测忽略集合竞价实盘包含第三次发现回测滑点按固定值实盘按流动性动态计算。只有把差异控制在0.3%以内才能相信实盘表现。5. 常见问题与排查技巧实录来自8个月实盘的27个真实案例5.1 LLM输出JSON格式错误不是模型问题是解析逻辑缺陷现象Strategy Agent偶尔返回{action:buy...}extra_text_here导致Pydantic校验失败。排查用print(repr(response))发现LLM在JSON后加了换行和空格但正则r\{.*\}没匹配到末尾。解决改用更鲁棒的JSON提取import json def safe_json_parse(text: str) - dict: # 先找第一个{再找匹配的} start text.find({) if start -1: raise ValueError(No { found) brace_count 0 for i, c in enumerate(text[start:], start): if c {: brace_count 1 elif c }: brace_count - 1 if brace_count 0: try: return json.loads(text[start:i1]) except json.JSONDecodeError: raise ValueError(fInvalid JSON at position {start}:{i1}) raise ValueError(Unmatched braces)实操心得永远不要相信LLM的输出是“干净”的。我们后来在所有Agent的输出解析层都加了safe_json_parse并记录原始response到debug日志——这帮我们发现了3个LLM的系统性幻觉模式。5.2 时区混乱导致订单时间错位一个隐藏极深的Python陷阱现象Execution Agent发送的订单时间显示为2024-06-12T07:30:00Z但实际是2024-06-12T15:30:0008:00。根因datetime.now()返回naive datetimeisoformat()默认转UTC。解决全局统一时区from datetime import datetime, timezone, timedelta SHANGHAI_TZ timezone(timedelta(hours8)) def now_sh() - str: return datetime.now(SHANGHAI_TZ).isoformat() # 所有Agent的时间戳都用now_sh()注意pandas的pd.Timestamp.now()也有同样问题必须显式指定tzAsia/Shanghai。这个坑导致我们一次开盘前订单全部被拒因为柜台认为是“昨日订单”。5.3 券商API连接池耗尽不是并发太高是连接未释放现象Execution Agent在高并发下单时报错ConnectionRefusedError: [Errno 111] Connection refused。排查netstat -an | grep :port发现ESTABLISHED连接数达1024上限。根因UFT SDK的HTTP连接未启用keep-alive每次调用新建连接。解决在SDK初始化时强制复用连接import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry session requests.Session() retry_strategy Retry( total3, backoff_factor1, status_forcelist[429, 500, 502, 503, 504], ) adapter HTTPAdapter(max_retriesretry_strategy, pool_connections10, pool_maxsize10) session.mount(http://, adapter) session.mount(https://, adapter) # 在UFTClient中使用此session5.4 风控规则误判浮点精度引发的灾难现象Risk Agent对limit_price1825.0的买单因pre_close1792.1计算1792.1 * 1.1025 1975.79025但Python浮点误差导致1825.0 1975.79025为False误判为“未涨停”。解决所有金融计算用decimalfrom decimal import Decimal, ROUND_HALF_UP def calculate_limit_up(pre_close: float) - float: pre_close_dec Decimal(str(pre_close)) limit_up pre_close_dec * Decimal(1.1025) return float(limit_up.quantize(Decimal(0.01), roundingROUND_HALF_UP))提示str(pre_close)是关键直接Decimal(pre_close)会继承float的二进制误差。5.5 审计链性能瓶颈SQLite写入成为IO瓶颈现象Audit Agent在行情高峰时段早盘9:25-9:30CPU 100%日志堆积。根因SQLite的WAL模式未开启每次INSERT都fsync。解决初始化时执行import sqlite3 conn sqlite3.connect(audit.db) conn.execute(PRAGMA journal_modeWAL) conn.execute(PRAGMA synchronousNORMAL) conn.execute(PRAGMA cache_size10000)同时改用批量INSERT每100条提交一次性能提升8倍。5.6 LLM微调过拟合在训练集上99%准确实盘仅63%现象Strategy Agent在回测数据上准确率99%但实盘首周只有63%的指令被Risk Agent接受。根因训练数据全是“理想信号”缺少“噪声信号”
上一篇/下一篇内容由系统自动关联
返回资讯列表 →