CUSUM 事件过滤器:只在市场偏离足够大时才采样
逐日开训练样本的隐性成本可精确计量:H=20 标注下相邻标签共享 95% 收益路径,1430 个名义样本的有效独立样本量只有 72.5——模型看到的是同一段行情复印 20 遍。CUSUM 过滤器(Page 1954 质量控制)只在累计偏离越过阈值时开样本:对积累到位的漂移敏感、对反复横跳的噪声免疫,触发即清零天然不重复计数。1500 日三区制模拟实测:固定阈值 h=3% 在高波动段事件密度爆炸 2.4 倍(采样节奏被波动率劫持),换 h=2.5×EWMA σ 自适应后密度回归均匀;CUSUM 用 17% 样本量保住 102% 有效独立信息,单标签唯一性 0.051→0.314 提升 6 倍。AFML 标准管线:bar→CUSUM→三重障碍→元标注四级串联。A 股:日频 CUSUM 天然适配 T+1,涨跌停需暂停累计器(中高阶)
一句话版本#
逐日给模型开训练样本,等于把同一段行情复印 20 遍喂给它——1430 个名义样本里有效独立信息只值 72 个。CUSUM 过滤器只在「累计偏离越过阈值」时开样本:用 17% 的样本量保住 102% 的有效信息,把训练集从复印件堆变成事件集。
上游还有一个没人问的问题#
这个系列走到现在,数据端的时钟已经修得七七八八:成交量时钟、美元 Bar、失衡 Bar,都在回答「怎么切分数据」。三重障碍法回答了「怎么标注样本」。但两者中间还夹着一个几乎没人认真问的问题:
在哪些时点,值得开一个训练样本?
绝大多数金融 ML 项目的默认答案是「每天都开」:每个交易日取一次特征,配一个未来 H 日的标签。这个默认选择的成本是隐性的,但可以精确计量。
假设标注视野 H=20。今天的标签覆盖未来 20 天的收益路径,明天的标签覆盖其中 19 天——相邻两个样本共享 95% 的信息。López de Prado 在 AFML 中给出了量化工具:对每个时点 ,数一数有多少个标签的区间覆盖它(记作 concurrency ),则标签 的平均唯一性为
全体标签唯一性之和就是有效独立样本量。逐日采样、H=20 时每个时点被约 20 个标签覆盖,单标签唯一性约 1/20——1430 个名义样本,有效样本量只有 72。你以为在用千级样本训练,实际的统计功效是两位数的;交叉验证的方差估计、特征重要性的显著性、早停的判据,全部建立在虚胖的样本量上。
解决思路不是修标签(三重障碍已经做了),而是别在信息重叠的时点开样本。这就需要一个事件过滤器。
CUSUM:质量控制车间里借来的工具#
CUSUM(Cumulative Sum)滤波器是 E. S. Page 1954 年为工业质量控制发明的:监测流水线上的测量值,当累计偏离超过容忍度时报警——它的设计目标就是对「持续的小漂移」敏感,对「无害的单次噪声」免疫。
搬到价格序列上,对称版 CUSUM 维护两个累计器:
任一侧越过阈值( 或 )就记录一个事件,两个累计器清零,重新积累。
import numpy as np
def cusum_filter(logp: np.ndarray, h) -> np.ndarray:
"""对称 CUSUM 事件过滤器。
logp: 对数价格序列;h: 阈值(标量或逐日数组,如 2.5*EWMA波动率)。
返回事件发生的索引。"""
events, s_pos, s_neg = [], 0.0, 0.0
diff = np.diff(logp)
h_arr = np.full(len(diff), h) if np.isscalar(h) else h[1:]
for i, d in enumerate(diff):
s_pos = max(0.0, s_pos + d)
s_neg = min(0.0, s_neg + d)
if s_pos >= h_arr[i]:
events.append(i + 1); s_pos = 0.0
elif s_neg <= -h_arr[i]:
events.append(i + 1); s_neg = 0.0
return np.array(events)python注意 max(0, ·) 这个细节:上行累计器在价格回落时会被拖回零但不会变负——它只记「从最近低点算起涨了多少」,不给反向波动预支额度。这正是 CUSUM 与「20 日动量超过 3%」这类滚动窗口规则的本质区别:滚动窗口有固定回看期,同一根大阳线会在窗口滑过时反复触发;CUSUM 事件触发后立即清零,每个事件消耗掉自己那份偏离,天然不重复计数。均值回复的假突破(涨 2% 跌 2% 反复横跳)在 CUSUM 里永远攒不够阈值——它过滤掉的恰恰是最没有标注价值的噪声时点。
实验:三区制市场里的两种阈值#
模拟 1500 个交易日,三段区制:前段横盘(μ=0, σ=1%)、中段上升趋势(μ=+0.12%/日)、后段高波动下跌(μ=-0.15%/日, σ=2.2%)。对比固定阈值 h=3% 与波动率自适应阈值 h=2.5×EWMA σ(λ=0.94)。
发现一:固定阈值的采样节奏被波动率劫持#


