跳到正文

结构断点检测

市场会变。关键在于什么时候变。三个检验覆盖 90% 的工作:Chow 检验针对已知断点日期,CUSUM 针对未知断点,Bai-Perron 针对多个断点。

第 3 篇 · 共 12 篇 约 11 分钟

结构断点:模型什么时候失效

用 2010–2014 数据拟合的模型,到 2024 年部署,通常会失败。原因不是 2024 年更难,而是 2014 到 2024 之间数据生成过程变了。2010–2014 的均值不再是正确的均值。2010–2014 的波动率不再是正确的波动率。特征和收益之间的关系也不再是原来的样子。

问题不是结构断点是否发生(它们总会发生),问题是什么时候发生,以及怎么检测。本文介绍三个检测金融时间序列中结构断点的检验。每个适用于不同的场景。

参考主要是计量经济学。经典文献是 Chow(1960)、Brown-Durbin-Evans(CUSUM,1975)和 Bai-Perron(1998、2003)。

(Chow, G. C., “Tests of Equality Between Sets of Coefficients in Two Linear Regressions,” Econometrica, 28(3), 1960, pp. 591–605。)

(Bai, J., & Perron, P., “Computation and Analysis of Multiple Structural Change Models,” Journal of Applied Econometrics, 18(1), 2003, pp. 1–22。)

三个检验

三个检验,复杂度递增:

Chow 检验:检验回归在两个子样本中是否有不同系数,断点日期已知。在你有候选断点日期(例如已知的危机日期),想检验它是否统计显著时使用。

CUSUM 检验:检验回归系数是否随时间稳定,不指定断点日期。在你不知道断点何时发生但想检测它时使用。

Bai-Perron 检验:检验多个结构断点,日期未知。在你怀疑发生过多个断点并想识别它们时使用。

每个检验回答不同的问题。根据先验知识选择。

Chow 检验:已知断点日期

设定:在整个样本 [1,T][1, T] 上的回归 yt=Xtβ+ϵty_t = X_t \beta + \epsilon_t。Chow 检验比较两个限制模型:

  • 限制模型:在 [1,T][1, T] 上的单一回归。
  • 无限制模型:在 [1,Tb][1, T_b] 和 [Tb+1,T][T_b + 1, T] 上分别回归,其中 TbT_b 是候选断点日期。

F 统计量是:

F=(RSSR−RSSUR)/kRSSUR/(T−2k)F = \frac{(RSS_R - RSS_{UR}) / k}{RSS_{UR} / (T - 2k)}

其中 RSSRRSS_R 是限制模型的残差平方和,RSSURRSS_{UR} 是两个无限制模型 RSS 之和,kk 是回归的参数个数,TT 是样本大小。

在无断点原假设下,FF 服从 F(k,T−2k)F(k, T - 2k) 分布。大的 FF 值拒绝原假设:回归系数在两个子样本中不同。

金融应用中:回归通常形如 rt=β0+β1ft+ϵtr_t = \beta_0 + \beta_1 f_t + \epsilon_t,ftf_t 是特征,rtr_t 是收益。Chow 检验问:β1\beta_1 在候选断点日期前后是否不同?

典型应用:检验 2008 年金融危机期间风险-收益关系(夏普比率回归)是否变了。设 TbT_b = 2008 年 9 月。计算 F 统计量。如果显著,关系就变了。

(Chow, 1960。)

Chow 检验的实务

一个干净的实现:

import numpy as np
from scipy.stats import f

def chow_test(y, X, break_point):
    """Test for a structural break at break_point."""
    n, k = X.shape
    
    # Restricted model: single regression
    beta_r = np.linalg.lstsq(X, y, rcond=None)[0]
    rss_r = np.sum((y - X @ beta_r) ** 2)
    
    # Unrestricted model: two separate regressions
    beta_1 = np.linalg.lstsq(X[:break_point], y[:break_point], rcond=None)[0]
    rss_1 = np.sum((y[:break_point] - X[:break_point] @ beta_1) ** 2)
    
    beta_2 = np.linalg.lstsq(X[break_point:], y[break_point:], rcond=None)[0]
    rss_2 = np.sum((y[break_point:] - X[break_point:] @ beta_2) ** 2)
    
    rss_ur = rss_1 + rss_2
    
    # F-statistic
    f_stat = ((rss_r - rss_ur) / k) / (rss_ur / (n - 2 * k))
    p_value = 1 - f.cdf(f_stat, k, n - 2 * k)
    
    return f_stat, p_value

函数返回 F 统计量和 p 值。p 值低于 0.05 表示候选日期存在显著断点。

