2. 单变量时序分析基础:时间序列分解、平稳性检验、ACF/PACF
各位同学,欢迎来到多因子时序预测实战训练营的第二讲。
今天咱们聊点基础但极其重要的东西——单变量时序分析。你可能会问:“老师,我们不是要做多因子模型吗?为什么还要花一整章讲单变量?”
嗯,这个问题问得好。我个人的经验是:多因子模型的地基,就是单变量分析。如果你连一个时间序列的“脾气”都摸不透,堆再多因子也是白搭。我在做CTA策略的时候,就吃过这个亏——上来就搞复杂模型,结果回测漂亮,实盘一塌糊涂。后来老老实实回去做单变量诊断,才发现问题出在数据本身。
好,咱们正式开始。
2.1 时间序列分解:把数据拆开看
一个时间序列,说白了就是三个成分的叠加:趋势(Trend)、季节性(Seasonal)、残差(Residual)。用数学公式表达就是:
Y(t) = T(t) + S(t) + R(t) (加法模型)
Y(t) = T(t) * S(t) * R(t) (乘法模型)
加法模型适用于季节性波动幅度不随时间变化的情况。乘法模型则适用于波动幅度随趋势增长而放大的情况——比如股票价格,牛市里波动大,熊市里波动小,这就是乘法模型的典型特征。
我个人习惯先用加法模型试试,如果残差有明显的异方差性,再换乘法模型。
2.1.1 如何分解?
Python里最常用的工具是 statsmodels.tsa.seasonal_decompose。来看一段代码:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.seasonal import seasonal_decompose
# 生成模拟数据:趋势 + 季节 + 噪声
np.random.seed(42)
t = np.arange(0, 365)
trend = 0.05 * t
seasonal = 10 * np.sin(2 * np.pi * t / 30)
noise = np.random.normal(0, 2, 365)
data = trend + seasonal + noise
# 分解
result = seasonal_decompose(data, model='additive', period=30)
result.plot()
plt.show()
这段代码会输出四张图:原始序列、趋势成分、季节成分、残差成分。你一眼就能看出数据里有没有明显的趋势和周期。
2.2 平稳性检验:数据“稳”了才能建模
平稳性,是时间序列建模的第一道门槛。什么叫平稳?简单说就是:统计性质不随时间变化。具体来说,均值、方差、自协方差都是常数。
为什么这么重要?因为大多数模型(ARIMA、GARCH等)都假设数据是平稳的。如果数据不平稳,模型会学到虚假的规律——比如把趋势当成预测信号,结果一预测就崩。
我见过最惨的案例:有人用非平稳的股价直接跑LSTM,训练集上拟合得完美,测试集上直接飞了。原因就是模型学到了趋势,但趋势的方向变了。
2.2.1 ADF检验(单位根检验)
ADF检验的原假设是:序列存在单位根(非平稳)。如果p值小于0.05,拒绝原假设,认为序列平稳。
from statsmodels.tsa.stattools import adfuller
result = adfuller(data)
print(f'ADF Statistic: {result[0]}')
print(f'p-value: {result[1]}')
print(f'Critical Values: {result[4]}')
# 输出示例:
# ADF Statistic: -3.45
# p-value: 0.009
# Critical Values: {'1%': -3.45, '5%': -2.87, '10%': -2.57}
p值0.009 < 0.05,说明序列平稳。但注意:ADF检验对滞后阶数敏感。我建议用AIC自动选择滞后阶数,而不是随便设一个固定值。
2.2.2 KPSS检验(互补检验)
KPSS检验的原假设正好相反:序列是平稳的。如果p值小于0.05,拒绝原假设,认为序列非平稳。
from statsmodels.tsa.stattools import kpss
result = kpss(data, regression='c')
print(f'KPSS Statistic: {result[0]}')
print(f'p-value: {result[1]}')
四种可能的结果:
| ADF结果 | KPSS结果 | 结论 |
|---|---|---|
| 平稳 | 平稳 | 序列平稳 |
| 不平稳 | 不平稳 | 序列非平稳(差分处理) |
| 平稳 | 不平稳 | 可能存在趋势(去趋势处理) |
| 不平稳 | 平稳 | 可能存在结构突变 |
2.3 自相关与偏自相关图:找“记忆”的长度
ACF(自相关函数)和PACF(偏自相关函数)是判断ARIMA模型阶数的核心工具。说白了,它们告诉你:过去的数据对现在有多大影响?影响能持续多久?
2.3.1 ACF图
ACF衡量的是 Y(t) 和 Y(t-k) 之间的相关性,不考虑中间变量的影响。如果ACF在滞后k处显著不为0,说明k期前的数据对当前有直接影响。
from statsmodels.graphics.tsaplots import plot_acf
import matplotlib.pyplot as plt
plot_acf(data, lags=40)
plt.show()
2.3.2 PACF图
PACF则是在剔除了中间滞后项的影响后,计算 Y(t) 和 Y(t-k) 的偏相关。它更“干净”,能直接告诉你AR模型的阶数。
from statsmodels.graphics.tsaplots import plot_pacf
plot_pacf(data, lags=40)
plt.show()
2.3.3 如何用ACF/PACF定阶?
这是经典套路:
- AR(p)模型:PACF在p阶后截尾(突然降到0),ACF拖尾(缓慢衰减)
- MA(q)模型:ACF在q阶后截尾,PACF拖尾
- ARMA(p,q)模型:两者都拖尾
举个例子:如果PACF在滞后2之后突然掉到置信区间内,而ACF缓慢衰减,那大概率是AR(2)模型。
但说实话,实际数据很少这么完美。我的做法是:先用ACF/PACF初步判断,然后用AIC/BIC在候选阶数里选最优。别死磕“截尾”这个标准,数据不会那么听话。
2.4 本章知识体系总览
下面这张图,是我自己总结的单变量时序分析流程。每次拿到新数据,我都会走一遍这个流程:
这张图的核心逻辑是:先分解看结构,再检验看平稳性,最后用ACF/PACF定阶。每一步都有明确的输出,每一步都在为下一步做准备。
2.5 本章小结
好,咱们来捋一捋今天的内容:
- 时间序列分解:把数据拆成趋势、季节、残差,看清数据的底层结构
- 平稳性检验:ADF和KPSS双剑合璧,判断数据是否“稳”得住
- ACF/PACF:找数据的“记忆长度”,为ARIMA定阶做准备
这些工具,说白了就是帮你读懂数据。我做了这么多年量化,最大的体会就是:模型再复杂,也救不了对数据的一无所知。每次拿到新数据,我都会老老实实走一遍这个流程——哪怕只是看一眼ACF图,心里也有个底。
下一章,咱们会把这些工具串起来,正式进入ARIMA模型的实战。到时候你会发现,今天打下的基础,全都能用上。
公众号:蓝海资料掘金营,微信deep3321