
最近经常有人问我能不能让 AI 自己盯盘、自己下单最好再自己赚钱说实话从大模型这波热度起来之后“让 AI 炒股”就一直是最容易被追问的话题之一。我花了大半年时间从零搭过一套以 LLM 为核心决策器的股票交易实验系统更准确的说法是我做的其实是Agent Harness Engineering——研究怎么给一个“自主 Agent”套上可靠的工程化约束框架。先说结论我能做到的是让系统在仿真环境里完整走完“看数据、做分析、下决策、复盘改进”的闭环离“躺着赚钱”差了十万八千里。这篇博文会把我的整体思路、模块拆解和踩坑过程完整摊开最后的风险警示部分请务必读完尤其是打算上真金白银的读者那部分比代码重要得多。1. 先想清楚你要做的是“自动赚钱脚本”还是“可验证的自主决策实验系统”1.1 自动脚本和自主 Agent 的根本差别很多人第一反应是写个定时任务每隔几分钟调用接口拿行情按几条均线规则判断买卖不就实现“AI 炒股”了吗这不是升级而是一个普通的量化策略脚本。脚本和 Agent 的最大区别在于脚本是把所有路径都写死的程序Agent 则是在目标和约束给定的情况下自己动态选择下一步操作的程序。举个例子传统脚本看到“价格突破20日均线”就买逻辑非常刚性。我搭的这套系统输入给模型的是市场状态摘要模型会自己决定“先查一下最近30天的成交量分布再确认是否处于缩量整理阶段如果量能没有配合就继续等待”。这个“自己决定下一步干什么”的能力才是 Agent 化的核心价值。但代价也很明显路径越多失控面越大。所以如果你只是想让某个规则自动跑起来完全没有必要引入 Agent。引入 Agent 的真正前提是你希望系统能够处理未预期场景并且在处理过程中保持可解释、可干预。1.2 “自主”是一个光谱不是一个开关我习惯把“自主”分成几个阶段阶段0人工决策脚本只负责执行下单。阶段1规则触发系统按固定条件自动执行。阶段2模型分析后生成建议由人在环上做最终确认。阶段3Agent 自主决策但外层有独立风控兜底。阶段4Agent 自行设定交易目标和策略参数甚至自己调整风控阈值。这个项目的定位是阶段2到阶段3之间绝大多数时间跑仿真盘偶尔让人工确认 Agent 的决策。我强烈建议个人用户不要追求阶段4。阶段4意味着模型可以自己改止损参数、自己决定要不要加仓一旦它基于错误理解做出极端决策后果是不可逆的。1.3 我给自己划的三条红线项目动手之前我先定了三条原则整个开发过程中没有动摇过。第一定位是研究项目目标不是赚钱而是验证 LLM 能否在受限金融场景下稳定调用工具、产出可解释的决策。第二默认运行在仿真环境即使未来实盘也只使用一个独立小账户。第三Agent 永远没有直接下单权限只能输出结构化的“交易意图”实际执行必须经过独立风控中间件。这三条红线听起来保守但正是它们让整个项目没有滑向“失控赌博”。Harness Engineering 的核心思想就藏在这里与其追求一个全知全能的 Agent不如先把它的活动范围圈在安全区域内。2. 工程骨架数据、决策、执行、风控、监控是一条“不能放任的链路”2.1 整体数据流与模块划分我最初犯过一个错误把行情获取、策略判断、下单执行全写在一个 Python 文件里。后来代码能跑但完全没法定位问题——不知道某笔交易到底是模型判断出来的还是数据更新延迟导致的。所以第二步我把系统拆成了六个边界清晰的模块数据接入、特征工程、决策引擎、风控中间件、执行网关、监控审计。数据流大致是这样的行情数据源 → 清洗与存储 → 特征计算 → Agent 上下文构建 → 模型决策 → 结构化意图 → 风控校验 → 执行网关仿真 → 成交回报 → 日志与复盘数据库 → 教训片段注入下次决策。模块之间通过异步任务队列通信。为什么不用同步调用因为行情是持续流入的而 Agent 的推理可能消耗几十秒如果让一个慢请求阻塞后续所有行情更新系统会越来越卡。异步解耦之后即便某个模块故障其他模块也能降级运行。有一次行情源连接断了决策引擎仍然正常工作只是拿到的数据是旧的——监控模块发现数据时间戳滞后自动切入了“暂停决策”状态这就是模块化的价值。2.2 执行网关为什么必须和 Agent 隔离这是整套系统里我最重视的一条设计原则交易动作必须处于 Agent 的外侧。Agent 只负责输出一个结构化的 JSON 对象例如{ agent_id: demo-001, timestamp: 2025-01-15T14:30:0008:00, action: buy, instrument: 000001, quantity: 100, reason: 放量突破近20日平台短期趋势转强, confidence: 0.61, risk_level: medium }执行网关拿到这段 JSON 之后先校验字段合法性再查询当前持仓和可用资金然后按预设的滑点和手续费模型构造仿真订单。整个过程中Agent 连交易通道的边都摸不到。即使模型胡说八道网关也能拦下一道。这就是“Harness”这个词的本质——马可以自己跑但方向和边界由骑手控制。2.3 数据接口、异步任务和状态存储个人实验项目不需要一开始就引入重型的流处理框架我用的是轻量轮询加有限状态机。行情模块每隔5秒拉取一次最新快照写入内存中的环形缓冲区特征工程订阅这个缓冲区做增量计算。决策请求进入任务队列决策引擎消费队列完成后把结果发布到风控中间件。状态存储方面我最终选了数据库来做原因只有一个审计需要。每一笔决策、风控校验、执行回执都要落库字段包括模型输入摘要、模型输出原文、校验结果、执行结果。没有这些历史记录复盘就无从谈起。另外提一个容易踩的坑账户查询和成交回报之间存在时间差读取持仓时必须同时对订单状态做快照否则会出现“明明刚提交了卖出持仓查询还是原来的数字”的错觉。3. 数据与特征工程喂给 Agent 的信息必须是“干净的过去式”3.1 行情数据清洗复权、停牌、涨跌停在金融数据上“脏数据”比代码 bug 更致命。我在这块踩过的最深的坑有三个。第一个是复权。股票分红除息后价格会跳空不复权的历史数据会让均线、MACD 等指标产生假信号。实际操作中前复权适合看最近走势后复权适合长期回测我统一用前复权做特征计算回测时再单独处理。第二个是停牌。停牌期间没有成交不能假设随时可以买卖。如果一只股票停牌半个月复牌首日直接一字涨停回测模型可能在“停牌期间一直持有”的假设下赚到不切实际的收益而现实中你根本买不进也不一定卖得出。第三个是涨跌停。涨停封死的时候买单排队未必能成交跌停封死的时候卖单也未必能成交。回测和仿真里必须标记“该K线不可成交”否则模型会疯狂捕捉一字板信号并假装自己赚到了钱。3.2 特征维度量价、技术指标与文本情绪Agent 不能直接消化原始行情我需要把原始数据加工成特征快照。基础的量价特征是必须的开高低收、成交量、成交额、收益率、振幅。技术指标我用过均线、MACD、RSI、布林带和量能均线。文本情绪其实是个双刃剑新闻标题和公告关键词有信息量但噪声很大而且发布时间和盘面时间的对齐非常麻烦。我最后把文本情绪做成一个0到1的分值只作为辅助信号从不单独触发买卖。这里有个实际经验特征维度宁少勿多。LLM 的上下文是有限的喂进去的特征如果又杂又长模型反而容易迷失重点。我最终只保留约20个核心特征按固定顺序拼接成表格文本模型的决策稳定性明显提升。3.3 数据存储与性能取舍个人项目不需要一上来就上大数据集群。我用本地列式格式按日期分片存储每只股票一个目录行情接口只返回最近N根K线和最新的指标快照。注意这里最忌讳的是让 Agent 每次决策都去全表扫描历史数据既慢又浪费 token。正确做法是数据层封装一个“取快照”接口内部完成聚合只返回给 Agent 一份精简摘要。盘中更新还要警惕增量写入的冲突。同一分钟内可能有多个模块同时写数据文件我在写端加了文件锁同时规定所有数据落盘必须带时间戳。这个时间戳不只是给人看的更是回测系统判断“当前时刻能用到哪些数据”的关键。3.4 我最常看到的数据穿越案例数据穿越是最隐蔽的 bug它会让回测收益率虚高一倍都不止。典型错误是拿当天收盘后的新闻摘要作为当天买入决策的理由。现实中收盘后你才看到新闻但决策模型却假装它在盘中就看到了这就是未来函数。另一个错误是在15:00收盘后才能获取的日线数据上做当日盘中决策。看起来没什么实际上模型以为的“当日操作”在现实中根本没法成交。正确做法是定死一个原则决策时刻只能使用决策时刻之前已经产生的数据。回放系统里我用K线收盘时间加一个最小tick作为数据可见时间从机制上杜绝未来函数。4. 决策引擎设计让 Agent 会先论证、敢纠错、被装上安全阀4.1 上下文组装系统提示词、市场摘要、持仓与复盘决策引擎的输入不是简单地把行情往模型里塞。我设计了四段式上下文。第一段是系统提示词写死角色和边界。内容大概是你是量化研究助手不是理财顾问目标是在仿真环境中寻找可解释的交易机会每次必须输出限定结构的 JSON。第二段是市场摘要由数据层生成包括近期指数状态、目标股票的K线总结和关键指标。第三段是当前持仓和可用资金。第四段是上次决策复盘也就是上一轮模型做了什么、结果如何。这里最大的坑是上下文长度失控。历史复盘越积越多Agent 会越来越“健忘”只记得最近的内容。我的做法是每轮只保留最近3条复盘片段每片段压缩成一句话例如“0621买入后连跌3天止损出局教训是缩量突破追涨胜率低”。4.2 决策流程先观察、再论证、后输出结构化意图Agent 的决策流程被我用提示词固定在五个步骤里观察读取最新行情快照与市场摘要。分析列出当前趋势、支撑压力位、成交量特征。候选动作对比买入、卖出、持有、观望四个选项给出理由。风险自评模型评估如果看错最大损失是多少。输出 JSON必须包含 action、quantity、reason、confidence、risk_level 字段。这一步的意义在于模型被要求先给出“论证过程”再输出结论。这样即便最终决策是错的我们也能在日志里看到它错在哪一步而不是面对一个黑箱结果。4.3 工具调用设计给 Agent“能查什么”的边界Agent 具备工具调用能力之后事情就开始变得危险。我的原则是只允许 Agent 调用只读工具。它能查询K线、计算指标、获取持仓、查看可用资金但没有任何工具可以提交订单、修改订单或撤销订单。这样的设计让 Agent 永远处在“分析师”的位置而不是“交易员”的位置。工具返回结果也要做截断。比如查询K线接口如果返回过去一年的全量数据会直接撑爆上下文。我限定只返回最近60根K线和关键指标的汇总值。工具调用失败时允许重试但最多重试三次三次之后必须转入观望状态防止模型陷入循环调用死磕。4.4 记忆与复盘亏损教训如何注入下一次决策复盘模块是这套系统区别于普通脚本的另一个关键点。每完成一次仿真交易系统会记录决策理由、市场状态、盈亏结果然后让另一个独立的评估流程生成一条复盘碎片。这个碎片不是简单的“亏了”而是具体的教训比如“高位放量滞涨后第二天低开概率大”。下一次决策前复盘模块会筛选与当前市场状态匹配的最近几条教训注入到上下文里。实际效果是模型在连续吃了几次“追涨”的亏之后系统会不再轻易给出追涨信号。这有点像给 Agent 装上了“肌肉记忆”但它只能通过硬编码的筛选逻辑起作用而不是让模型自由读取全部历史。4.5 模型幻觉与乱输出的兜底模型不是每次都能输出合法 JSON。我遇到过输出非法字符、数量为负数、甚至直接把“满仓买入”写进 reason 的情况。这些全部要靠 schema 校验拦截。解析失败时系统会把该条决策标记为 invalid并直接进入30分钟冷静期——不重试、不补单、不清理缓存。冷静期的逻辑很简单既然模型当前状态不对就别让它继续做决策。还有一个细节模型的文本永远不能直接变成指令。只有通过 JSON schema 校验的字段才允许进入下一步文本只作为审计归档。这个原则四两拨千斤它堵住了绝大多数模型幻觉导致的风险。5. 回测与仿真验证先让系统“亏得起”再谈“赚得到”5.1 回测引擎的几个硬要求回测是用历史数据验证系统是否值得继续跑下去的手段。我的回测引擎有几条硬性要求。第一逐根K线事件驱动回放而不是把整个价格序列一次性塞给策略。第二每笔成交都必须模拟手续费、滑点和税费。第三涨跌停不可成交的规则必须在撮合逻辑里体现。第四统计指标不能只算收益率还要算最大回撤、胜率、盈亏比、换手率。很多人回测跑出漂亮曲线就直接上实盘这是极其危险的操作。回测的每一行代码都在跟含糊的假设打交道——成交价、滑点、及时性——任何一个假设失真结果就会变成幻觉。我的原则是回测结果差一定不能实盘回测结果好也不一定敢实盘中间隔着仿真验证这道坎。5.2 仿真盘Paper Trading的价值仿真盘连接实时行情但不下真实单。它最大的价值在于暴露回测发现不了的问题接口延迟、订单状态机、重复提交、Agent 决策超时、数据源断流。我第一次上仿真盘时系统运行到第4天突然停止决策。查日志才发现行情模块在某个时点推送了一条格式异常的消息特征工程抛异常后没有捕获导致任务队列被源源不断的重试任务耗尽。回测环境根本模拟不出这种实时系统故障只有仿真盘能逼出这些问题。所以仿真验证阶段我要求系统至少连续运行一个月完整市场周期包括上涨、震荡和下跌行情。5.3 我实测中失效的三个信号场景仿真盘跑下来我记了三个最典型的失败场景。第一个是数据穿越导致虚高收益。回测里模型在当天收盘后拿到新闻情绪分并基于它做了当日买入决策净值曲线极其漂亮。仿真盘里同样的信号完全失效因为盘中根本没有这个情绪分。修掉时间对齐问题后收益曲线立刻回归平淡。第二个是涨停不可成交。回测撮合逻辑里涨停价买入被模拟为“成功成交”仿真盘里订单排队到最后被拒。这个差异直接让一类“打板策略”的收益率从正变成负。第三个是高换手被手续费吞噬。模型频繁交易单笔胜率55%看似有点优势但扣除手续费和滑点后最终收益转负。后来我把换手率纳入了风控阈值超过一定水平就直接降权。5.4 评估指标组合不要只盯着年化收益我见过太多人只看年化收益。年化100%的策略如果最大回撤80%本质上是赌徒游戏。我至少同时看六项指标年化收益率、最大回撤、胜率、平均盈亏比、夏普比率、换手率。个人经验是最大回撤超过30%的策略不要实盘即便收益看起来很诱人。还有一个容易忽视的点绩效归因。如果收益集中在少数几笔交易上说明策略没有统计意义只是运气好。我用一个简单的归因脚本按日统计每笔交易的贡献如果前5笔交易贡献了超过80%的利润这个系统就还需要继续观察。6. 风险警示合规、资金、技术、市场四条红线6.1 合规红线没有资质不要越界这个话题必须放在最前面。证券投资咨询、代客理财、公开荐股在国内都有明确的资质要求。个人如果未经允许帮别人管钱、收费带单、在公开渠道发布“必涨”信息都是非常大的合规隐患。即使只是自己做自动化实验也要确认开户券商对程序化交易的政策是否要求登记、报备、使用指定的接口通道。不要尝试绕过券商的任何风控措施也不要对外输出任何投资建议。我做的这套系统严格限定为个人技术研究运行在仿真环境。如果你要接触实盘请务必先跟自己的券商沟通清楚规则并且给自己划定“绝不对外提供投资建议”的边界。6.2 资金风险AI 模型没有“保本”概念不要指望语言模型理解“亏钱”是什么感受。它可以在一个极度恐慌的行情里自信地输出“买入”因为它没有账户、没有压力、没有生活开销。所以资金层面的风控必须全部硬编码在系统里不能交给模型判断。我设了三道硬性门槛单笔最大亏损比例、单日最大亏损熔断、账户最大回撤熔断。任何一条触发系统直接进入停止交易状态需要人工确认才能恢复。网格加仓、摊平成本这类操作全部禁止模型也没有权限调整风控参数。实盘资金必须是你心理上能接受全部亏掉的闲钱否则这个项目会反过来吞噬你的生活。6.3 技术风险密钥泄漏和裸奔过夜技术层面最大的风险是密钥泄漏。脚本里但凡把 API 密钥、账户口令硬编码一旦代码库泄露或日志被上传后果就是账户被盗操作。我要求所有敏感凭据放环境变量或密钥管理服务而且仿真环境用单独的密钥跟任何可能的实盘账户彻底隔离。另一个风险是系统故障导致的裸奔状态。如果程序在盘中崩溃、断网、或接口异常AI 无法管理现有的持仓。我的策略是启动前写入一份“故障预案”内容包括断网超过 N 分钟自动清仓模拟标记、重连后不许盲目补单、收盘前未恢复则保持现状等待人工处理。日志巡检也是每日必做异常事件全部告警。6.4 市场风险风格切换和黑天鹅市场本身就是最大的不确定源。模型可能在某种风格行情里表现出色比如趋势行情一旦转入快速轮动或震荡行情策略就会连续亏损。更极端的情况是放量暴跌、连续跌停、流动性枯竭这时候模型可能会基于历史规律强行给错误信心。我的应对方式是在风控中间件里加入极端行情探测器当指数日内波动超过预设阈值时系统暂停所有决策进入只读状态。同时限制单一标的的仓位上限永远不允许满仓押注一只股票。市场风格的切换在回测里很难完全模拟仿真盘和实盘小账户的长期观察才能逐步暴露问题。6.5 从仿真到实盘的检查清单如果你真的考虑把类似系统迁移到实盘我建议至少过一遍这张清单连续仿真运行满3个月覆盖过涨、跌、震荡三种状态。最大回撤始终控制在预先约定的阈值内。所有熔断机制做过至少一次故障演练确认能触发、能告警、能停止。密钥权限最小化分离仿真与实盘的凭据。实盘账户是独立小账户资金量为亏光也不影响生活的闲钱。有一条随时可以完全停止系统的手动开关。这篇博文只谈工程方法不构成任何投资建议。市场有风险决策需谨慎请在合规的前提下开展所有实验。最后分享一个我自己的体会做完这套系统后我对“自主”两个字的理解完全变了。真正难的从来不是让 Agent 变得更自由而是让它在明确边界内自由。Harness Engineering 的核心就是把自由限制在一个恰到好处的范围内。另一个小技巧是在 Agent 的输出结构里要求它每次写一句“如果看错最大损失是多少”。这个字段看起来简单却是我用过的效果最好的心理校准器——它逼着模型在自信之外也必须面对最坏情况。把这些风控细节一个个落地之后项目才真正开始像一个可以长期运行的实验系统。