2. 价差分析:价差的计算、统计特征与平稳性检验
好,咱们进入第二章。价差分析,说白了就是跨期套利的“心脏”。你策略再花哨,如果价差算不对、特征摸不清,那一切都是白搭。我个人习惯把这一章看作是整个系统的“体检科”——先给价差做个全面检查,再决定要不要用它。
2.1 价差的计算:不只是简单的减法
很多人以为价差就是近月合约减远月合约。嗯,理论上没错,但实际项目中坑很多。我记得刚入行时,直接拿收盘价一减就开始跑策略,结果回测曲线漂亮得不行,实盘一跑就亏。为什么?因为忽略了合约的“非同步性”。
价差的核心公式其实很简单:
价差 = 近月合约价格 - 远月合约价格
但这里有个关键点:时间对齐。两个合约的成交时间可能差几毫秒,甚至几秒。如果你用不同时刻的价格去算价差,那算出来的就是“假价差”。
我个人推荐的做法:
- 使用Tick级数据时,取同一时间戳下的最新成交价
- 使用分钟级数据时,取同一分钟内的收盘价或均价
- 如果数据源没有对齐,先做线性插值再计算
来看一段我常用的价差计算代码:
import pandas as pd
import numpy as np
def calculate_spread(near_contract, far_contract, method='close'):
"""
计算价差
:param near_contract: 近月合约价格序列
:param far_contract: 远月合约价格序列
:param method: 'close' 或 'mid'(中间价)
"""
if method == 'close':
spread = near_contract - far_contract
elif method == 'mid':
# 用买卖中间价更稳定
spread = (near_contract['ask'] + near_contract['bid']) / 2 - \
(far_contract['ask'] + far_contract['bid']) / 2
else:
raise ValueError("不支持的method参数")
return spread
# 使用示例
near = pd.Series([3500, 3510, 3520])
far = pd.Series([3480, 3490, 3500])
spread = calculate_spread(near, far)
print(spread)
# 输出: 20, 20, 20
避坑指南:我曾经在股指期货上吃过亏。当时用收盘价算价差,结果发现每天收盘前最后几秒,价差会突然拉大。后来一查,原来是两个合约的收盘集合竞价时间不同。从那以后,我改用最后1分钟的均价来计算,效果好了很多。
2.2 统计特征:摸清价差的“脾气”
价差算出来了,接下来要干嘛?你得了解它的“性格”。是温和还是暴躁?是稳定还是飘忽不定?这就得靠统计特征了。
我一般会看这几个指标:
| 指标 | 含义 | 实战意义 |
|---|---|---|
| 均值 | 价差的平均水平 | 判断当前价差是否偏离正常范围 |
| 标准差 | 价差的波动程度 | 设置开仓阈值的重要依据 |
| 偏度 | 价差分布是否对称 | 正偏态说明价差更容易向上偏离 |
| 峰度 | 价差是否有厚尾 | 峰度高说明极端行情多,要小心 |
| 自相关系数 | 价差前后是否相关 | 判断价差是否有趋势性 |
你想想看,如果价差的标准差是5个点,你设个10个点的开仓阈值,那大概率是等不到的。反过来,如果标准差是20个点,你设2个点的阈值,那基本天天都在开仓,手续费都亏死你。
来看一段计算统计特征的代码:
def spread_statistics(spread):
"""计算价差的统计特征"""
stats = {
'均值': np.mean(spread),
'标准差': np.std(spread),
'偏度': spread.skew(),
'峰度': spread.kurtosis(),
'最大值': np.max(spread),
'最小值': np.min(spread),
'当前值': spread.iloc[-1],
'当前Z-score': (spread.iloc[-1] - np.mean(spread)) / np.std(spread)
}
return stats
# 假设spread是已经计算好的价差序列
stats = spread_statistics(spread)
for key, value in stats.items():
print(f"{key}: {value:.2f}")
注意:统计特征会随着时间变化。我建议每过一段时间就重新计算一次,尤其是在市场结构发生变化时(比如换月、政策调整)。别指望一套参数用一辈子。
2.3 平稳性检验:价差会“回家”吗?
这是整个价差分析里最重要的一步。跨期套利能赚钱,核心假设就是价差会“均值回归”——偏离了迟早会回来。但如果价差不平稳,它可能一去不复返,你的套利就变成了单边投机。
我个人最常用的方法是ADF检验(Augmented Dickey-Fuller Test)。说白了,就是检验价差序列有没有“单位根”。如果有单位根,说明价差不平稳,不适合做套利。
来看代码:
from statsmodels.tsa.stattools import adfuller
def check_stationarity(spread, significance_level=0.05):
"""
ADF检验判断价差是否平稳
:return: (是否平稳, p值, 检验统计量)
"""
result = adfuller(spread, autolag='AIC')
p_value = result[1]
adf_stat = result[0]
is_stationary = p_value < significance_level
print(f"ADF统计量: {adf_stat:.4f}")
print(f"p值: {p_value:.4f}")
print(f"结论: {'平稳' if is_stationary else '不平稳'}")
return is_stationary, p_value, adf_stat
# 使用示例
is_stationary, p_value, adf_stat = check_stationarity(spread)
这里有个坑:ADF检验对数据长度敏感。数据太少,检验结果不可靠;数据太多,又可能包含结构变化。我一般取最近3-6个月的数据,大概500-1000个样本点。
实战经验:我曾经遇到过一个品种,ADF检验显示价差平稳,但实盘就是不回归。后来发现,是因为样本里包含了两次换月,价差被人为拉回了。去掉换月数据后,再检验就不平稳了。所以,一定要剔除换月前后的异常数据。
2.4 知识体系总览
说了这么多,咱们用一张图来总结一下价差分析的核心逻辑:
这张图把整个流程串起来了。从原始数据开始,先算价差,然后兵分两路:一路做统计特征分析,另一路做平稳性检验。两条路最终汇合,为套利策略提供决策依据。
一个小建议:别只看ADF检验的p值。我习惯把统计特征和平稳性检验结合起来看。比如,如果价差均值稳定但标准差突然变大,那可能是市场在变盘,这时候即使ADF显示平稳,也要谨慎开仓。
好了,价差分析这块就讲到这里。记住一句话:算对价差是基础,摸清特征是关键,检验平稳是底线。这三步走扎实了,后面的策略设计才能站得住脚。
公众号:蓝海资料掘金营,微信deep3321