2026年十一月8日 · 研究

你的回测可能过于可复现

你的回测可能过于可复现

完全可复现的回测,可信度可能不如结果略有波动的回测。可重复性只能证明你能两次得到相同答案;它说明不了这个答案是否依赖某个任意的数据快照、库的特性或隐藏的默认设置。

听起来像是在反对可复现性,其实并不是。固定一次运行,这样你就能解释它;然后有意改变那些本不该左右结果的假设。第一步让结果可以审计,第二步则告诉你这个结果是否有意义。

可复现的回测究竟能证明什么?

如果相同的代码、数据、配置和随机种子能产生相同的交易和指标,你就控制住了一个重要的混淆来源。这样可以将某个 agent 的“改进”与其父级运行进行比较,也能把修复 bug 的影响与费用表变更区分开来。同事可以查看同一份账本,并找到相同的成交记录。

但这个结果取决于你固定的所有内容。想象一项加密货币策略,它的历史文件包含 1 分钟 K 线。你保存文件哈希、锁定代码,每次重跑都得到 1.4 的 Sharpe。如果供应商后来修正了几根蜡烛线,这种干净的可复现性仍然只描述旧文件。它没有告诉你信号能否经受修正后的历史数据,也没有说明当时是否能以这种形式获得这些蜡烛线。

哈希很有用:它让依赖关系显而易见。但它并不能证明这种依赖无害。

固定运行;检验结论

我喜欢把问题分成两个:我们能否重建这次完全相同的运行?研究结论能否经得住合理的变更?第一个问题需要不可变的记录;第二个需要逐项进行受控扰动。

记录内容之后改变的内容可以揭示什么
原始数据版本和校验和供应商修订版或第二个数据源对修正值或供应商特定数值的依赖
代码提交版本和软件包版本数值等价的实现对运算顺序、舍入或库的敏感性
费用、资金费率和成交假设合理的成本区间微薄的优势是否依赖格外有利的执行条件
交易标的范围和时点成员资格其他符合条件的市场规则对纳入或排除决定的依赖

例如,假设某个期货策略在基准重放中显示年化超额收益为 8%。将 taker 成本提高 25%,把资金费率结算时间移到下一个观测到的结算时点,并分别移除贡献最大的两个标的后重新运行。这三项操作不是改进模型的三种方法,而是检验手段:每一项都在探查某个看似合理的细节是否撑起了 headline 结果。

每项检验都要单独进行。如果同时更改数据、费用表和执行时间,结果变差时就很难判断原因。如果某项检验不符合实际,就把它标注为压力情景,而不要把它说成最可能出现的结果。

别把逐字节相同误当成数值准确

有些计算对运算顺序很敏感。浮点数加法不满足结合律,因此,以不同顺序对许多很小的盈亏值求和,可能会改变末尾几位数字。并行归约、硬件和库版本都可能影响精确输出。通常这无关紧要;但有时,微小的数值变化会翻转阈值、改变持仓,并让模拟余下部分走上另一条路径。

因此,我会同时保留精确产物和比较容差。记录交易账本,而不只是最终 Sharpe。先比较决策和现金流,再按声明的容差比较指标。如果一分钱的差异会改变是否提交订单,就要明确检查这个边界。

有用的运行记录应包含数据和代码的身份信息、配置、随机种子、执行环境,以及足够的中间输出,以便追溯指标对应的成交和现金流。只有最终评分,并不算可复现的研究产物。

何时是波动噪声,何时是发现

数字有变化,不一定就意味着出了问题。不同的归约顺序导致指标略有漂移,可能不会改变交易。阈值附近的交易发生变化,就值得检查。如果供应商修订了一小段历史数据,策略的大部分收益便随之消失,那么你就了解了策略自身的脆弱性,即使原始运行仍然完全可复现。

对稳健性检查持批评态度的人有一点说得没错:人们很容易不断更改假设,直到偏好的策略看起来足够稳健;也可能因为某个刻意设置的极端情景会让结果失效,就否定原本可靠的结论。应预先定义合理的变动,报告全部结果,并区分常规替代情景与压力情景。然后保留基准结果,让其他研究者能够精确复现你看到的内容。

可复现性为你提供了可靠的起点。接下来真正有用的问题是:当这次运行周围的环境发生合理可预期的变化时,答案中的哪些部分仍然不变?

可复现性回测数据工程量化研究
← 全部文章