第四章 时间序列分析基础(下):ARIMA模型建模全流程
好,咱们接着聊。上一章我们把时间序列的平稳性、白噪声这些基础概念捋了一遍。这一章,我带你走一遍ARIMA模型的完整建模流程。说白了,就是给你一套标准动作,照着做,基本不会跑偏。
核心逻辑:ARIMA建模不是玄学,是一套可复现的工程流程。我个人的习惯是:先看数据长什么样,再决定用什么模型,最后反复验证模型靠不靠谱。
4.1 数据预处理——别让脏数据毁了你的模型
拿到股票价格序列,第一件事不是跑模型,而是先看看数据干不干净。我在做统计套利策略时,遇到过好几次因为数据没处理好,导致回测结果漂亮得离谱,实盘却一塌糊涂的惨案。
具体来说,你需要检查这几项:
- 缺失值处理:停牌日、节假日会导致数据缺失。我一般用前向填充(ffill),或者直接删除。千万别用均值填充,那会引入未来信息。
- 异常值识别:比如某天价格突然跳空,可能是数据错误。用3倍标准差法或者IQR法都能筛出来。
- 对数变换:价格序列通常有异方差性——价格越高,波动越大。取对数能稳定方差,这是标准做法。
我的经验:对数收益率比原始价格更适合建模。原因很简单——对数收益率近似正态分布,而且具有可加性。我几乎从不对原始价格直接跑ARIMA,除非是平稳的价差序列。
4.2 平稳性检验——不平稳就别往下走了
ARIMA模型要求数据平稳。什么叫平稳?均值、方差、自协方差都不随时间变化。说白了,就是数据没有明显的趋势和季节性。
检验方法主要有两种:
| 检验方法 | 原假设 | 什么时候用 |
|---|---|---|
| ADF检验 | 序列存在单位根(不平稳) | 最常用,p值小于0.05则拒绝原假设 |
| KPSS检验 | 序列平稳 | 与ADF互补,两者结合判断更可靠 |
我个人习惯两个检验都做。如果ADF说平稳,KPSS也说平稳,那基本稳了。如果结果矛盾,我会更相信ADF的结果——它在实践中表现更稳定。
4.3 差分处理——让非平稳变平稳
如果数据不平稳,怎么办?差分。一阶差分就是今天的值减去昨天的值。对于股票价格,一阶差分通常就能得到平稳序列——也就是收益率序列。
怎么确定差分阶数d?
- 画图看:差分后的序列是否围绕0均值波动
- ADF检验:差分后p值小于0.05
- 经验法则:金融数据d最多取1或2,取多了会丢失信息
注意:过度差分是个坑。我曾经为了追求完美平稳性,对某只股票做了三阶差分,结果模型预测出来的全是噪声。记住,差分是为了消除趋势,不是为了消灭所有波动。
4.4 模型定阶——AIC/BIC准则帮你做选择
定阶就是确定p(自回归阶数)和q(移动平均阶数)。有两种方法:
方法一:看图法
- ACF图(自相关函数):如果拖尾,考虑AR模型;如果截尾,考虑MA模型
- PACF图(偏自相关函数):如果截尾,考虑AR模型;如果拖尾,考虑MA模型
方法二:信息准则法
AIC(赤池信息准则)和BIC(贝叶斯信息准则)是更客观的方法。公式我就不写了,你只需要知道:
- AIC:倾向于选择更复杂的模型(参数更多)
- BIC:对复杂模型惩罚更重,倾向于选择更简洁的模型
- 两者都是越小越好
实际中怎么做?我通常用网格搜索,遍历p和q从0到5的所有组合,选AIC或BIC最小的那个。Python的pmdarima库有auto_arima函数,一键搞定。
# 自动定阶示例
from pmdarima import auto_arima
model = auto_arima(price_log_diff,
start_p=0, max_p=5,
start_q=0, max_q=5,
seasonal=False,
trace=True,
error_action='ignore',
suppress_warnings=True,
stepwise=True)
print(model.summary())
4.5 模型诊断——残差必须是白噪声
模型建好了,别急着用。先做诊断。诊断的核心就一句话:残差必须是白噪声。
什么意思?残差里不能有任何可预测的模式。如果残差还有自相关性,说明模型没把信息提取干净,需要重新定阶。
诊断工具:
- 残差图:看是否围绕0随机波动,有没有明显的模式
- Q-Q图:检查残差是否正态分布(虽然不是必须的,但正态性有助于区间估计)
- Ljung-Box检验:统计检验残差的自相关性。p值大于0.05,说明残差是白噪声
避坑指南:我曾经在诊断阶段偷懒,看到残差图还行就直接用了。结果实盘时模型频繁失效。后来仔细一查,残差在特定时间段(比如财报发布前后)有明显的自相关性。所以,Ljung-Box检验一定要做,而且要分时段做。
4.6 实战:用Python对股票价格序列建模
好了,理论说完了,咱们动手。下面是一个完整的建模流程,我用的是某只股票的日收盘价。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.stattools import adfuller
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.stats.diagnostic import acorr_ljungbox
# 1. 加载数据
df = pd.read_csv('stock_price.csv', index_col='date', parse_dates=True)
price = df['close']
# 2. 对数变换 + 一阶差分
log_price = np.log(price)
log_return = log_price.diff().dropna()
# 3. 平稳性检验
adf_result = adfuller(log_return)
print(f'ADF p-value: {adf_result[1]:.4f}') # 应该小于0.05
# 4. 画ACF和PACF图
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6))
plot_acf(log_return, lags=20, ax=ax1)
plot_pacf(log_return, lags=20, ax=ax2)
plt.show()
# 5. 拟合ARIMA模型(假设看图定阶为p=2, d=1, q=2)
model = ARIMA(log_price, order=(2, 1, 2))
result = model.fit()
print(result.summary())
# 6. 模型诊断
residuals = result.resid
lb_test = acorr_ljungbox(residuals, lags=[10, 20, 30], return_df=True)
print(lb_test) # p值应大于0.05
# 7. 预测
forecast = result.forecast(steps=5)
print(forecast)
这段代码基本覆盖了从数据预处理到预测的全流程。你跑一遍,看看结果。如果Ljung-Box检验的p值小于0.05,说明模型没通过诊断,回去重新定阶。
一个小技巧:如果你发现模型总是通不过诊断,试试把p和q的范围扩大。有时候金融数据的记忆性比我们想象的要长。我遇到过需要p=7才能把残差中的自相关性消除干净的案例。
4.7 模型应用:从预测到交易信号
模型建好了,怎么用?在统计套利中,ARIMA模型通常用来预测价差的短期走势。比如:
- 预测下一期的价差
- 如果预测值偏离当前值超过某个阈值,生成交易信号
- 结合协整关系,做配对交易
但记住一点:ARIMA模型擅长短期预测,别指望它能预测一个月后的价格。我一般只用它预测未来1-3个交易日。
好了,这一章的内容就到这儿。ARIMA建模的流程你记住了吗?预处理→平稳性检验→差分→定阶→拟合→诊断→应用。每一步都有坑,但每一步也都有解法。多练几次,你就能找到感觉。
最后说一句:模型诊断这一步,千万别跳过。我见过太多人建完模型就直接拿去交易,结果亏得一塌糊涂。记住,残差必须是白噪声——这是底线。
公众号:蓝海资料掘金营,微信deep3321