回测很好看,为什么一到实盘就缩水?
做量化研究最让人兴奋的时刻,通常是回测跑完以后,屏幕上出现一条平滑向上的净值曲线。
年化收益很高,最大回撤不大,夏普比率也不错。看完以后很容易产生一种感觉:只要把代码放进实盘,接下来就是等待收益到账。
真正运行一段时间后,却常常发现结果完全不是一回事。
回测里可以买到的价格,实盘不一定能成交;回测里完整的历史数据,当时可能根本看不到;回测里表现最好的参数,也可能只是碰巧适合过去。
回测和实盘之间不是隔着一条缝,而是隔着一层层摩擦。
回测不是预测,而是一次历史模拟
回测回答的问题是:
如果过去拥有现在写好的规则,并且能够按照设定的成交条件执行,结果可能怎样?
它并不能直接证明:
- 这个规律未来一定存在;
- 订单能够按照模拟价格成交;
- 研究过程中没有使用未来信息;
- 策略参数不是为这段历史专门挑选的;
- 实盘时能够承受同样的回撤并坚持执行。
美国SEC披露文件在说明假设回测时,也反复强调两个限制:回测规则可能带有事后视角,而且不同建模方法可能得到完全不同的结果。SEC关于假设回测局限性的披露
因此,回测更适合用来排除明显不合理的想法,而不是给未来收益盖章。
第一层损耗:成交价格太理想
很多回测默认使用开盘价、收盘价或某一分钟价格成交,但实盘订单提交以后,还要经过排队、撮合和价格变化。
假设策略在09:30看到开盘价后发出买单,回测却仍按09:30的开盘价成交,相当于同时知道价格并瞬间完成交易。实盘里很难做到。
常见损耗包括:
- 买入时比回测价格更高;
- 卖出时比回测价格更低;
- 涨停买不到、跌停卖不出;
- 小市值股票挂单深度不足;
- 大额订单对市场价格产生冲击;
- 部分成交以后,剩余订单价格继续变化。
这就是滑点和冲击成本。
对于低换手、流动性好的ETF策略,单次误差可能不明显;但对于每天调仓、持仓集中或交易微盘股的策略,微小误差会反复累积。
有研究指出,一些利用小公司短周期可预测性的纸面策略,其收益可能被交易成本完全吞没。《Review of Financial Studies》关于交易策略成本的研究
第二层损耗:费用写了,但没有写全
不少回测已经设置佣金和印花税,于是认为成本问题已经解决。
其实真实交易成本远不止手续费:
| 成本 | 回测中是否容易遗漏 |
|---|---|
| 佣金、印花税 | 通常会设置 |
| 买卖价差 | 经常遗漏 |
| 滑点 | 容易低估 |
| 市场冲击 | 很难准确模拟 |
| 撤单与未成交 | 经常忽略 |
| 停牌、涨跌停限制 | 处理方式差异很大 |
| 资金占用和最低佣金 | 容易被简化 |
最简单的压力测试,是把交易成本故意设得更差一些。如果成本提高后策略立刻从盈利变成亏损,说明利润空间本来就很薄。
第三层损耗:数据偷偷穿越了
未来函数不一定表现为直接读取明天的价格。更常见的情况隐藏在数据细节里。
例如:
- 用当天收盘后才能确定的数据,在当天收盘价成交;
- 使用后来修订过的财务数据;
- 按今天的指数成分股回测十年前;
- 股票池只保留目前仍然上市的公司;
- 用完整历史计算标准化,再回到过去选股;
- 忽略已经退市、停牌或更名的失败样本。
这些问题会让回测中的策略拥有当时投资者不可能掌握的信息。
判断是否穿越,可以对每个变量追问一句:在发出订单的那个时间点,这个数据真的已经公开并且可以读取了吗?
如果答案不确定,就应该把数据至少延迟一个可交易周期再测试。
第四层损耗:参数是从历史里挑出来的
假设我们依次测试5日、10日、20日、30日、60日动能,再测试不同止损线、持仓数量和调仓频率,最后只展示表现最好的组合。
即使所有策略原本都没有预测能力,也可能有某一个参数组合因为运气而表现很好。
Bailey、Borwein、López de Prado和Zhu关于回测过度拟合的研究指出,测试的策略配置越多,挑中偶然优秀结果的概率就越高;如果不报告总共尝试过多少种配置,外部观察者很难判断结果的可靠程度。论文:The Effects of Backtest Overfitting on Out-of-Sample Performance
真正危险的不是“调参数”本身,而是:
- 在全部历史数据上反复调整;
- 每次都根据结果继续修改;
- 最后仍把同一段数据称为验证结果。
这样做相当于一边看答案,一边修改考试题。
第五层损耗:策略容量被忽略
一套策略用10万元回测时,可能可以轻松成交;资金增加到100万元、1000万元以后,结果未必还能保持。
策略容量取决于:
- 标的日均成交额;
- 买卖盘深度;
- 单只股票分配金额;
- 调仓是否集中在同一时间;
- 策略是否与其他资金使用相似信号;
- 极端行情下的真实流动性。
微盘股策略对此尤其敏感。正常时期看起来流动性尚可,市场恐慌时却可能同时出现跌停和买盘消失。
回测只看到价格序列,实盘面对的却是“这个价格旁边到底有多少数量可以成交”。
第六层损耗:市场环境改变了
策略依赖的规律可能来自某一种市场结构。
例如,小市值溢价、涨停延续、行业轮动速度、ETF溢价和资金抱团程度,都可能随着监管、参与者和交易制度变化而变化。
历史上有效并不等于逻辑已经失效,但我们需要分清两种情况:
- 策略暂时处于正常回撤;
- 支撑策略的市场机制已经改变。
这也是为什么只看十年总收益不够。应该把回测按年份、牛熊阶段、流动性环境和制度变化拆开观察。
第七层损耗:人并不是回测程序
回测可以毫无感情地承受40%的最大回撤,然后继续执行。
真实账户下跌时,人会怀疑代码、修改参数、暂停策略,或者在最低点手动清仓。
这不只是心理问题,也是一种实盘风险。
如果策略的理论回撤已经超过自己的承受能力,那么即使长期逻辑正确,实际也很可能坚持不到收益恢复。
因此,策略仓位不应按照“怎样收益最高”决定,而应该按照“多大损失仍能正常执行”决定。
一条漂亮曲线是怎样缩水的?
上图只是结构示意,并不是任何真实策略的收益数据。它想表达的是:回测优势需要足够厚,才能穿过真实交易中的多层损耗。
如果一套策略只在最理想假设下略微盈利,那么它几乎没有犯错空间。相反,如果在更差成交价、更高成本、不同参数和不同时间区间下仍然保持基本逻辑,结果才更值得继续观察。
我会怎样检查一套回测?
拿到一套看起来很漂亮的策略,我通常不会第一时间继续提高收益,而会先做这些破坏性测试:
- 成交延迟一根K线:检查信号是否依赖无法实现的成交价格。
- 提高滑点和手续费:观察策略对交易成本是否敏感。
- 更换相邻参数:确认结果不是某一个数字形成的尖峰。
- 拆分样本内外:调参使用一段数据,验证使用另一段数据。
- 保留退市和失败样本:避免幸存者偏差。
- 限制成交容量:不允许订单占标的成交量过高。
- 逐年查看收益:判断利润是否集中在少数特殊年份。
- 做模拟交易:用真实时钟检验数据、信号和订单流程。
好的回测不是怎么折腾都不回撤,而是合理改变假设以后,策略仍然保持相似的行为和可以解释的收益来源。
我的理解
回测最重要的作用,不是证明我们找到了印钞机,而是帮助我们理解策略在哪些环境下赚钱、在哪些情况下会失败。
一条太完美的曲线应该让人兴奋,也应该让人警惕。
因为真实市场里有手续费、有价差、有无法成交的订单,也有我们事先不知道的未来。实盘不会完全复制回测,这不是偶然,而是两者本来就在不同条件下运行。
我在博客展示延迟一天的模拟策略持仓,也是希望把“历史回测”和“持续运行记录”分开。前者告诉我们规则过去可能怎样,后者才能慢慢检验它离开历史样本以后是否仍然有效。
回测收益缩水并不可怕。真正可怕的是,我们不知道收益为什么缩水,却仍然把问题全部归结为运气不好。
免责声明: 本文仅用于量化研究与个人经验交流,不构成任何投资建议。历史回测和模拟结果不代表未来收益。
参考资料
- Bailey, D. H., Borwein, J., López de Prado, M., & Zhu, Q. J. The Effects of Backtest Overfitting on Out-of-Sample Performance.
- Lesmond, D. A., Schill, M. J., & Zhou, C. The Illusory Nature of Momentum Profits.
- SEC:Hypothetical Back-Tested Performance的局限性披露.