固定阈值 h=3% 共触发 211 个事件,但分布严重失衡:高波动段密度 25 事件/百日,横盘段只有 10.4——差 2.4 倍。原因很机械:σ=2.2% 的日子里随机游走本身就频繁越过 3% 的累计线,事件里大量是「波动大」而非「有漂移」。这和三重障碍篇里固定收益阈值的病灶同源:任何以固定百分比为界的规则,在波动率区制切换时都会变味——低波动期规则太松触发不了,高波动期规则太紧被噪声打穿。
自适应阈值 h=2.5σ 把事件密度拉回均匀(高波动段 16.3 vs 横盘段 15.6/百日):高波动期阈值自动放宽,要求「相对当前噪声水平足够大」的偏离才算事件。此时事件的语义才是干净的——每个事件代表一次同等统计显著性的偏离,而不是波动率的回声。趋势段(绿色区域)事件沿上涨路径均匀铺开,每次趋势推进 2.5 个标准差就记录一次,正是趋势跟踪类标签最想要的采样点。
发现二:17% 的样本,102% 的信息#
对自适应 CUSUM 的 236 个事件和逐日采样的 1430 个时点,分别计算 H=20 视野下的标签唯一性:

| 采样方式 | 名义样本量 | 单标签平均唯一性 | 有效独立样本量 |
|---|---|---|---|
| 逐日采样 | 1430 | 0.051 | 72.5 |
| CUSUM 事件采样 | 236 | 0.314 | 74.1 |
这是本文最重要的一张表。逐日采样的 1430 个样本,有效信息只有 72.5 个——95% 的样本是冗余复印件。CUSUM 用 236 个样本(17% 的量)拿到 74.1 的有效信息(102%),单标签唯一性从 0.051 抬升到 0.314,6 倍提升。
对训练管线的连锁收益是实打实的:
- 交叉验证不再自欺:重叠样本落进不同 fold 时,验证集和训练集共享收益路径——泄漏被伪装成泛化能力。样本独立性提升 6 倍后,即使配合 Purged CV,需要清除的样本也少得多;
- Bagging 恢复效力:bootstrap 抽样在高冗余样本上抽来抽去都是同一段行情,子模型高度相关,集成的方差缩减名存实亡。AFML 提出序列 bootstrap 来修这个问题,而 CUSUM 从源头减少了对修补的依赖;
- 算力省 83%:三重障碍标注、特征计算、模型训练的开销都按样本数线性缩放。
值得强调:CUSUM 不是「压缩样本量的有损妥协」,而是剔除了本来就不携带独立信息的时点。有效样本量不降反微升(74.1 vs 72.5),因为事件点错开分布,区间重叠远少于逐日紧邻。
与家族前作的分工#
至此这个系列的采样工具箱可以画出完整流水线:
| 层 | 工具 | 回答的问题 |
|---|---|---|
| 数据结构层 | 成交量/美元/失衡 Bar | 用什么时钟切分原始数据 |
| 事件层 | CUSUM 过滤器 | 哪些时点值得开样本 |
| 标注层 | 三重障碍法 | 每个样本怎么标对错 |
| 决策层 | 元标注 | 信号该不该信、信多少 |
AFML 的标准管线正是四级串联:信息驱动 bar 上跑 CUSUM 选事件,事件点上用三重障碍标注,再往上叠元标注。CUSUM 与失衡 Bar 看似都在「检测异常」,但分工不同:失衡 Bar 监听订单流方向(微观结构信号,tick 级),CUSUM 监听价格漂移积累(趋势信号,bar 级)——前者是数据的时钟,后者是标注的开关,可以叠加使用。
三个使用警告#
1. 阈值校准的前视红线。 自适应阈值必须用 EWMA 或滚动窗口从过去数据估计波动率。用全样本 σ 校准 h 意味着 2020 年的事件定义里混入了 2024 年的波动信息——这条红线在本系列已经出现第三次,因为它是回测虚高最隐蔽的来源。
2. 倍数 m 的选择余地不大。 h = m×σ 中 m 取 2-3 是合理区间:m 太小(<1.5)事件退化为逐日采样,冗余问题回归;m 太大(>4)事件太稀,趋势段中间的推进被整段吞掉。和三重障碍的参数纪律相同——不要对 m 做网格搜索,事件定义参数一旦进入优化循环,选出的就是对样本内路径过拟合的采样方式。
3. CUSUM 事件 ≠ 交易信号。 事件只说「这里发生了值得标注的偏离」,不说方向对错——涨 2.5σ 触发的事件,三重障碍标注出来可能是 -1(随后回落止损)。把 CUSUM 触发直接当买入信号,等于跳过了整个 ML 层,退化成一个没有风控的动量追涨策略。
A 股落地注记#
- T+1 天然适配:日频 CUSUM 事件天然落在日线上,信号确认后次日开盘执行,与 T+1 制度无缝衔接——这是少数不需要为 A 股特殊改造的工具。
- 涨跌停的累计器污染:连续涨停期间价格被封在涨幅限制上,CUSUM 会在开板后瞬间触发一连串事件,但这些事件点根本无法以合理价格成交。工程处理:触及涨跌停的日子暂停累计器更新,或将其间触发的事件标记为不可交易。
- 停牌复牌跳空:长期停牌后复牌的一次性跳空会瞬间打穿任何阈值。这类「事件」是公司行为不是市场漂移,应在数据清洗层剔除,而非让 CUSUM 报警。
下一篇预告:样本选好了、标签打好了,下一个问题是特征端——分数差分(fractional differentiation)如何在保留记忆的同时让价格序列平稳。