3. 样本外测试:检验策略的试金石

说实话,我见过太多策略在回测里跑得漂亮,一上实盘就崩盘。原因很简单——过拟合了。那怎么判断你的策略是不是在「死记硬背」历史数据呢?样本外测试就是最好的照妖镜。

我个人习惯把样本外测试看作策略的「高考」。你在样本内训练、调参,就像平时做练习题。但真正能不能考上大学,得看高考成绩——也就是样本外的表现。你想想看,如果平时模拟考次次满分,高考却不及格,那肯定是学习方法出了问题。

3.1 什么是样本外测试

样本外测试,说白了就是把数据分成两段:一段用来开发策略(样本内),一段用来验证策略(样本外)。样本内的数据你随便折腾,但样本外的数据在开发阶段绝对不能碰。

核心原则:样本外数据必须保持「纯净」——在策略开发、参数优化、特征选择等任何环节都不能被使用。

我在项目中遇到过不少新手,嘴上说做了样本外测试,实际上偷偷看了样本外的数据来调参数。这叫什么?这叫作弊。样本外测试的意义就在于模拟未知的未来,你提前看了答案,那测试还有什么意义?

3.2 数据划分的常见方法

数据怎么切?这里有几个主流做法,我按推荐程度排个序:

方法 适用场景 优点 缺点
简单时间分割 数据量充足 简单直观 只验证一个时间段
滚动窗口 策略会定期重训 多次验证,更稳健 计算量大
扩展窗口 长期策略 训练数据越来越多 早期样本少
组合分割 多市场、多品种 全面验证 实现复杂

简单时间分割是最常用的。比如你有5年数据,前4年做样本内,最后1年做样本外。比例一般是70%/30%或80%/20%。我个人习惯用80/20,因为高频交易的数据量通常够大,20%的样本外数据已经足够检验了。

滚动窗口更适合策略需要定期更新的场景。举个例子:用过去1年数据训练,预测未来1个月,然后窗口向前滚动1个月,重复这个过程。这样你能得到12个样本外测试结果,统计意义更强。

我的经验:如果你做的是高频策略(比如Tick级别),建议用滚动窗口。因为市场结构变化快,单一时间段的样本外测试可能不够有说服力。

3.3 样本外测试的评估指标

样本外跑完了,怎么判断过不过关?别只看收益率。我见过太多人盯着年化收益不放,结果策略在样本外收益还行,但最大回撤翻了一倍。这能叫好策略吗?

我一般会看这几个指标:

  • 收益衰减率:样本外收益 / 样本内收益。理想值在0.7以上。低于0.5就要警惕了。
  • 夏普比率变化:样本外夏普比样本内下降不超过30%。
  • 最大回撤比:样本外最大回撤 / 样本内最大回撤。超过1.5倍就危险了。
  • 胜率稳定性:样本外胜率与样本内相差不超过10个百分点。

避坑指南:我曾经犯过一个错误——样本外测试只跑了一次,结果还不错,就以为策略没问题。后来发现那段时间刚好是趋势行情,策略只是运气好。所以我现在至少要求做3个不同时间段的样本外测试,或者用滚动窗口做多次验证。

3.4 样本外测试的常见陷阱

嗯,这里要注意几个坑:

  1. 数据泄露:这是最致命的。比如你用未来数据计算了某个指标,或者样本外数据被无意中用于特征工程。我曾经见过有人用全体数据的均值和标准差做标准化,结果样本外数据的信息提前泄露了。
  2. 幸存者偏差:只测试了存活下来的股票或合约。退市的、被摘牌的都不在数据集里,这会让策略看起来比实际好。
  3. 过度的样本外调参:样本外表现不好,就回去改参数,改完再测。反复几次后,样本外其实已经变成了新的样本内。这叫「数据窥探」。
  4. 时间跨度不够:样本外只有几个月,可能刚好碰上特殊行情。我建议样本外至少覆盖一个完整的市场周期,比如包含牛熊转换。

3.5 实战:一个简单的样本外测试流程

下面是我个人常用的样本外测试代码框架。它不复杂,但很实用:

import pandas as pd
import numpy as np
from sklearn.model_selection import TimeSeriesSplit

# 假设你有5年的日线数据
data = pd.read_csv('price_data.csv', index_col='date', parse_dates=True)

# 方法1:简单时间分割
train_end = int(len(data) * 0.8)
train_data = data.iloc[:train_end]
test_data = data.iloc[train_end:]

# 在train_data上开发策略
# 在test_data上验证策略

# 方法2:滚动窗口验证
tscv = TimeSeriesSplit(n_splits=5)

for train_idx, test_idx in tscv.split(data):
    train = data.iloc[train_idx]
    test = data.iloc[test_idx]
    
    # 训练策略
    # 测试策略
    # 记录每次的测试结果
    
# 汇总多次测试结果
# 计算平均收益、夏普比率、最大回撤等

小技巧:我习惯在样本外测试时记录每次交易的详细信息。如果发现样本外的亏损交易集中在某个特定时间段或特定市场环境下,那说明策略可能只适用于特定条件。这时候就需要增加条件过滤,或者干脆放弃这个策略。

3.6 样本外测试的进阶技巧

如果你已经掌握了基础方法,可以试试这些进阶技巧:

  • 多市场验证:在A股开发的策略,拿到港股或美股上跑跑。如果表现差不多,说明策略抓住了市场的共性规律,而不是A股的特定噪声。
  • 参数敏感性测试:在样本外测试时,稍微改变一下参数值。如果策略表现剧烈波动,说明参数过拟合了。
  • 蒙特卡洛模拟:对样本外结果进行随机重采样,看看策略的收益分布是否稳定。如果95%的模拟结果都是亏损的,那样本外的正收益可能只是运气。

最后说一句:样本外测试不是万能的。它只能告诉你策略「没有明显过拟合」,但不能保证未来一定赚钱。但话说回来,连样本外测试都过不了的策略,你敢实盘吗?


公众号:蓝海资料掘金营,微信deep3321