Skip to content

第 14 讲:滚动样本外——walk-forward

本讲要点

一次切分只是入门;专业最低配至少要会滚动检验。


1. 为何单次切分不够

第 7 讲用「另一段历史」揭穿过拟合。若只做一次训练 / 测试:

  • 恰好切在某种行情边界上,结论可能运气很好或很差;
  • 无法看到样本外表现的分布(有多少折为正、离散有多大)。

Walk-forward(滚动前进)

步骤如下:

  1. 取一段训练窗,在窗内扫描参数,选出冠军;
  2. 冻结参数,在紧随其后的测试窗跑一遍;
  3. 窗口整体向前滚,重复多次;
  4. 报告各折测试收益,并可拼接样本外净值。

更严格的组合交叉验证(如 CPCV)存在;本课要求理解:为何需要滚动,以及如何读各折结果


2. 本讲设定

项目取值
训练窗24 个月
测试窗6 个月
滚动步长6 个月(与测试窗同长)
扫描网格动量回看月数 = 1 / 2 / 3;Top-N = 1 / 2 / 3
训练选优训练窗内 Sharpe 最高
成本0 bps(专注参数迁移;摩擦见第 15 讲)

共 3×3 = 9 组参数;每折只在训练窗内选优,测试窗禁止再调参。


3. 完整代码思路

python
TRAIN_MONTHS, TEST_MONTHS = 24, 6
MOM_GRID = (1, 2, 3)
TOP_GRID = (1, 2, 3)

oos_parts = []
i = 0
while i + TRAIN_MONTHS + TEST_MONTHS <= len(dates):
    train_idx = dates[i : i + TRAIN_MONTHS]
    test_idx = dates[i + TRAIN_MONTHS : i + TRAIN_MONTHS + TEST_MONTHS]

    best_sharpe, best = float("-inf"), None
    for mom in MOM_GRID:
        for top in TOP_GRID:
            ret = run_params(train_me, mom, top).loc[train_idx[0] : train_idx[-1]]
            s = sharpe(ret)
            if s > best_sharpe:
                best_sharpe, best = s, (mom, top)

    mom_b, top_b = best
    test_ret = run_params(me, mom_b, top_b).reindex(test_idx).dropna()
    oos_parts.append(test_ret)
    i += TEST_MONTHS

oos = pd.concat(oos_parts)  # 拼接样本外

完整可运行脚本:easy-quant/code/14_walk_forward.py

bash
python easy-quant/code/14_walk_forward.py

4. 运行结果

text
折1: 训练选 mom=1, top=1  训练收益 17.17%  测试收益 -4.04%
折2: 训练选 mom=1, top=1  训练收益 4.15%  测试收益 0.66%
折3: 训练选 mom=1, top=3  训练收益 1.07%  测试收益 7.17%
折4: 训练选 mom=3, top=1  训练收益 31.69%  测试收益 24.84%
折5: 训练选 mom=3, top=1  训练收益 42.79%  测试收益 35.36%
折6: 训练选 mom=3, top=1  训练收益 94.67%  测试收益 10.03%

滚动折数: 6
拼接样本外累计收益: 92.50%
拼接样本外 Sharpe: 1.03
全样本固定 mom=1, top=2 累计: 63.56%  (非样本外,仅对照)
测试窗收益为正的折数: 5/6
训练冠军训练收益测试收益
1mom=1, top=117.17%−4.04%
2mom=1, top=14.15%0.66%
3mom=1, top=31.07%7.17%
4mom=3, top=131.69%24.84%
5mom=3, top=142.79%35.36%
6mom=3, top=194.67%10.03%

walk-forward

读法:

  1. 第 1 折测试为负:即使整体拼接好看,仍有失效窗口——要看分布,不看单一幸运数字。
  2. 冠军参数在折间会变(top 与 mom 都会换),全样本死守 mom=1, top=2 只是其中一种选择。
  3. 拼接样本外累计与「全样本固定参数」不可直接比谁更神:路径、参数序列都不同;前者回答的是「按规则滚动选参后,样本外还在不在」。
  4. 仅 6 折、单一资产池,统计力度有限;课程达标线是会做、会读,不是宣称策略可上线。

5. 本讲小结

  • Walk-forward = 反复「训练选参 → 测试冻结 → 向前滚」
  • 关注各折测试收益的符号与离散,而非只报拼接总值
  • 下一讲:把理想成交换成含佣金与滑点的净值

上一讲:组合验收 · 下一讲:成本与滑点