3. 时间序列基础:平稳性、ACF与PACF、白噪声检验
做资金流预测,说白了就是跟时间序列打交道。我刚开始接触这个领域时,觉得不就是按时间排个序嘛,有什么难的?结果第一次建模就被数据狠狠教育了一顿——模型预测值飘得离谱,完全没法用。
后来我才明白,时间序列分析有三大基石:平稳性、自相关函数(ACF)和偏自相关函数(PACF),外加一个白噪声检验。今天咱们就把这几个概念彻底讲透。
3.1 平稳性:时间序列的“定海神针”
平稳性是什么?简单说,就是一个时间序列的统计性质不随时间变化。均值恒定、方差恒定、自协方差只与时间间隔有关——这就是弱平稳(也叫宽平稳)。
我个人习惯把平稳性想象成“一个老实人的行为模式”:今天他走路的步速、步幅和明天差不多,不会突然蹦迪或者突然瘫痪。而非平稳序列就像个情绪不稳定的人,均值忽高忽低,方差忽大忽小。
为什么平稳性这么重要?
因为大多数时间序列模型(ARIMA、GARCH等)都假设数据是平稳的。如果数据不平稳,模型会学到虚假的规律——比如把趋势当成周期性,预测自然就崩了。
判断平稳性有两种常用方法:
- 肉眼观察法:画个时序图,看看有没有明显的趋势或季节性波动
- 统计检验法:最常用的是ADF检验(Augmented Dickey-Fuller Test)
嗯,这里要注意:ADF检验的原假设是“序列存在单位根”(即非平稳)。p值小于0.05才能拒绝原假设,认为序列平稳。
# Python代码示例:ADF检验
from statsmodels.tsa.stattools import adfuller
def check_stationarity(series):
result = adfuller(series)
print(f'ADF统计量: {result[0]:.4f}')
print(f'p值: {result[1]:.4f}')
if result[1] < 0.05:
print('✅ 序列平稳')
else:
print('❌ 序列非平稳,需要差分')
我在项目中遇到过最典型的案例:某银行日资金流数据,肉眼看着挺平稳,但ADF检验p值高达0.3。后来发现是数据里藏着一个微弱的趋势——每天资金流入量缓慢增加,被日均波动掩盖了。差分一次后,p值直接降到0.001。
避坑指南:我曾经以为差分次数越多越好,结果把数据差分成白噪声了,模型完全学不到东西。记住:差分是为了消除非平稳性,不是消除所有信息。一般差分1-2次就够了。
3.2 自相关函数(ACF)与偏自相关函数(PACF)
这两个函数是时间序列分析的“X光机”,能帮你看清数据内部的结构。
ACF(自相关函数):衡量当前值与过去某个滞后值之间的相关性。比如ACF(1)就是t时刻与t-1时刻的相关性,ACF(2)是t时刻与t-2时刻的相关性。
PACF(偏自相关函数):剔除中间变量影响后,当前值与过去某个滞后值之间的“净”相关性。比如PACF(2)是剔除了t-1时刻的影响后,t时刻与t-2时刻的相关性。
你想想看,为什么需要PACF?因为ACF会传递效应——如果t与t-1相关,t-1又与t-2相关,那么t与t-2也会表现出相关性,但这其实是间接的。PACF能帮你找到真正的“直接关联”。
# Python代码示例:绘制ACF和PACF
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6))
plot_acf(series, lags=20, ax=ax1)
plot_pacf(series, lags=20, ax=ax2)
plt.show()
我个人的经验是:看ACF和PACF图时,重点关注那些“超出蓝色置信区间”的柱子。蓝色区间代表相关性不显著的范围,柱子超出这个范围,说明该滞后项有统计意义。
ACF/PACF与模型选择的关系:
| ACF特征 | PACF特征 | 建议模型 |
|---|---|---|
| 拖尾(缓慢衰减) | p阶后截尾 | AR(p)模型 |
| q阶后截尾 | 拖尾(缓慢衰减) | MA(q)模型 |
| 拖尾 | 拖尾 | ARMA(p,q)模型 |
什么叫“截尾”?就是某个滞后阶数之后,相关性突然掉到置信区间内,不再显著。什么叫“拖尾”?就是相关性缓慢衰减,像尾巴一样拖得很长。
我记得有一次帮某支付公司分析交易流水,ACF图显示滞后1-3阶显著,之后突然截尾;PACF图则缓慢衰减。这明显是MA(3)的特征。用MA(3)建模后,预测误差直接降低了15%。
注意:实际数据往往没有教科书那么完美。ACF和PACF的“截尾”和“拖尾”是理想情况,真实数据可能模棱两可。这时候我建议用AIC/BIC准则来辅助定阶,别光靠肉眼。
3.3 白噪声检验:你的模型还有救吗?
白噪声,就是纯随机序列——每个时间点的值独立同分布,均值为0,方差恒定。说白了,就是“没有信息可提取”的序列。
为什么白噪声检验重要?因为模型拟合后的残差应该是白噪声。如果残差不是白噪声,说明模型没把信息提取干净,还有改进空间。
常用的白噪声检验方法是Ljung-Box检验:
# Python代码示例:Ljung-Box检验
from statsmodels.stats.diagnostic import acorr_ljungbox
def check_whitenoise(residuals):
result = acorr_ljungbox(residuals, lags=[10], return_df=True)
p_value = result['lb_pvalue'].values[0]
print(f'Ljung-Box p值: {p_value:.4f}')
if p_value > 0.05:
print('✅ 残差为白噪声,模型拟合良好')
else:
print('❌ 残差非白噪声,需要改进模型')
原假设是“残差为白噪声”。p值大于0.05,说明没有足够证据拒绝原假设,模型OK。p值小于0.05,说明残差中还有自相关结构,模型没学好。
我曾经犯过一个低级错误:模型拟合后,残差的Ljung-Box检验p值只有0.01,但我嫌麻烦没管,直接拿去上线了。结果两周后模型开始漂移,预测值越来越偏。后来一查,残差里藏着明显的周周期性——我忘了加入周季节因子。从那以后,白噪声检验成了我模型评估的必选项。
实用建议:Ljung-Box检验的滞后阶数怎么选?我一般取log(n)或者n/4的较小值,其中n是样本量。太小了检测不到长周期相关性,太大了又容易过敏感。
3.4 本章知识体系总览
下面这张图总结了时间序列基础的核心逻辑,我建议你保存下来,建模时对照着看:
这张图把整个流程串起来了。你从原始数据出发,先做平稳性检验。如果不平稳,差分或变换;如果平稳,画ACF和PACF图来定阶。模型拟合后,别忘了对残差做白噪声检验——这是检验模型是否“学到位”的关键一步。
好了,时间序列基础就讲到这里。这些概念看着简单,但真正用好需要大量实践。我建议你找一份真实的资金流数据,从头到尾走一遍这个流程,遇到问题再回来翻翻这部分内容。