3、经典统计模型:ARIMA模型原理与实战、SARIMA季节性模型、模型诊断与残差分析

说到时间序列预测,很多人一上来就上深度学习。但我个人习惯,先拿经典统计模型试试水。为什么?因为ARIMA这类模型,说白了就是帮你把「时间」这个维度拆解得明明白白。你想想看,如果连数据里的趋势和周期都看不清楚,直接上黑盒模型,很容易翻车。

我在项目中遇到过好几次,用LSTM跑出来的结果,还不如一个调参调好的ARIMA。嗯,这里要注意,不是说深度学习不好,而是经典模型更「透明」——你能看到每一步在做什么。

3.1 ARIMA模型:从直觉到公式

ARIMA的全称是自回归积分滑动平均模型。名字挺长,但拆开看就三部分:

  • AR(自回归):用过去的值预测现在的值。比如今天的气温,跟昨天、前天有关。
  • I(差分):让非平稳数据变平稳。说白了就是「减一减」,把趋势去掉。
  • MA(滑动平均):用过去的预测误差来修正当前的预测。

ARIMA模型有三个关键参数:pdq

参数 含义 怎么定
p 自回归阶数 看PACF图,截尾处
d 差分阶数 做单位根检验,直到平稳
q 滑动平均阶数 看ACF图,截尾处

数学表达式长这样:

ARIMA(p,d,q):
(1 - φ₁B - ... - φₚBᵖ)(1-B)ᵈ yₜ = (1 + θ₁B + ... + θₙBᵠ) εₜ

别被公式吓到。你只要记住:B是滞后算子,φ是AR系数,θ是MA系数。剩下的交给代码。

我的小技巧: 刚开始做ARIMA时,别纠结p和q的精确值。先用AIC/BIC准则自动搜索,再手动微调。我曾经花了一整天手动调参,后来发现auto_arima一步到位。

3.2 实战:用Python实现ARIMA

我们拿股票日收益率数据来演示。注意,收益率序列通常已经接近平稳,省去了很多麻烦。

import pandas as pd
import numpy as np
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
import matplotlib.pyplot as plt

# 加载数据
df = pd.read_csv('stock_returns.csv', index_col='date', parse_dates=True)
y = df['return'].dropna()

# 画ACF和PACF图
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6))
plot_acf(y, lags=30, ax=ax1)
plot_pacf(y, lags=30, ax=ax2)
plt.show()

# 拟合ARIMA(2,0,2)模型
model = ARIMA(y, order=(2, 0, 2))
result = model.fit()
print(result.summary())

输出结果里,重点关注两件事:

  • 系数是否显著(看P值,小于0.05就算显著)
  • AIC和BIC值(越小越好,用于模型对比)
避坑指南: 我曾经犯过一个低级错误——直接用原始股价做ARIMA。结果模型预测出来一条直线,完全没意义。记住,ARIMA要求数据平稳。股价不平稳,收益率才平稳。

3.3 SARIMA:给模型加上「日历」

ARIMA处理不了周期性。比如电商销量,每周五都会冲高。这时候就需要SARIMA——在ARIMA基础上加了季节性成分。

SARIMA的参数变成7个:(p,d,q)×(P,D,Q,s)。其中s是周期长度,比如周数据s=7,月数据s=12。

举个例子,如果你做的是日频数据,发现每周都有规律:

from statsmodels.tsa.statespace.sarimax import SARIMAX

# SARIMA(1,1,1)×(1,1,1,7)
model = SARIMAX(y, order=(1,1,1), seasonal_order=(1,1,1,7))
result = model.fit()
print(result.summary())

为什么是(1,1,1,7)?

  • 季节性AR阶数P=1:用上周同一天的值
  • 季节性差分D=1:去掉周级别的趋势
  • 季节性MA阶数Q=1:用上周的预测误差
  • 周期s=7:一周7天

我在做电商销量预测时,发现SARIMA的效果比纯ARIMA提升了30%以上。尤其是节假日效应,SARIMA能自动捕捉到「去年双11前后销量暴涨」这种模式。

3.4 模型诊断:别急着用,先看看残差

模型拟合完了,别急着预测。先做诊断——说白了就是检查残差(真实值-预测值)是不是「白噪声」。

好的残差应该满足三个条件:

  1. 均值为0:没有系统性偏差
  2. 无自相关:残差之间不相关
  3. 正态分布:方便做置信区间

诊断代码:

# 残差分析
residuals = result.resid

# 1. 画残差图
plt.figure(figsize=(10, 4))
plt.plot(residuals)
plt.title('残差序列')
plt.show()

# 2. 画残差ACF图
plot_acf(residuals, lags=30)
plt.title('残差自相关检验')
plt.show()

# 3. Ljung-Box检验
from statsmodels.stats.diagnostic import acorr_ljungbox
lb_test = acorr_ljungbox(residuals, lags=[10, 20, 30], return_df=True)
print(lb_test)

Ljung-Box检验的p值如果大于0.05,说明残差没有显著自相关,模型OK。如果p值小于0.05,说明残差里还有信息没被提取,需要重新调整参数。

核心要点: 残差分析不是走过场。我见过太多人直接跳过这步,结果模型在回测里表现很好,实盘却一塌糊涂。残差里有模式,说明模型没学全。

3.5 知识体系总览

下面这张图,把ARIMA和SARIMA的核心逻辑串起来了。建议你保存下来,调参时对照着看。

ARIMA/SARIMA 模型知识体系 时间序列数据 平稳性检验 + 差分处理 模型选择 ARIMA(p,d,q) SARIMA(p,d,q)(P,D,Q,s) 自动搜索(AIC/BIC) 模型诊断:残差分析 预测结果 步骤1 步骤2 步骤3 步骤4 步骤5

这张图展示了从原始数据到最终预测的完整流程。每一步都有对应的统计检验和可视化工具。我个人建议,新手先按这个流程走一遍,再考虑优化。

实战建议: 如果你用的是高频数据(比如分钟级),ARIMA可能不太够用。但如果是日频或更低频,ARIMA和SARIMA依然是性价比最高的选择。我在做因子收益率预测时,ARIMA经常作为基准模型,用来对比更复杂的模型是否真的有提升。

好了,这一章的内容就到这里。ARIMA和SARIMA虽然经典,但用好了威力不小。下一章我们会聊更进阶的模型——但在此之前,建议你把今天的内容动手跑一遍。代码我都贴出来了,复制到Jupyter里就能用。

专注资料整理