3. 金融时间序列基础
在均值回归策略里,我们真正建模的对象几乎从来不是“价格”本身,而是价格衍生出的收益率或价差序列。理解价格与收益率的区别、平稳性的含义、自相关结构以及白噪声与随机走的性质,是后续多模型组合与风险控制的共同地基。本节把这四个概念串成一条可操作的认知链。
一、核心原理:价格、收益率与平稳性
价格序列通常是非平稳的:它带有趋势、量纲随标的而变,且方差随时间漂移。直接对价格做回归,容易得到“伪回归”——两个独立上涨的序列也能算出很高的 R²。收益率则不同,它近似无量纲、可加、统计性质更稳定,因此是建模的首选输入。
常用收益率有两种:
- 简单收益率:r_t = P_t / P_{t-1} - 1,直观、可解释为实际盈亏比例,但多期不可直接相加。
- 对数收益率:r_t = ln(P_t / P_{t-1}),多期可加,且与连续复利一致,是时间序列建模的主流形式。
平稳性(stationarity)是时间序列分析的入场券。弱平稳要求:均值恒定、方差恒定、自协方差只依赖时间间隔 τ 而与绝对时间 t 无关。只有平稳序列,其历史统计规律才可能外推到未来。均值回归策略本质上是在交易“平稳的价差或收益率”,若序列非平稳,回归信号会持续失效。
二、方法流程:检验与识别
平稳性检验常用 ADF(Augmented Dickey-Fuller)与 KPSS。两者原假设相反,配合使用更稳健:ADF 拒绝原假设说明“无单位根”,KPSS 不拒绝原假设说明“可视为平稳”。
from statsmodels.tsa.stattools import adfuller, kpss
import numpy as np
# 假设 price 为价格序列,ret 为对数收益率
adf_p = adfuller(price, autolag="AIC")
adf_r = adfuller(ret, autolag="AIC")
kpss_r = kpss(ret, regression="c", nlags="auto")
print("价格 ADF p值:", adf_p[1]) # 通常 > 0.05,非平稳
print("收益率 ADF p值:", adf_r[1]) # 通常 < 0.05,平稳
print("收益率 KPSS p值:", kpss_r[1]) # 通常 > 0.05,支持平稳
自相关(ACF)与偏自相关(PACF)用于识别序列的线性依赖结构。ACF 衡量 r_t 与 r_{t-τ} 的相关性,包含中间滞后传导;PACF 剔除中间项影响,只保留 r_t 与 r_{t-τ} 的直接关系。二者配合可初步判断 AR、MA 或 ARMA 的阶数。
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
import matplotlib.pyplot as plt
fig, ax = plt.subplots(2, 1, figsize=(8, 6))
plot_acf(ret, lags=40, ax=ax[0])
plot_pacf(ret, lags=40, ax=ax[1])
plt.tight_layout()
白噪声是“无信息”的基准:均值恒定、方差恒定、各滞后自相关为零。若收益率序列接近白噪声,说明线性可预测性极弱,均值回归信号需要从价差、波动率或其他维度寻找。随机走则是价格层面的典型非平稳过程,其增量近似白噪声,价格本身无固定均值,因此对随机走做“抄底摸顶”式均值回归风险极高。
| 概念 | 关键特征 | 对均值回归的含义 |
|---|---|---|
| 价格 | 常非平稳,含趋势与量纲 | 不宜直接建模,需转换 |
| 对数收益率 | 近似平稳、可加 | 建模首选输入 |
| 白噪声 | 无自相关、无信息 | 线性信号弱,需换维度 |
| 随机走 | 增量白噪声、价格非平稳 | 均值回归易失效,需严格风控 |
| 平稳价差 | 均值回复、方差稳定 | 均值回归的核心交易对象 |
三、案例/场景:从价格到可交易信号
假设我们观察某配对价差序列 spread_t = P_A - β·P_B。若直接对 spread 做回归而不检验平稳性,可能得到虚假的高拟合。正确流程是:先对 spread 做 ADF 检验,若 p 值小于 0.05,说明价差平稳,具备均值回归基础;再计算其 ACF/PACF,若 ACF 快速衰减而 PACF 在低阶截尾,可尝试 AR(1) 或 AR(2) 建模,估计回复速度与半衰期。
# 半衰期估计:AR(1) 模型 spread_t = a + b * spread_{t-1} + e
import statsmodels.api as sm
lag = spread.shift(1).dropna()
y = spread.loc[lag.index]
X = sm.add_constant(lag)
model = sm.OLS(y, X).fit()
b = model.params.iloc[1]
half_life = -np.log(2) / np.log(b)
print("回复系数 b:", b, "半衰期(期):", half_life)
若半衰期过长(例如超过 60 个交易日),即使统计上平稳,交易成本与资金占用也会吞噬收益;若半衰期过短,则可能被噪声主导。这一判断直接决定后续多模型组合中该信号的权重与风控阈值。
四、误区与复盘
- 误区一:把价格当平稳序列建模。 价格非平稳会导致伪回归,R² 虚高但无交易价值。复盘时应强制先做单位根检验。
- 误区二:只看 ADF 不看 KPSS。 两者结论冲突时,往往说明序列接近单位根边界,需谨慎降杠杆或延长观察窗口。
- 误区三:把白噪声误认为“没有机会”。 白噪声只说明线性自相关弱,波动率聚集、非线性结构仍可能存在,需换模型维度。
- 误区四:对随机走做均值回归。 随机走没有固定均值,回归信号会持续被趋势碾压,必须设置硬止损与仓位上限。
把本节四个概念连起来看:价格是非平稳的原始素材,收益率与平稳价差是可建模对象,ACF/PACF 描述其依赖结构,白噪声与随机走则划定了“可预测”与“不可预测”的边界。后续的多模型组合,本质上是在这些边界内寻找稳定、可风控的均值回归机会。