背景知识:时间序列交叉验证(Purged CV)
"标准 K-Fold 用在金融数据上,就像用明天的报纸预测今天的股价。"
为什么标准交叉验证在金融中失效?
标准 K-Fold 的假设:样本之间相互独立。
金融数据的现实:
- 今天的收益率和昨天高度相关(自相关)
- 用于预测第 100 天的特征可能包含第 99、98 天的信息
- 标签(收益)往往涉及多天窗口
结果:信息从测试集"泄漏"到训练集,过拟合严重。
一个具体的泄漏案例
场景:预测未来 5 天收益
数据:第 1-100 天
标签:ret_5d[t] = (close[t+5] - close[t]) / close[t]
样本 95 的标签用到了:第 95-100 天的价格
样本 96 的标签用到了:第 96-101 天的价格(部分重叠!)
标准 K-Fold 可能:
- 训练集包含样本 95(标签涉及 95-100 天)
- 测试集包含样本 96(标签涉及 96-101 天)
- 96-100 天的信息同时在训练和测试中!
三种时间序列 CV 方法
方法一:简单时间切分(Walk-Forward)
Fold 1: 训练 [1-60] → 测试 [61-70]
Fold 2: 训练 [1-70] → 测试 [71-80]
Fold 3: 训练 [1-80] → 测试 [81-90]
Fold 4: 训练 [1-90] → 测试 [91-100]
优点:简单,无未来信息泄漏 缺点:训练集越来越大,早期数据可能已失效
方法二:滑动窗口(Rolling Window)
Fold 1: 训练 [1-60] → 测试 [61-70]
Fold 2: 训练 [11-70] → 测试 [71-80]
Fold 3: 训练 [21-80] → 测试 [81-90]
Fold 4: 训练 [31-90] → 测试 [91-100]
优点:训练集大小固定,使用最近的数据 缺点:样本利用率低
方法三:Purged K-Fold(推荐)
在标准 K-Fold 基础上:
- 时间排序:按时间顺序分 K 折
- Purge(清除):删除训练集中与测试集标签重叠的样本
- Embargo(隔离):在清除区外再留安全边界
Purged CV 详解
问题设定:
- 特征窗口:过去 20 天
- 标签窗口:未来 5 天
- 数据:第 1-100 天
步骤:
1. 分折(假设 5 折)
Fold 3 测试集:第 41-60 天
2. 识别泄漏区
测试集标签涉及:第 41-65 天(41+5-1 到 60+5-1)
训练特征涉及:第 21-40 天也可能影响测试
3. Purge(清除)
删除训练集中标签与测试集重叠的样本
删除:第 36-40 天(标签涉及 36-45,与 41-65 重叠)
4. Embargo(隔离)
再删除 Purge 边界之后的 N 个样本
假设 Embargo = 5 天,删除第 41-45 天的训练样本
可视化:
Embargo 的作用
为什么需要 Embargo?
即使清除了标签重叠,仍可能存在:
- 特征的自相关(今天的 MA20 和明天的 MA20 几乎一样)
- 信息传播延迟(新闻影响持续数天)
- 市场状态持续性(趋势不会一天内消失)
Embargo 长度建议:
| 数据频率 | 标签窗口 | 建议 Embargo |
|---|---|---|
| 日线 | 5 天 | 3-5 天 |
| 日线 | 20 天 | 10-20 天 |
| 分钟线 | 1 小时 | 30-60 分钟 |
| Tick | 100 Tick | 50-100 Tick |
经验法则:Embargo ≈ 0.5 × 标签窗口
实际计算示例
设定:
- 数据量:1000 个样本(日线 4 年)
- 标签:未来 10 天收益
- K = 5 折
- Embargo = 5 天
Fold 分配:
| Fold | 原始测试区 | Purge 删除 | Embargo 删除 | 有效训练样本 |
|---|---|---|---|---|
| 1 | 1-200 | 无 | 无 | 210-1000 (790) |
| 2 | 201-400 | 191-200 | 401-405 | 1-190, 406-1000 (785) |
| 3 | 401-600 | 391-400 | 601-605 | 1-390, 606-1000 (785) |
| 4 | 601-800 | 591-600 | 801-805 | 1-590, 806-1000 (785) |
| 5 | 801-1000 | 791-800 | 无 | 1-790 (790) |
注意:每折损失约 15 个样本用于防止泄漏。
与其他方法对比
| 方法 | 信息泄漏 | 样本利用率 | 计算复杂度 | 适用场景 |
|---|---|---|---|---|
| 标准 K-Fold | ❌ 严重 | 高 | 低 | 不适用金融 |
| 简单时间切分 | ✅ 无 | 中 | 低 | 快速验证 |
| 滚动窗口 | ✅ 无 | 低 | 中 | 策略稳定性测试 |
| Purged K-Fold | ✅ 无 | 较高 | 中 | 模型选择、超参调优 |
| Purged + Embargo | ✅ 无 | 中 | 中 | 最严格验证 |
多智能体视角
在多智能体系统中,不同 Agent 的训练需要不同的 CV 策略:
Signal Agent(预测 5 日收益):
- Purge: 标签窗口 5 天
- Embargo: 3 天
- 保守估计模型表现
Regime Agent(识别市场状态):
- Purge: 通常不需要(状态是当前的)
- Embargo: 较长(状态转换有惯性)
- 关注状态转换期的准确率
Risk Agent(预测波动率):
- Purge: 波动率窗口(如 20 天)
- Embargo: 5 天
- 波动率聚集性导致需要更长 Embargo
常见误区
误区一:用了 Purged CV 就不会过拟合
不对。Purged CV 只防止信息泄漏,不能防止:
- 特征过多导致的过拟合
- 数据窥探(反复测试直到找到好结果)
- 模型复杂度过高
误区二:Embargo 越长越好
不完全对。过长的 Embargo:
- 浪费有效训练样本
- 可能导致训练数据过于陈旧
- 增加计算成本
误区三:只需要在最终测试时用 Purged CV
错误。超参数调优时也必须用 Purged CV,否则会选出过拟合的参数。
实用建议
1. 检查是否需要 Purge
需要 Purge 的情况:
- 标签涉及多天窗口(如未来 N 天收益)
- 特征涉及长窗口(如 60 日均线)
- 样本间存在重叠
不太需要 Purge 的情况:
- 标签是瞬时的(如下一 Tick 方向)
- 样本完全独立(如不同股票的截面)
2. 验证 Purge 效果
对比实验:
1. 用标准 K-Fold 训练,记录测试准确率
2. 用 Purged K-Fold 训练,记录测试准确率
3. 差异越大,说明原来泄漏越严重
3. 保留完全独立的测试集
数据分配:
- 70%:Purged K-Fold 用于模型选择和超参调优
- 30%:完全隔离的最终测试集,只用一次
总结
| 要点 | 说明 |
|---|---|
| 核心问题 | 时间序列样本不独立,标准 CV 导致信息泄漏 |
| Purge 作用 | 删除训练集中与测试标签重叠的样本 |
| Embargo 作用 | 在 Purge 边界外增加安全缓冲 |
| 推荐方法 | Purged K-Fold + Embargo |
| 验证方式 | 对比标准 CV 和 Purged CV 结果差异 |