一个注意点:Chow 检验假设断点日期已知。如果你扫描很多候选日期,挑出 F 统计量最大的那个,得到的 p 值会向下偏(多重检验偏差)。用 Bonferroni 修正调整 p 值,或者用 sup-F 检验(见下)。

Sup-F 检验:未知断点日期

Chow 检验在断点日期未知时的推广:对每个候选断点日期计算 Chow F 统计量,取最大值。

最大 F 统计量的分布不是标准 F 分布。它是 sup-F 分布,计量经济学家已制表。对典型样本量,5% 水平临界值在 8–12 附近(标准 F 临界值在 3–4 附近)。

Sup-F 检验在大多数计量软件包中都有实现(例如 Python 的 statsmodels)。

一个简单实现:

def sup_f_test(y, X, min_frac=0.15):
    """Sup-F test for unknown break date."""
    n = len(y)
    min_obs = int(n * min_frac)
    f_stats = []
    for bp in range(min_obs, n - min_obs):
        f_stat, _ = chow_test(y, X, bp)
        f_stats.append(f_stat)
    return max(f_stats), f_stats.index(max(f_stats)) + min_obs

函数返回最大 F 统计量和产生它的断点日期。Sup-F 分布的临界值已制表;查阅计量经济学参考。

(Andrews, D. W. K., “Tests for Parameter Instability and Structural Change with Unknown Change Point,” Econometrica, 61(4), 1993, pp. 821–856。)

CUSUM 检验:检测不稳定

CUSUM(累积和)检验检测回归系数的渐变。它基于递归残差的累积和。

时点 tt 的递归残差是:在数据 [1,t−1][1, t-1] 上拟合的回归对 XtX_t 给出的预测误差。设 wtw_t 为递归残差。CUSUM 是:

St=∑i=k+1twi/σ^S_t = \sum_{i=k+1}^{t} w_i / \hat{\sigma}

其中 σ^\hat{\sigma} 是残差的标准差。StS_t 随时间变化的图就是 CUSUM 图。

如果回归系数稳定,StS_t 在置信带内(通常是 5% 显著水平下的 ±0.948T−k\pm 0.948 \sqrt{T - k})围绕零波动。如果系数变化,StS_t 会漂出置信带。

断点日期大约是 StS_t 跨过置信带的位置。

(Brown, R. L., Durbin, J., & Evans, J. M., “Techniques for Testing the Constancy of Regression Relationships Over Time,” Journal of the Royal Statistical Society, 37(2), 1975, pp. 149–192。)

CUSUM 实务

一个简单实现:

def cusum_test(y, X, significance=0.05):
    """CUSUM test for parameter instability."""
    n, k = X.shape
    recursive_residuals = []
    
    for t in range(k, n):
        beta = np.linalg.lstsq(X[:t], y[:t], rcond=None)[0]
        resid = y[t] - X[t] @ beta
        recursive_residuals.append(resid)
    
    recursive_residuals = np.array(recursive_residuals)
    sigma = np.std(recursive_residuals)
    cusum = np.cumsum(recursive_residuals) / sigma
    
    # Confidence band
    band = 0.948 * np.sqrt(n - k)
    
    # Detect break (first crossing of the band)
    crossing = np.where(np.abs(cusum) > band)[0]
    break_date = crossing[0] + k if len(crossing) > 0 else None
    
    return cusum, band, break_date

CUSUM 图是有用的诊断工具:目视检查累积和随时间的变化,寻找超出置信带的部分。

典型模式:在正收益状态下 StS_t 上漂,在负收益状态下下漂,在稳定期内保持在带内。StS_t 跨过置信带就信号断点。

Bai-Perron 检验:多个断点

Bai-Perron 检验在未知日期下识别多个结构断点。它是最强的检验,但也最复杂。

算法:

  1. 对每组候选的 mm 个断点日期,计算 m+1m+1 个独立回归的总 RSS。
  2. 用动态规划找到使总 RSS 最小的 mm 个断点日期。
  3. 用序贯 F 检验检验 mm 个断点是否显著优于 m−1m-1 个。

输出是估计的断点日期集合和每个区间对应的回归系数。

实现需要动态规划例程。实际中用 ruptures(Python)或 strucchange(R)这样的包。

(Bai & Perron, 2003。)

何时用哪个检验

场景检验
已知断点日期(例如危机)Chow
未知断点日期,单个断点Sup-F 或 CUSUM
未知断点日期,多个断点Bai-Perron
连续监控稳定性CUSUM
候选日期很多带多重检验修正的 Sup-F

