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 本章知识体系总览

下面这张图总结了时间序列基础的核心逻辑,我建议你保存下来,建模时对照着看:

时间序列基础:知识体系 原始时间序列 平稳性检验(ADF检验) 非平稳 → 差分/变换 平稳序列 → ACF/PACF分析 残差 → 白噪声检验 模型定阶(AR/MA/ARMA) 模型拟合与评估 核心流程:原始数据 → 平稳性检验 → ACF/PACF分析 → 模型定阶 → 拟合评估 → 白噪声验证

这张图把整个流程串起来了。你从原始数据出发,先做平稳性检验。如果不平稳,差分或变换;如果平稳,画ACF和PACF图来定阶。模型拟合后,别忘了对残差做白噪声检验——这是检验模型是否“学到位”的关键一步。

好了,时间序列基础就讲到这里。这些概念看着简单,但真正用好需要大量实践。我建议你找一份真实的资金流数据,从头到尾走一遍这个流程,遇到问题再回来翻翻这部分内容。


专注资料整理