6、基差统计特征分析:描述性统计、正态性检验、自相关与偏自相关分析、季节性分解、波动率聚类分析

基差数据,说白了就是现货和期货之间的价差。很多交易员上来就盯着基差的绝对值看,觉得高了就空、低了就多。我见过太多人栽在这上面——基差明明到了历史极值,结果还能再走两个标准差出去。

为什么会这样?因为你不了解它的「脾气」。基差有自己的统计特征,摸透了这些,你才能判断当前这个价差到底是机会还是陷阱。这一章,我把这些年用过的分析工具和方法,一个一个拆给你看。

6.1 描述性统计:先看看基差长什么样

拿到基差数据,我第一件事不是画图,而是算几个关键统计量。这就像医生看病先量体温、测血压一样,快速建立直觉。

统计量 含义 我在项目中的用法
均值 基差的长期中枢 判断当前基差是否偏离「正常位置」
标准差 基差的波动幅度 设定入场阈值,比如±2倍标准差
偏度 分布是否对称 偏度>0说明正基差更极端,做空要小心
峰度 尾部厚度 峰度>3说明极端值频发,止损要收紧
分位数 历史分布位置 我习惯看5%和95%分位,作为预警线

核心经验:别只看均值和标准差。偏度和峰度才是判断「基差会不会突然发疯」的关键。我记得有一次做铜的基差交易,标准差看着不大,但峰度高达8.2,结果连续三天出现极端行情,幸好提前设了硬止损。

import pandas as pd
import numpy as np

# 假设 df 包含基差序列 'basis'
stats = {
    '均值': df['basis'].mean(),
    '标准差': df['basis'].std(),
    '偏度': df['basis'].skew(),
    '峰度': df['basis'].kurtosis(),
    '5%分位': df['basis'].quantile(0.05),
    '95%分位': df['basis'].quantile(0.95)
}
print(pd.Series(stats))

6.2 正态性检验:基差到底是不是正态分布?

很多量化模型假设基差服从正态分布。嗯,这个假设在实盘中经常翻车。我做过统计,大宗商品的基差数据,大约70%都不符合正态分布。

常用的检验方法有三种:

  • Shapiro-Wilk检验:小样本(<5000)时最准,我一般用它做初步判断
  • Jarque-Bera检验:基于偏度和峰度,适合大样本,速度快
  • Q-Q图:可视化判断,点越接近对角线越好

避坑指南:我曾经在橡胶品种上犯过错误——Jarque-Bera检验显示p值0.15,我以为基差是正态的,直接用了2倍标准差做止损。结果连续三次被假突破打脸。后来仔细看Q-Q图才发现,尾部明显偏离对角线。记住:p值只是参考,一定要看图。

from scipy import stats
import matplotlib.pyplot as plt

# Shapiro-Wilk检验
stat, p_value = stats.shapiro(df['basis'].dropna())
print(f'Shapiro p-value: {p_value:.4f}')

# Jarque-Bera检验
jb_stat, jb_p = stats.jarque_bera(df['basis'].dropna())
print(f'Jarque-Bera p-value: {jb_p:.4f}')

# Q-Q图
stats.probplot(df['basis'].dropna(), dist='norm', plot=plt)
plt.title('基差Q-Q图')
plt.show()

6.3 自相关与偏自相关分析:基差有没有记忆?

基差今天涨了,明天会不会接着涨?这就是自相关要回答的问题。我个人习惯用ACF和PACF两个图来判断。

  • ACF(自相关函数):看基差和它过去值之间的相关性。如果拖尾衰减,说明有持续性
  • PACF(偏自相关函数):剔除中间变量的干扰,看「纯」相关性。如果某阶突然截断,说明可以用AR模型

实战技巧:我做豆粕基差时发现,ACF在滞后3阶后仍然显著,说明基差有较强的趋势性。这时候做均值回归策略就要小心——你以为到顶了,结果趋势还能延续好几天。我的做法是:先做差分,把基差变成平稳序列,再分析。

from statsmodels.graphics.tsaplots import plot_acf, plot_pacf

# 画ACF和PACF图
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6))
plot_acf(df['basis'].dropna(), lags=20, ax=ax1)
plot_pacf(df['basis'].dropna(), lags=20, ax=ax2)
plt.show()

6.4 季节性分解:基差也有「春夏秋冬」

农产品、能源品的基差,季节性非常明显。比如大豆,收获季基差通常走弱,因为现货供应充足。你想想看,如果不做季节性分解,你可能会把季节性波动误判成趋势机会。

我常用的分解方法是STL(Seasonal-Trend decomposition using LOESS),它比经典加法分解更稳健,能处理异常值。

from statsmodels.tsa.seasonal import STL

# STL分解,周期设为12(月度数据)
stl = STL(df['basis'], period=12)
result = stl.fit()

# 提取成分
trend = result.trend
seasonal = result.seasonal
residual = result.resid

# 画图
fig = result.plot()
plt.show()

我的经验:分解后,我重点关注残差项。如果残差突然变大,说明有异常事件在驱动基差,这时候要查基本面——是不是港口堵了?是不是交割库出问题了?我记得有一次甲醇基差残差飙升,后来发现是某大型库区检修,现货提货困难。这个信息比任何技术指标都值钱。

6.5 波动率聚类分析:基差的「暴脾气」会传染

波动率聚类,说白了就是「大波动后面跟着大波动,小波动后面跟着小波动」。这在基差交易中特别重要——如果你在低波动期入场,突然遇到高波动期,止损可能瞬间被打穿。

我一般用两种方法:

  • GARCH模型:量化波动率的聚集效应,预测下一期波动率
  • 滚动标准差:简单粗暴,用过去N天的标准差作为当前波动率估计

避坑指南:我曾经在螺纹钢上吃过亏。当时基差波动率很低,我放大了仓位。结果第二天环保限产消息出来,波动率瞬间翻了三倍,账户回撤了5%。后来我学乖了:波动率低的时候,仓位反而要保守,因为你不知道「暴风雨前的宁静」什么时候结束。

from arch import arch_model

# 计算日收益率
df['return'] = df['basis'].pct_change().dropna()

# 拟合GARCH(1,1)模型
model = arch_model(df['return'].dropna() * 100, vol='Garch', p=1, q=1)
result = model.fit(disp='off')

# 预测下一期波动率
forecast = result.forecast(horizon=1)
print(f'预测波动率: {forecast.variance.iloc[-1].values[0]:.4f}')

# 滚动标准差(20天窗口)
df['rolling_std'] = df['basis'].rolling(20).std()

6.6 知识体系总览

这一章的内容比较多,我画了一张图帮你理清思路。你看,整个分析流程是层层递进的:先看描述性统计建立直觉,再检验正态性判断模型适用性,接着用自相关分析找规律,用季节性分解剥离周期,最后用波动率聚类管理风险。

基差统计特征分析流程 基差时间序列 描述性统计:均值、标准差、偏度、峰度 正态性检验 自相关与偏自相关 季节性分解(STL) 波动率聚类(GARCH) 风控决策:阈值设定、仓位管理 残差分析

最后说一句:这一套分析流程,我建议你每周跑一次。不是每天跑——基差的统计特征变化没那么快,但也不能一个月不看。我习惯在周日下午花半小时,把主要品种的基差统计特征过一遍,看看有没有异常变化。这个习惯帮我躲过好几次大坑。


公众号:蓝海资料掘金营,微信deep3321