对大多数量化应用,sup-F 检验是起点。它检测单个断点、日期未知。如果怀疑多个断点,用 Bai-Perron。

Chow 检验在你对断点日期有强先验时有用(例如监管变化、已知危机)。Sup-F 和 CUSUM 在探索性分析中有用。

常见陷阱

五种陷阱。

陷阱 1:忽略异方差。

Chow 检验假设方差恒定。金融序列中波动率是时变的。当波动率变化时,检验倾向于检测出断点,即使均值关系是稳定的。用异方差稳健的版本(White 标准误或 HAC 标准误)。

陷阱 2:多重检验偏差。

如果你扫描很多候选断点日期,挑出 F 统计量最大的那个,p 值会向下偏。用 Bonferroni 修正,或者用 sup-F 临界值(考虑了扫描)。

陷阱 3:混淆统计显著性和经济意义。

统计上显著的断点在经济上可能没意义。如果 F 统计量大但系数变化小,断点对交易决策可能不重要。把统计检验和经济直觉结合。

陷阱 4:检测断点太晚。

检验信号断点的时候,市场往往已经走过去了。断点在后视镜里。用 CUSUM 做早期检测(它逐步累积证据)。

陷阱 5:把断点当作永久的。

很多“结构断点”是暂时的。2020 年 3 月的波动率飙升看起来像断点,但其实是暂时状态切换。在长样本上做 Bai-Perron 检验可能检测出很多断点,大部分是暂时的。用稳健的设定(例如 HAC 标准误)避免过拟合。

具体例子

设定:20 年标普 500 日频收益(约 5,000 个观测)。回归:rt=β0+β1VIXt+ϵtr_t = \beta_0 + \beta_1 VIX_t + \epsilon_t,VIXtVIX_t 是 VIX 指数。

Chow 检验在 2008-09-15(雷曼兄弟破产):F 统计量 = 28.4,p 值 < 0.001。高度显著断点。VIX-收益关系在 2008 年大幅变化。

Sup-F 检验(扫描所有日期):最大 F 统计量 = 35.2,在 2008-10-15。结论类似但日期略有不同。

CUSUM 图:StS_t 从 2008 年年中开始稳步漂出置信带,2009 年初回到带内。断点是一个 6 个月的状态切换。

Bai-Perron(测试最多 5 个断点):找出 3 个断点,分别在 2000-03-01(互联网泡沫顶)、2008-09-15(雷曼)和 2020-03-15(COVID 崩盘)。都有经济上可解释的含义。

结论:VIX-收益关系在各个状态间不稳定,主要断点出现在已知危机日期。在全样本上拟合的模型平均了这些状态,在任一状态下的预测都一般。考虑断点的模型(例如状态特定的系数)表现更好。

把结构断点和交易连接起来

三种方法在交易中使用结构断点检验。

用法 1:重估计的触发器。

对策略的 P&L 回归跑 CUSUM 检验。当 CUSUM 跨过置信带时,重估计策略参数。这是一种决定何时重拟合的有纪律方法。

用法 2:状态识别。

用 Bai-Perron 识别历史状态。为每个状态训练独立模型。部署时识别当前状态(用最近的断点日期),应用对应模型。

用法 3:风险管理。

如果在状态切换时策略的因子载荷变化,策略的风险轮廓也变化。早期检测断点能让你提前减少风险。

一个常见模式:连续监控 CUSUM,用较低的阈值(例如 0.5 而不是 0.948)。当阈值被跨过,把仓位规模降低 50%,直到状态稳定。这是一条简单但有效的风险管理规则。

CUSUM 用于在线监控

CUSUM 对在线监控特别有用,因为它能随新数据到来增量更新。

时点 tt 的递归残差只依赖截至 t−1t-1 的数据。新数据到来时,递归残差从现有回归加上新观测算出。CUSUM 通过加上新递归残差(按 σ^\hat{\sigma} 缩放)来更新。

这意味着你可以实时监控参数稳定性,而不需要重拟合回归。CUSUM 随每个新观测更新,跨过阈值就信号状态切换。

实务实现:维护一个滚动回归窗口(例如最近 252 个观测),对每个新观测算递归残差,更新 CUSUM。当 CUSUM 跨过阈值,发送警报。

这比定期跑完整 Bai-Perron 检验更高效,Bai-Perron 复杂度是样本大小的 O(T2)O(T^2) 或 O(T3)O(T^3)。

Quandt 似然比检验

未知断点日期的相关检验是 Quandt 似然比(QLR)检验,也叫 sup-Wald 检验。

