halo 的技术博客

返回

一句话版本#

泡沫不是「涨太多」,是价格的生成机制换挡:从随机游走(涨跌无记忆)切换到爆炸性自回归(涨会引来更多涨)。SADF 把教科书里的单位根检验改造成一个滑动监测器,专门回答一个问题:最近这段行情,是不是已经进入自我强化模式?


「泡沫」需要一个可检验的定义#

「现在是不是泡沫」是金融市场上被问得最多、答得最烂的问题。烂的原因是大多数回答用的定义不可检验:「估值太贵」(多贵算太贵?)、「涨太快」(多快算太快?)、「脱离基本面」(基本面是哪个数?)。

计量经济学给过一个干净得多的定义。写一个最简单的自回归:

yt=ρyt1+εty_t = \rho \, y_{t-1} + \varepsilon_t

  • ρ=1\rho = 1:随机游走。今天的涨跌对明天没有约束力,价格是鞅,这是有效市场的底色。
  • ρ<1\rho < 1:均值回复。涨多了会被拉回来。
  • ρ>1\rho > 1爆炸过程。偏离会自我放大——涨引来追涨,追涨引来更高的价格。这是泡沫的数学签名。

这个定义的好处是它完全不依赖「合理估值」这种主观锚点。它只问一件事:价格偏离的动力学是收敛的、中性的、还是发散的。而 ρ\rho 是可以从数据里估计并检验的。

标准工具是 ADF(Augmented Dickey-Fuller)检验。但教科书版 ADF 有两个先天缺陷,让它没法直接拿来测泡沫——修掉这两个缺陷的过程,就是 SADF 的诞生史。

从 ADF 到 SADF:两处手术#

手术一:检验方向反过来。 教科书 ADF 是左尾检验——原假设「有单位根(ρ=1)」,备择假设「平稳(ρ<1)」,统计量越负越显著。测泡沫要的是右尾:备择假设换成「爆炸(ρ>1)」,统计量越越显著。检验统计量本身不用改,改的是你看哪一侧的分位数。

手术二:窗口滑动起来。 泡沫是局部现象——一段 1000 日的样本里,可能只有中间 200 日是爆炸的。全样本 ADF 把这 200 日和前后 800 日的随机游走搅在一起,爆炸信号被大量「正常样本」稀释。

Phillips 及合作者的方案(SADF,2011;GSADF/BSADF,2015):不固定窗口起点,把所有可能的起点都试一遍,取统计量的上确界。在每个观察时点 tt,对所有满足最小窗口长度的起点 t0t_0 计算 ADF 统计量,然后取最大值:

BSADFt=supt0[0,tτ]ADF(yt0:t)\text{BSADF}_t = \sup_{t_0 \in [0,\, t - \tau]} \text{ADF}(y_{t_0 : t})

直觉:如果最近 150 天在爆炸,那么起点恰好落在爆炸段开头的那个窗口会给出巨大的 ADF 统计量——取上确界保证这个窗口不会被平庸的窗口埋没。监测器只对「以当前时点结尾的某段子样本是否爆炸」敏感,历史上的死水完全不构成稀释。

代码骨架(滞后阶数取 0 的简化版,够说明机制):

起点扫描的 step=5 是纯粹的计算量妥协;生产环境用增量更新的回归可以做到逐点扫描。

受控实验:植入一段温和爆炸#

空谈机制不如做一个知道真相的实验。我构造了 1000 日的对数价格:

  • 第 1-500 日:随机游走 + 微弱漂移(正常市场)
  • 第 500-730 日:爆炸段,偏离项按 ρ=1.012\rho = 1.012 复利放大——注意这个 ρ 只比 1 大 1.2%,日线上肉眼几乎不可辨,这是对真实泡沫的诚实模拟(泡沫在早期从不敲锣打鼓)
  • 第 730-780 日:崩溃(负漂移 + 波动放大 1.8 倍)
  • 第 780-1000 日:回到随机游走

受控实验的价格路径

对这条路径跑 BSADF(最小窗口 100 日),临界值用 200 条纯随机游走路径蒙特卡洛模拟的 95% 分位(≈0.57——注意这个分布是非标准的,不能查正态或 t 分布表,临界值必须模拟,且依赖最小窗口和样本长度设定):

BSADF 统计量与报警时点

三个读数:

  1. 报警时点 t=565:爆炸从 t=500 开始,BSADF 在 65 个交易日后越过临界值。三个月的滞后——记住这个数字,后面要用它泼冷水。
  2. 爆炸段内峰值 11.3,临界值 0.57 的近 20 倍。一旦爆炸积累到可检测的程度,信号不是暧昧的,是压倒性的。
  3. 崩溃后迅速回落。BSADF 同时监测泡沫的生成与破灭——统计量从高位跳水本身就是「爆炸机制已终结」的信号,PSY 用这个性质给泡沫做起止日期的断代。

为什么起点必须滑动:双泡沫实验#

上面的实验里,锚定起点 t=0 的扩张窗 ADF(即原始 SADF 的单个窗口)其实也能测到第一轮泡沫。真正把「滑动起点」从优化变成刚需的,是样本里有不止一轮泡沫的场景——这正是 Phillips-Shi-Yu 2015 年那篇论文的核心动机。

第二个实验:1000 日里植入两轮泡沫(200-320 日、600-720 日),各自跟着崩溃段:

双泡沫场景:锚定起点 vs 滑动起点

结果是教科书级的对比:

监测器泡沫 2 段内峰值临界值结论
扩张窗 ADF(起点锚定 t=0)0.140.57完全失灵
BSADF(起点滑动)2.720.57正常报警

