halo 的技术博客

返回

一句话版本#

逐日给模型开训练样本,等于把同一段行情复印 20 遍喂给它——1430 个名义样本里有效独立信息只值 72 个。CUSUM 过滤器只在「累计偏离越过阈值」时开样本:用 17% 的样本量保住 102% 的有效信息,把训练集从复印件堆变成事件集。


上游还有一个没人问的问题#

这个系列走到现在,数据端的时钟已经修得七七八八:成交量时钟、美元 Bar、失衡 Bar,都在回答「怎么切分数据」。三重障碍法回答了「怎么标注样本」。但两者中间还夹着一个几乎没人认真问的问题:

在哪些时点,值得开一个训练样本?

绝大多数金融 ML 项目的默认答案是「每天都开」:每个交易日取一次特征,配一个未来 H 日的标签。这个默认选择的成本是隐性的,但可以精确计量。

假设标注视野 H=20。今天的标签覆盖未来 20 天的收益路径,明天的标签覆盖其中 19 天——相邻两个样本共享 95% 的信息。López de Prado 在 AFML 中给出了量化工具:对每个时点 tt,数一数有多少个标签的区间覆盖它(记作 concurrency ctc_t),则标签 ii 的平均唯一性为

uˉi=1Ht[ti,ti+H]1ct\bar{u}_i = \frac{1}{H}\sum_{t \in [t_i, t_i+H]} \frac{1}{c_t}

全体标签唯一性之和就是有效独立样本量。逐日采样、H=20 时每个时点被约 20 个标签覆盖,单标签唯一性约 1/20——1430 个名义样本,有效样本量只有 72。你以为在用千级样本训练,实际的统计功效是两位数的;交叉验证的方差估计、特征重要性的显著性、早停的判据,全部建立在虚胖的样本量上。

解决思路不是修标签(三重障碍已经做了),而是别在信息重叠的时点开样本。这就需要一个事件过滤器。

CUSUM:质量控制车间里借来的工具#

CUSUM(Cumulative Sum)滤波器是 E. S. Page 1954 年为工业质量控制发明的:监测流水线上的测量值,当累计偏离超过容忍度时报警——它的设计目标就是对「持续的小漂移」敏感,对「无害的单次噪声」免疫。

搬到价格序列上,对称版 CUSUM 维护两个累计器:

St+=max(0,  St1++Δlogpt),St=min(0,  St1+Δlogpt)S_t^+ = \max(0,\; S_{t-1}^+ + \Delta \log p_t), \qquad S_t^- = \min(0,\; S_{t-1}^- + \Delta \log p_t)

任一侧越过阈值(S+hS^+ \geq hShS^- \leq -h)就记录一个事件,两个累计器清零,重新积累。

注意 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)。

发现一:固定阈值的采样节奏被波动率劫持#

两种阈值下的 CUSUM 事件分布

事件密度对比

固定阈值 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 视野下的标签唯一性:

名义样本量 vs 有效独立样本量

采样方式名义样本量单标签平均唯一性有效独立样本量
逐日采样14300.05172.5
CUSUM 事件采样2360.31474.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)如何在保留记忆的同时让价格序列平稳。

CUSUM 事件过滤器:只在市场偏离足够大时才采样
https://blog.halo26812.eu.org/blog/cusum-filter-event-sampling
Author halo
Published at 2026年7月30日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