算法:

  1. 对每个候选断点日期 TbT_b,计算检验两个子样本系数相等的 Wald 统计量。
  2. 跨所有 TbT_b 取最大 Wald 统计量。
  3. 和 sup-Wald 分布的临界值比较。

QLR 检验和 sup-F 检验类似,但用 Wald 统计量代替 F 统计量。渐近分布相同。

QLR 检验的优势:能应用到非线性模型(例如 GARCH),这些模型里 F 统计量不直接适用。Wald 统计量从对数似然的梯度计算,对任何模型都定义。

实务实现:在每个子样本 [1,Tb][1, T_b] 和 [Tb+1,T][T_b + 1, T] 上拟合模型,计算检验参数相等的 Wald 统计量,取最大。

(Quandt, R. E., “Tests of the Hypothesis That a Linear Regression Obeys Two Different Regimes,” Journal of the American Statistical Association, 55(290), 1960, pp. 324–330。)

Andrews-Plosser 检验

Sup-F 检验的一个改进:Andrews-Plosser 检验用候选断点日期上 F 统计量的加权和,权重强调样本中部的日期。

动机是:sup-F 检验可能功效较低,因为最大 F 统计量被尾部的噪声主导。Andrews-Plosser 检验对所有候选日期取平均,给样本中部(断点检测最可靠的位置)的日期更高权重。

Andrews-Plosser 检验在很多情况下比 sup-F 检验有更高功效,特别是当断点在样本中部附近。实现和 sup-F 类似,但用加权和代替最大。

(Andrews, D. W. K., & Plosser, M. C., “A Monte Carlo Comparison of Tests for Cointegration,” Journal of Econometrics, 65(1), 1994, pp. 113–150。)

三个检验的统计功效

三个检验有不同的统计功效(断点真实存在时检测出来的能力):

检验功效备注
Chow最高必须精确知道断点日期。
Sup-F高单个断点,日期未知。
Bai-Perron高多个断点,日期未知。
CUSUM中检测渐变,对突变的功效较低。

Chow 检验功效最高,因为它能利用已知的断点日期。Sup-F 检验因为扫描很多候选日期(多重检验惩罚)损失一些功效。Bai-Perron 检验因为同样原因损失更多功效。

实际中,对中等样本量(n>200n > 200)和中等断点幅度(系数变化 1+ 个标准误),三个检验都有合理功效。对小样本或小断点,检验可能即使在断点存在时也检测不到。

I 类与 II 类错误的权衡

显著性水平(通常 5%)控制 I 类错误率:没有断点时检测出断点的概率。5% 显著性水平意味着 5% 的时候检验会错误地检测出断点。

更低的显著性水平(例如 1%)减少假阳性,但增加假阴性(II 类错误:漏掉真实断点)。更高的显著性水平(例如 10%)捕获更多真实断点,但产生更多假警报。

对大多数应用,5% 是合理默认。对高风险决策(例如把大量资金投入策略),用 1% 减少假阳性。对探索性分析,用 10% 捕获更多潜在断点。

常见误用:预测未来断点

一个常见误解是:结构断点检验能预测未来断点。不能。它们检测历史数据中的过去断点。预测未来断点需要额外建模(例如状态切换模型、风险率模型)。

有用的说法是:断点检验告诉你,在历史数据上拟合的模型是否还适用。它不告诉你未来会不会发生断点。

要预测未来断点,用显式建模状态变化概率的状态切换模型。断点检验是历史期间的诊断工具,不是预测工具。

(Hamilton, 1990。)

更大的视角

结构断点检测是更广泛学科的一块:随时监控模型有效性。今天拟合的模型是用昨天的数据拟合的。世界在变,模型会失效。问题不是是否要重拟合,而是何时。

三种模型监控方法:

  1. 表现监控:跟踪模型的样本外表现。当表现下降时重拟合。
  2. 参数稳定性监控:用 CUSUM 或 sup-F 检测模型参数何时漂移。漂移时重拟合。
  3. 分布监控:跟踪特征和预测的分布。当分布变化时重拟合(用 KS 检验或 Population Stability Index)。

每种方法都有权衡。表现监控最直接但滞后(你在模型亏钱时才发现它坏了)。参数稳定性监控更快(它能在模型出问题前检测变化)但间接(参数不稳定不总意味着表现下降)。分布监控最快但噪声最大。

一个稳健的监控系统同时使用三种。CUSUM 检验参数是早期检测的核心;表现监控确认参数变化是有经济意义的;分布监控提供早期警告。

(Brown, Durbin, & Evans, 1975;Bai & Perron, 2003。)