1907 字
10 分钟

回测的正确姿势:未来函数、幸存者偏差与过拟合

本课目标:认识回测中最常见的几类系统性错误,学会用一份自查清单在提交结论之前给自己”挑刺”。

上一课我们走通了双均线策略的回测流程。这一课要泼一盆冷水:大多数惊艳的回测结果,是错误造成的,不是策略造成的。回测出错的方式有很多,但绝大多数可以归入几个经典类别。提前认识它们,比事后懊悔便宜得多。本文不构成投资建议。

未来函数:用了”当时不可能知道”的信息#

未来函数(look-ahead bias)指回测在某个时点的决策中,使用了那个时点还不存在的信息。它是新手回测虚高的头号原因。典型形态包括:

  • 用当日收盘价做当日决策:收盘价要到收盘才知道,但回测里却按”当天以收盘价买入”计算。正确做法是信号 shift(1),次日成交;
  • 用复权价直接当交易价:前复权价格会随最新分红除权整体平移,早期的”价格”其实包含了未来的分红信息,做信号可以,当成交价要小心;
  • 用整段数据算指标再回看:比如用全样本的均值和标准差做标准化,等于让 2020 年的你知道 2025 年的分布;
  • 财报数据按报告期而非公告日对齐:年报反映的是 12 月 31 日的数据,但你实际要到次年三四月才能看到。

判断标准只有一条:站在那个交易日的收盘前,这条信息我真的拿得到吗?

未来函数的可怕之处在于,它制造的往往不是小误差,而是方向性的错觉:一个本来亏损的策略可以被它”修正”成年年赚钱。而且它很隐蔽——代码能正常运行、曲线很漂亮、逻辑看起来自洽,只有逐行追问每个变量的信息时点才能发现。所以有经验的研究者看到异常漂亮的回测,第一反应不是兴奋,而是找哪里泄漏了未来信息。

幸存者偏差:你只看到了活下来的#

如果你今天取”当前全部 A 股”的名单,回测过去十年,那么已退市、已被 ST 淘汰的公司天然不在样本里。你的股票池等于提前剔除了失败者,回测收益自然被高估。基金研究同理:清盘的基金消失了,剩下的平均业绩看起来更好。

一个思想实验能说明它的威力:假设你研究”长期持有低价股”,用今天还存活的股票列表回测,那些跌到低价后一路退市归零的公司全都不在你的样本里——你看到的低价股个个都”熬过来了”,结论自然严重失真。

对策:

  • 使用包含退市股票的全历史股票池,或至少明确声明样本的局限;
  • 股票池的成分要按当时的成分取,比如回测沪深 300 策略,要用每个时点的历史成分股名单,而不是今天的名单;
  • 入门阶段用宽基 ETF 做实验可以绕开大部分幸存者偏差问题,这也是我们反复推荐它的原因之一。

忽略成本与流动性:纸面收益的漏损#

回测里一行 position * ret 背后,真实世界要付出佣金、印花税(卖出时)、买卖价差和冲击成本。换手越高的策略,被成本侵蚀得越狠——一个每天换仓的策略,年化换手可能高达几十倍,成本足以吃掉全部纸面利润。

流动性问题则更隐蔽:涨停板买不进、跌停板卖不出、小盘股挂单量不足,这些回测默认”都能成交”的假设在实盘会失效。入门阶段的务实做法:

  • 每次换仓按一个偏保守的固定费率(含冲击成本的估计)扣减;
  • 优先在宽基 ETF 等高流动性品种上做实验;
  • 对涨跌停日的成交做保守处理,例如禁止在涨停日买入。

过拟合:把噪声当规律#

过拟合是指策略”记住”了历史数据中的偶然模式。参数试得越多、规则加得越细,样本内表现越好、样本外越糟。基本防线是样本内外划分

train = data.loc[:'2022-12-31'] # 样本内:允许调参
test = data.loc['2023-01-01':] # 样本外:只允许最终验证一次
# 在 train 上选定参数后,用同一套参数在 test 上跑
# 如果对着 test 的结果反复改参数,test 就失效了

关键纪律是:样本外数据只能”揭榜”一次。如果你看了样本外结果不满意、回头改参数再看一次,样本外实际上已经变成了样本内。

除了划分样本,还有几个判断过拟合的经验信号:规则条数越多越可疑(“均线金叉且成交量放大且周三除外”这类叠床架屋的条件,每加一条都是在缩小样本、放大巧合);策略逻辑讲不出经济直觉、只能用”数据显示如此”来辩护的,也要打问号。一个粗糙但有用的标准:如果你不能用两三句话向别人解释这个策略为什么应该赚钱,它大概率是拟合出来的。

回测自查清单#

在把任何回测结论讲给别人(或自己)之前,过一遍这张表:

检查项通过标准
信息时点所有信号只用决策时点前可得的数据,信号已 shift
股票池包含退市/ST,成分按历史时点取
成交假设涨跌停、停牌日不假设可成交
成本已扣佣金、印花税及冲击成本估计
参数尝试过的参数组合数有记录,结果对参数平滑
样本外留了未参与调参的时间段,且只验证了一次
可复现换台机器重跑,结果一致
逻辑能用两三句话说清策略为什么应该有效

这份清单的正确用法不是”想起来就看一眼”,而是把它变成流程:每次准备下结论前逐项打钩,任何一项不过关,结论就降级为”待验证”。回测的意义从来不是预测未来,而是淘汰坏想法——一个诚实的、结果平庸的回测,比一个漂亮但漏洞百出的回测有价值得多。

本课小结#

  • 未来函数的判断标准:那个时点这条信息是否真的可得。
  • 幸存者偏差来自”用今天的名单回测昨天”,股票池要按历史时点构建。
  • 成本与流动性会系统性侵蚀高换手策略,回测必须扣减。
  • 样本外数据只能用一次,反复回看等于没有样本外。
  • 好习惯是把自查清单变成每次回测的固定流程。

动手练习:把上一课的双均线回测改出一个”错误版本”——去掉 shift(1),让信号当日生效——对比两版净值曲线的差异,感受未来函数能把结果美化到什么程度。