第9章:模型诊断与改进:异方差检验(Breusch-Pagan)、自相关检验(Durbin-Watson)、模型修正
模型建好了,参数也跑出来了。然后呢?
直接拿去交易?别急。我见过太多人,看到R²高就兴奋,结果实盘一跑就崩。为什么?因为模型本身可能有问题——异方差、自相关,这些词听起来学术,但说白了就是你的模型在「说谎」。
这一章,我们就来给模型做个体检。看看它有没有「带病上岗」。
核心逻辑:模型诊断不是为了学术好看,而是为了实盘能打。异方差和自相关会搞乱你的参数估计,让你对基差回归的置信区间产生误判。
9.1 异方差检验:Breusch-Pagan
先说说异方差。什么意思?就是残差的波动不恒定。
你想想看,基差在价格低位时波动小,高位时波动大——这是常态。但OLS回归假设残差方差是常数。如果这个假设不成立,你的标准误就偏了,t统计量也就废了。
Breusch-Pagan检验,就是专门抓这个问题的。
它的逻辑很简单:把残差平方对自变量做辅助回归,看R²够不够大。如果辅助回归显著,说明残差方差和自变量有关——异方差实锤。
我的习惯:每次跑完基差回归,第一件事就是做BP检验。p值小于0.05,我就知道参数估计的置信区间可能不靠谱了。
import statsmodels.api as sm
from statsmodels.stats.diagnostic import het_breuschpagan
# 假设你已经跑好了模型
model = sm.OLS(y, X).fit()
residuals = model.resid
# BP检验
bp_test = het_breuschpagan(residuals, X)
bp_stat, bp_pval, bp_fstat, bp_fpval = bp_test
print(f'BP统计量: {bp_stat:.4f}')
print(f'BP p值: {bp_pval:.4f}')
if bp_pval < 0.05:
print('⚠️ 存在异方差,需要修正')
else:
print('✅ 无异方差问题')
输出示例:
| 统计量 | 值 | p值 | 结论 |
|---|---|---|---|
| LM统计量 | 12.847 | 0.002 | 存在异方差 |
| F统计量 | 6.521 | 0.003 | 存在异方差 |
注意:BP检验对正态性假设敏感。如果残差非正态,可以考虑用White检验替代。我一般两个都跑,互相印证。
9.2 自相关检验:Durbin-Watson
自相关,说白了就是残差之间有「记忆」。
今天的残差和昨天的残差有关系。这在时间序列数据里太常见了——基差走势往往有持续性,今天偏离均值,明天可能继续偏离。
Durbin-Watson检验,就是看残差的一阶自相关。
DW统计量的取值范围是0到4。2附近表示无自相关,接近0是正自相关,接近4是负自相关。
from statsmodels.stats.stattools import durbin_watson
dw_stat = durbin_watson(residuals)
print(f'DW统计量: {dw_stat:.4f}')
if dw_stat < 1.5:
print('⚠️ 正自相关显著')
elif dw_stat > 2.5:
print('⚠️ 负自相关显著')
else:
print('✅ 无显著自相关')
输出示例:
| DW统计量 | 判断区间 | 结论 |
|---|---|---|
| 0.89 | 0 - 1.5 | 正自相关 |
| 2.03 | 1.5 - 2.5 | 无自相关 |
| 3.12 | 2.5 - 4 | 负自相关 |
避坑指南:DW检验只检测一阶自相关。如果你怀疑高阶自相关(比如周度数据有月度效应),可以用Ljung-Box Q检验。我曾经在螺纹钢基差模型里只看了DW,结果漏掉了周度周期效应,后来补了Q检验才发现问题。
9.3 模型修正方案
发现问题了,怎么修?
别慌。修正不是推翻重来,而是对症下药。
9.3.1 异方差的修正
方案一:稳健标准误(Huber-White)
这是最省事的办法。不改模型,只改标准误的计算方式。说白了就是告诉模型:「我知道你有异方差,我算标准误的时候自己小心点。」
# 使用稳健标准误
model_robust = sm.OLS(y, X).fit(cov_type='HC3')
print(model_robust.summary())
方案二:加权最小二乘法(WLS)
如果异方差的结构比较清晰,比如你知道残差方差和某个变量成正比,可以用WLS。给波动大的观测值更小的权重。
# 假设权重与X的某个变量成反比
weights = 1 / X[:, 1]**2 # 示例:用第二个自变量构造权重
model_wls = sm.WLS(y, X, weights=weights).fit()
print(model_wls.summary())
我的经验:在基差交易中,我倾向于先用稳健标准误。因为异方差的结构往往不明确,强行假设权重可能引入新偏差。稳健标准误虽然保守,但至少不会错。
9.3.2 自相关的修正
方案一:Newey-West标准误
和稳健标准误类似,但专门处理自相关和异方差的组合问题。这是时间序列回归的标配。
# Newey-West标准误
model_nw = sm.OLS(y, X).fit(cov_type='HAC', cov_kwds={'maxlags': 5})
print(model_nw.summary())
方案二:差分或季节调整
如果自相关很强,说明模型可能漏掉了时间趋势或周期。试试一阶差分,或者加入滞后项。
# 一阶差分处理
y_diff = y.diff().dropna()
X_diff = X.diff().dropna()
model_diff = sm.OLS(y_diff, X_diff).fit()
方案三:ARIMA误差修正
如果自相关结构复杂,可以考虑用ARIMA模型来拟合残差。这在基差回归中比较高级,但效果往往不错。
from statsmodels.tsa.arima.model import ARIMA
# 先跑OLS,再对残差建ARIMA
model_ols = sm.OLS(y, X).fit()
resid_arima = ARIMA(model_ols.resid, order=(1,0,1)).fit()
print(resid_arima.summary())
9.4 综合诊断流程
说了这么多,实际操作中怎么走?我总结了一个流程:
- 跑OLS模型,拿到残差
- 做BP检验,看异方差
- 做DW检验,看自相关
- 做JB检验,看正态性(辅助参考)
- 根据结果选择修正方案:
- 只有异方差 → 稳健标准误(HC3)
- 只有自相关 → Newey-West标准误
- 两者都有 → Newey-West标准误 + 考虑差分
- 问题严重 → 换模型(WLS或ARIMA)
核心原则:修正的目的是让参数估计更可靠,而不是让模型更复杂。能用标准误解决的,就别动模型结构。我曾经见过有人为了修正一个轻微的自相关,硬上了ARIMA(3,1,3),结果过拟合得一塌糊涂。
9.5 实战案例:螺纹钢基差模型诊断
拿螺纹钢基差数据举个例子。我跑了一个简单的回归:基差 ~ 库存 + 开工率 + 螺纹指数。
import pandas as pd
import statsmodels.api as sm
# 加载数据(示例)
data = pd.read_csv('rebar_basis.csv')
y = data['basis']
X = data[['inventory', 'capacity_util', 'rebar_index']]
X = sm.add_constant(X)
# 1. 跑OLS
model = sm.OLS(y, X).fit()
print(model.summary())
# 2. 诊断
resid = model.resid
bp_stat, bp_pval, _, _ = het_breuschpagan(resid, X)
dw_stat = durbin_watson(resid)
print(f'BP p值: {bp_pval:.4f}')
print(f'DW统计量: {dw_stat:.4f}')
# 3. 修正
if bp_pval < 0.05 or dw_stat < 1.5 or dw_stat > 2.5:
model_final = sm.OLS(y, X).fit(cov_type='HAC', cov_kwds={'maxlags': 5})
print('使用Newey-West标准误修正')
else:
model_final = model
print('模型无需修正')
输出结果:
| 检验项 | 统计量 | p值/判断 | 结论 |
|---|---|---|---|
| Breusch-Pagan | 8.234 | 0.041 | 存在异方差 |
| Durbin-Watson | 1.21 | 正自相关 | 存在自相关 |
| 修正后 | Newey-West | lags=5 | 标准误修正完成 |
重要提醒:修正后的标准误通常比OLS标准误大。这意味着你的置信区间变宽了,t统计量变小了。别慌,这是诚实的表现。宁可置信区间宽一点,也别用虚假的显著性去交易。
嗯,模型诊断这块就讲到这里。说白了,就是给模型做个全面体检。发现问题不可怕,可怕的是带着问题去实盘。修正方案选对了,你的基差回归模型才能真正经得起市场考验。