第四章:时间序列模型:ARIMA、GARCH、Prophet模型的原理与实战
时间序列分析,说白了就是跟历史数据对话。我做了这么多年量化,发现很多新手一上来就堆特征、上深度学习,结果过拟合得一塌糊涂。其实,很多金融数据本身就带着强烈的时间结构——趋势、季节、波动聚集。把这些结构用好,比盲目上复杂模型管用得多。
今天咱们就聊聊三个经典模型:ARIMA、GARCH 和 Prophet。它们各有各的脾气,也各有各的用武之地。
4.1 ARIMA:最基础的时序预测利器
ARIMA 全称是自回归积分滑动平均模型。名字挺唬人,其实拆开看就三部分:
- AR(自回归):用过去的值预测现在的值。比如今天股价跟昨天有关。
- I(差分):把非平稳序列变平稳。说白了就是让数据“老实”一点。
- MA(滑动平均):用过去的预测误差来修正当前预测。
我个人习惯用 ARIMA 做短期价格预测,比如预测未来 5-10 个交易日的走势。它有个好处——参数少,训练快,不容易过拟合。
4.1.1 定阶:p、d、q 怎么选?
这是 ARIMA 最头疼的地方。我刚开始做的时候也踩过坑,总想着把 p 和 q 设大一点,结果模型又慢又差。
我的经验是三步走:
- 先定 d:做 ADF 检验,看差分几次能平稳。一般金融数据 d=1 就够了。
- 再看 ACF 和 PACF 图:ACF 拖尾、PACF 截尾 → 选 AR;ACF 截尾、PACF 拖尾 → 选 MA。
- 最后用 AIC/BIC 验证:跑几个候选组合,选 AIC 最小的。
4.1.2 实战代码:用 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 包含 'close' 列)
df = pd.read_csv('stock_data.csv', index_col='date', parse_dates=True)
series = df['close']
# 1. 检查平稳性
from statsmodels.tsa.stattools import adfuller
result = adfuller(series)
print(f'ADF Statistic: {result[0]:.4f}')
print(f'p-value: {result[1]:.4f}')
# 如果 p-value > 0.05,需要差分
if result[1] > 0.05:
series_diff = series.diff().dropna()
d = 1
else:
series_diff = series
d = 0
# 2. 画 ACF 和 PACF 图(辅助定阶)
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8))
plot_acf(series_diff, ax=ax1, lags=20)
plot_pacf(series_diff, ax=ax2, lags=20)
plt.show()
# 3. 训练 ARIMA 模型(这里用 auto_arima 自动选参)
from pmdarima import auto_arima
model = auto_arima(series, seasonal=False, trace=True,
error_action='ignore', suppress_warnings=True)
print(model.summary())
# 4. 预测未来 10 天
forecast = model.predict(n_periods=10)
print("未来10天预测值:", forecast.values)
4.2 GARCH:捕捉波动率的“脾气”
做量化的都知道,金融数据有个特点——波动率会聚集。大涨之后往往跟着大跌,平静之后还是平静。这就是所谓的“波动聚集效应”。
ARIMA 只能预测价格本身,但 GARCH 模型专门用来预测波动率。说白了,它告诉你“市场现在有多躁动”。
4.2.1 GARCH 的核心思想
GARCH 模型认为:今天的波动率,取决于昨天的波动率和昨天的“冲击”(即残差平方)。
公式长这样:
σ²_t = ω + α * ε²_{t-1} + β * σ²_{t-1}
其中:
- σ²_t 是今天的条件方差(波动率)
- ε²_{t-1} 是昨天的残差平方(冲击)
- σ²_{t-1} 是昨天的波动率
- α + β 越接近 1,波动越持久
我记得有一次做期权定价,用 GARCH 预测的波动率比历史波动率准了将近 30%。原因很简单——历史波动率是平均的,但 GARCH 能捕捉到波动率的动态变化。
4.2.2 实战代码:用 GARCH 预测波动率
from arch import arch_model
# 假设 returns 是日收益率序列
returns = df['close'].pct_change().dropna() * 100
# 训练 GARCH(1,1) 模型
model = arch_model(returns, vol='Garch', p=1, q=1)
result = model.fit(disp='off')
print(result.summary())
# 预测未来 5 天的波动率
forecast = result.forecast(horizon=5)
print("未来5天波动率预测:")
print(forecast.variance.iloc[-1] ** 0.5) # 标准差形式
4.3 Prophet:Facebook 出品的“傻瓜式”时序模型
Prophet 是 Facebook 开源的时间序列预测工具。它的设计理念很直接——把时间序列拆成趋势、季节性和节假日效应三部分。
我个人觉得 Prophet 最大的优点是:对非专业用户友好。你不需要懂 ARIMA 那些复杂的定阶过程,也不需要调 GARCH 的参数。给它数据,它就能出结果。
4.3.1 Prophet 的三大组件
- 趋势项:线性或逻辑增长趋势,可以自动检测变点。
- 季节性项:年、周、日级别的周期性模式。
- 节假日项:特殊日期的影响,比如春节、双十一。
嗯,这里要注意:Prophet 对节假日特别敏感。如果你做的是中国市场的预测,记得把春节、国庆这些节日加进去。我有个朋友做电商销量预测,没加双十一的节假日效应,结果那天的预测值差了 40%。
4.3.2 实战代码:用 Prophet 预测销量
from prophet import Prophet
import pandas as pd
# Prophet 要求数据格式:ds(日期列),y(目标值)
df_prophet = df[['date', 'close']].rename(columns={'date': 'ds', 'close': 'y'})
# 创建模型
model = Prophet(
yearly_seasonality=True,
weekly_seasonality=True,
daily_seasonality=False,
changepoint_prior_scale=0.05 # 控制趋势变化的灵活度
)
# 添加节假日(以中国春节为例)
chinese_new_year = pd.DataFrame({
'holiday': 'chinese_new_year',
'ds': pd.to_datetime(['2024-02-10', '2025-01-29']),
'lower_window': -3,
'upper_window': 3
})
model.add_country_holidays(country_name='CN') # 自动添加中国节假日
# 训练模型
model.fit(df_prophet)
# 预测未来 30 天
future = model.make_future_dataframe(periods=30)
forecast = model.predict(future)
# 查看预测结果
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail(10))
4.4 三个模型怎么选?一张表说清楚
| 模型 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| ARIMA | 短期价格预测、平稳序列 | 参数少、可解释性强 | 对非平稳数据需要差分、无法处理波动率 |
| GARCH | 波动率预测、风险管理 | 捕捉波动聚集效应 | 对异常值敏感、参数估计不稳定 |
| Prophet | 有强季节性的数据、节假日效应明显 | 易用、自动处理缺失值 | 对突变趋势反应慢、不适合高频数据 |
我个人的经验是:做量化交易时,ARIMA 和 GARCH 经常搭配使用。ARIMA 预测价格方向,GARCH 预测波动率大小,两者结合就能做仓位管理。Prophet 更适合做业务层面的预测,比如用户增长、销量预估这些。
4.5 避坑指南:我踩过的三个坑
做时间序列模型,有些坑是新手必踩的。我当年也没少吃亏,分享出来大家少走弯路。
- 忘记做平稳性检验:直接用非平稳数据跑 ARIMA,结果全是伪回归。记住,先做 ADF 检验,不行就差分。
- GARCH 的残差假设:GARCH 假设残差服从正态分布,但金融数据往往有厚尾。我建议用学生 t 分布替代正态分布,效果会好很多。
- Prophet 的过拟合:Prophet 的变点检测太灵活,容易把噪声当成趋势。我一般把 changepoint_prior_scale 控制在 0.01-0.1 之间,别太大。
总结一下:时间序列模型不是越复杂越好。ARIMA 简单但有效,GARCH 专攻波动率,Prophet 适合有规律的数据。选对模型,比调参更重要。
下一章咱们聊聊特征工程——怎么从原始数据里挖出真正有用的信号。到时候我会分享一些我压箱底的特征构造技巧。