失灵的机制值得说透:第一轮泡沫崩溃后,窗口里躺着一段「暴涨然后暴跌」的完整回合——从 t=0 看过去,这段历史整体上更像均值回复而不是爆炸。当第二轮泡沫启动时,锚定起点的检验被迫拖着这段旧历史一起算,第一轮泡沫的尸体成了第二轮泡沫的掩体。BSADF 的滑动起点允许它把窗口起点挪到第一轮崩溃之后,轻装检验最近一段——峰值 2.72,干净利落。

真实市场里泡沫从来不是一次性事件(A 股 2007、2015;纳斯达克 2000、2021),所以实战中没有理由使用锚定起点的版本。

三盆冷水:这个工具不能做什么#

冷水一:65 日滞后意味着它是确认工具,不是预测工具。 BSADF 报警时,爆炸已经运行了三个月。它不能帮你「买在泡沫起点」;它能做的是在泡沫中段给你一个统计上严格的「当前机制是爆炸性的」确认——这对风控(该减仓的仓别拖)和策略切换(趋势跟踪在爆炸段该让位于什么)有价值,对抄底逃顶没价值。检测滞后可以通过缩短最小窗口来压缩,代价是误报率上升——这是硬权衡,没有免费午餐。

冷水二:临界值是设定依赖的。 换最小窗口、换样本长度、换滞后阶数,95% 分位都会动。任何声称「BSADF 大于某个通用数字就是泡沫」的用法都是错的——临界值必须针对你的设定重新模拟。这也意味着跨市场比较 BSADF 的绝对值没有意义,可比的是「相对自己临界值的超越程度」。

冷水三:它对慢牛沉默。 BSADF 检验的是自回归系数不是涨幅。一段漂移强劲但 ρ=1 的行情——每天期望涨 0.1%,但今天的涨不影响明天——可以翻倍而不触发任何报警。这是特性不是缺陷:这种行情在定义上不是自我强化的泡沫,它没有「必然内爆」的动力学结构。但如果你期望用 BSADF 捕捉一切大涨行情,你会失望。

AFML 的用法:特征,不是开关#

López de Prado 在 AFML 第十七章收录结构突变检验,给出的定位和直觉用法相反:不要把 BSADF 当择时开关(报警就清仓),要把它当特征喂给元标注的二级模型。

理由回到这个系列反复出现的架构:一级模型产生信号,二级模型判断「当前环境下这个信号值不值得信」。BSADF 序列恰好是对「当前环境」的一个高质量刻画——

  • 趋势跟踪信号在 BSADF 高企时胜率如何?(爆炸段趋势自我强化,可能更高)
  • 均值回复信号在 BSADF 从峰值回落时是什么表现?(机制切换期,历史规律最不可靠)

这些问题不需要你手工回答,把 BSADF 值放进二级模型的特征矩阵,让它自己学。相比「报警就清仓」的开关用法,特征用法保留了统计量的连续信息,也避免了对单一临界值的过度依赖。

# 元标注特征矩阵中加入结构突变信息
features['bsadf'] = bsadf_series
features['bsadf_chg_20d'] = bsadf_series.diff(20)   # 机制在增强还是衰减
features['bsadf_pct'] = bsadf_series.rolling(500).rank(pct=True)  # 相对历史分位
python

A 股落地注记#

  • 数据条件无障碍:日线收盘价 + 对数变换即可,BSADF 对数据的要求是这个系列里最低的。
  • 涨跌停的双向污染:连续涨停段的价格序列是被截断的爆炸过程(真实需求溢出到第二天),会让 ρ 的估计偏低、检测更滞后;连续跌停同理污染崩溃段的断代。对小盘股建议在检验前标记涨跌停日。
  • 2015 年是天然验证集:上证指数 2014-06 至 2015-06 的行情是文献里被 PSY 方法反复检验过的样本,自己实现后拿这段做冒烟测试——BSADF 应在 2014 年底至 2015 年 Q1 之间越过临界值,并在 6 月崩盘后跳水。
  • T+1 与择时的错配:即便你执意用报警做减仓开关,A 股 T+1 意味着信号日收盘确认、次日才能执行——把这一天滞后写进回测,爆炸段末端的单日波动足以显著改变结论。

定位与边界#

在 AFML 管线里,结构突变检验属于特征工程层:bar 采样 → 事件过滤 → 标注 → 特征(含 BSADF) → 元标注 → 仓位。它和 CUSUM 过滤器是近亲——都在监测「偏离是否积累到统计显著」——但 CUSUM 管的是采样时机,BSADF 管的是机制识别,一个是开关,一个是温度计。

它能做的:给「当前是否处于自我强化机制」一个可检验、可复现、带显著性水平的答案;给泡沫断代(起止日期);给二级模型提供环境特征。

它不能做的:预测泡沫何时开始(滞后 65 日)、预测泡沫何时破灭(报警持续期内随时可能崩也可能再翻倍)、识别不爆炸的慢牛。

把工具的边界说清楚,恰好是这个工具自己教的方法论:先定义可检验的假设,再谈市场观点。


本文实验代码基于 numpy/matplotlib,BSADF 实现为滞后 0 阶简化版,临界值经 200 路径蒙特卡洛模拟,参数见文中说明。系列相关篇目:CUSUM 事件过滤器元标注 Meta-Labeling

SADF 结构突变检验:实时监测价格序列的爆炸性泡沫
https://blog.halo26812.eu.org/blog/structural-breaks-sadf
Author halo
Published at 2026年7月30日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