前几天改了一个交易策略里的小问题。
问题本身不复杂:某些情况下,策略已经不应该继续等待原来的挂单机会,但代码还会保留一个过期的 pending signal。直觉上,这当然是 bug。既然是 bug,修掉以后策略就应该更好。
真实回放的结果刚好相反。
修复后的版本确实避开了那笔过期信号,也就是说,从逻辑正确性上看,修改是成立的。但同一个时间窗口、同一批真实交易标的、同一套执行假设下,新版本的收益更差,回撤也更大。
这件事对我有点提醒:在交易系统里,正确性和收益不是同一个东西。
这次不是随便拿一段历史 K 线重新跑一遍。
我把线上当时真实使用的交易标的列表保存下来,再用这份列表回放。也就是说,回测时策略能看到的标的,尽量接近当时线上真正会看到的标的,而不是事后用今天的 universe 去解释昨天的市场。
这个区别很重要。
如果每次回测都用当前标的池,很多结果会被悄悄污染。涨上来的标的会更容易留在池子里,跌没了或者流动性变差的标的会消失。你以为自己在复盘策略,其实是在用事后的幸存者名单重新解释历史。
这次我关心两个版本:
结果是:
这不是一个舒服的结果,但它是一个更有用的结果。
交易策略和普通业务系统不太一样。
普通业务系统里,一个 bug 被修掉,通常意味着系统更接近正确状态。比如金额算错、权限判断错、订单状态流转错,这类问题修掉以后,很少需要再问“修完以后业务指标会不会变差”。因为正确性本身就是目标。
交易系统不是这样。
交易系统的目标不是让每一段逻辑看起来更合理,而是在不确定的市场里,用可控风险换取长期正期望。
一个逻辑错误有时会带来坏结果,有时也可能恰好避开坏结果。一个逻辑修复有时会提高收益,有时也可能让策略暴露在另一组更差的交易里。
这听起来有点反直觉,但市场不会奖励“代码看起来更干净”。市场只反馈两件事:
中间的解释、动机、代码结构,只有在它们影响这两件事时才有意义。
这次 stale pending signal 的修复,在局部看是对的。它让策略不再等待一笔已经不该等待的机会。但这个动作改变了后续状态机,也改变了接下来几根 K 线里策略可能进入或退出的位置。
局部 bug 修复会改变全局交易路径。路径一变,收益分布就变了。
所以不能只看“这次错误是否被修正”,还要看“修正以后整个策略暴露到了什么新的分布里”。
以前我对回测的容忍度其实比较高。只要同一套参数、同一段行情、同一份代码能跑出结果,就会觉得可以比较。
现在看,这还不够。
策略回放最容易错在三个地方。
第一个是 universe。
实盘不是面对全市场做选择,而是面对当时系统筛出来的那批标的做选择。如果回测时标的池不是当时那一批,结果就已经偏了。
第二个是执行假设。
信号出现不等于成交。成交还取决于挂单方式、价格、滑点、手续费、仓位限制、撤单逻辑。很多策略看起来在信号层面更聪明,但执行层面拿不到那个价格,最后只是在纸面上更聪明。
第三个是评价指标。
只看收益是不够的。一个版本收益略高,但最大回撤明显变大,未必更值得上线。一个版本修掉了明显错误,但收益变差,也不能直接说它没价值。
这次真正有价值的不是 v1 和 v2 谁赢,而是回测把问题拆开了:
这些问题分开以后,下一步才不会乱。
这次最大的误判,是把 bug fix 下意识当成 strategy improvement。
这两个词在交易系统里应该分开。
bug fix 解决的是“代码有没有按照设计运行”。strategy improvement 解决的是“这个设计在市场里有没有更高的期望收益”。
有时二者会重合。比如一个止损逻辑写反了,修掉以后大概率会改善策略。
但更多时候不会这么干净。
这次就是这样。修复让状态机更符合预期,但它没有证明这个预期本身更赚钱。甚至可以反过来说,旧版本虽然包含一个错误,但这个错误在样本窗口里恰好形成了一条收益更好的路径。
这不代表应该保留错误。
它只代表不能因为“修了 bug”就跳过策略验证。
交易系统里有两种上线门槛:
前者过了,只是说明它有资格进入后者。
以后类似改动,我会按三个层次看。
第一层是局部证据。
这次具体问题有没有被修掉?触发条件是否消失?状态机有没有按预期迁移?
第二层是真实回放。
不用事后标的池,不用模糊样本。尽量拿当时线上看到的 universe、当时的配置、当时的执行假设去跑。
第三层是上线判断。
如果只是修复了局部正确性,但收益和回撤变差,就不要急着合并到主策略。可以把回放工具、数据保存能力、测试用例先合进去,把策略改动留在实验分支里继续观察。
这也是这次最后比较合理的处理方式:基础设施可以留下,策略实验可以丢掉。
工具变强以后,最容易犯的错误是把“我能更快验证”理解成“我能更快上线”。其实正好相反。验证越便宜,越应该提高上线门槛。
这次复盘给我的结论很简单:
正确性不是收益。
交易系统里,一个改动至少要过两关。第一关是它有没有修掉明确的问题。第二关是它有没有让策略在真实约束下变得更好。
只过第一关,不够。
我以前写“交易系统”时说过,交易的核心是胜率、风险和收益。现在看,代码层面的正确性只是让系统有资格参与这场概率游戏。至于它能不能在游戏里活下来,还要交给真实回放、执行约束和风险指标来判断。
市场不会因为你修了一个 bug 就奖励你。
它只会奖励最终那组入场、离场和仓位暴露。
本文创建日期: 2026-06-14
最后更新日期: 2026-06-14