回测里的幸存者偏差怎么避免
做回测时,很多人把精力花在调参数和换模型上,却忽略了一件更底层的事:你拿到的这份历史数据,本身可能就已经被筛过一遍了。幸存者偏差就是其中最典型的一种——表现差的样本在历史上消失了,留在数据集里的都是活下来的那一批,于是回测结果天然偏乐观。
先搞清楚偏差是怎么进来的
假设你要回测一个选股逻辑,所用的数据集只包含当前仍在交易的标的。那些中途退市、被并购、长期停牌后摘牌的样本,根本不在表里。你的策略在历史上买入过它们吗?大概率买过。但如果数据里没有它们,回测就当作这笔交易没发生过。
判断方法很直接,问自己三个问题:
- 这份数据的时间起点是什么时候,是从现在往回截取的吗?
- 数据里有没有退市、终止、失效这一类状态的字段?
- 如果某种标的在历史上消失了,它在你的数据集里是以什么形式存在?
只要第三个问题答不上来,就说明偏差很可能已经混进来了。
用「历史成分」而不是「当前成分」
很多数据源默认给你的是当前仍在存续的样本清单。用它去跑五年前的回测,等于用今天的结果去反推过去,方向就是错的。
正确做法是按时间点还原样本集合。比如在某一年做回测,就只使用那一年当时确实存在的样本。具体到操作上:
- 请求数据时带上时间截面参数,拿那个时点的清单,而不是最新清单。
- 如果数据源不直接提供,就用上市日期和退市日期两个字段自己筛。
- 对指数类回测,尽量找成分股的历史变动记录,而不是拿当前成分股列表硬套。
这一步做起来麻烦,但它决定了后面所有结论有没有意义。
处理退市样本的价格与状态
退市不等于归零,也不等于按最后价格成交。不同类型的终止事件,现金回收的比例差别很大。回测里如果一律按最后收盘价了结,结果会偏离实际。
比较稳妥的做法是分情况标注:
- 正常退市或转板,按最后可交易日的价格处理,必要时加一点滑点。
- 被并购或换股的,按当时的换股比例或现金对价折算,不要直接沿用停牌前的价格。
- 长期停牌后终止的,单独标记,不要混进常规交易记录。
哪怕只能拿到粗略的回收比例,也比假装这些样本不存在要好。
设定一个「反事实」对照组
光修数据还不够,还需要一个参照来判断偏差有没有被压下去。最简单的办法是做两次回测:一次用包含退市样本的全量数据,一次用只保留存活样本的数据。两者的差距,就是幸存者偏差大致的影响幅度。
如果差距很小,说明你的策略对样本存续不敏感,可以放心一些。如果差距很大,那就得回头看策略逻辑本身是不是过度依赖「活下来的那批标的」。这个对照不需要多复杂,能跑出两条曲线做对比就够了。
把偏差检查固定成流程
这种事靠临时想起来是做不牢的。把它变成一个固定动作:
- 每次拿到新数据集,先看字段里有没有退市日期、终止状态。
- 每次跑回测,同时跑一遍剔除存活样本的版本。
- 在结果记录里留下样本口径的说明,方便后面复核。
偏差不会因为你没看见就消失。把这几步例行化,回测结果的可信度会明显不同。
相关文章
动手前先建个基准线
这篇讲怎么在开始优化数据流程之前,先建立一个可比较的基准线。内容包括选指标、定口径、留出对照样本,以及基准线失效时怎么判断,让后续每次改动都有据可查。
试得越多越容易碰巧成功
本文讲多重检验下的过拟合问题:为什么试的策略越多,越容易撞上一个看似有效的结果。给出回测中识别与处理这类假阳性的具体做法,包括记录试错次数、样本切分、参数敏感度检查与效应量估计。
训练集和验证集该怎么分
数据集划分没有万能比例,关键看样本量、时间结构和类别分布。本文给出随机划分、分层抽样与按时间切分的判断标准,并说明验证集该留多大、如何避免信息泄露。