AR / MA / ARIMA 模型
直觉
ACF 告诉我们「有没有结构」。ARIMA 把这个结构参数化:AR(自回归)用过去的值预测现在,MA(滑动平均)用过去的冲击预测现在,I(差分)把非平稳变平稳。三者组合(p, d, q)就是 ARIMA。
模型形式
- :AR 阶数(用几个过去值);
- :差分阶数( 即对价格取一阶差分=收益);
- :MA 阶数(用几个过去冲击)。
「人话」解释:怎么定阶 p, d, q?
:差分到平稳为止(价格 ,收益 ),用 ADF 判断。 :看 ACF/PACF 的截尾形态,或更实用地——扫几个组合,选 AIC/BIC 最小的。 AIC 在「拟合好」和「参数少」之间平衡,越小越好。
可运行案例:拟合 AR(1) 并对真实收益建模
先用构造的 AR(1) 验证能还原参数;再用 AIC 定阶;最后对真实收益拟合——你会发现系数接近 0,说明收益近似白噪声、很难预测。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.arima.model import ARIMA
# 1) 构造 AR(1): x_t = 0.6 x_{t-1} + noise
rng = np.random.default_rng(3)
n = 1000
x = np.zeros(n); phi = 0.6
for t in range(1, n):
x[t] = phi * x[t-1] + rng.standard_normal()
m = ARIMA(x, order=(1, 0, 0)).fit()
print(f"真值 phi=0.6 估计 phi={m.params['ar.L1']:.3f}")
print("\nAIC 定阶(越小越好):")
for p in range(4):
print(f" AR({p}): AIC = {ARIMA(x, order=(p,0,0)).fit().aic:.1f}")
# 2) 真实收益: 近似白噪声
df = pd.read_csv('/data/spy_daily.csv', parse_dates=['date']).set_index('date')
ret = np.log(df['adj_close'] / df['adj_close'].shift(1)).dropna()
mr = ARIMA(ret, order=(1, 0, 0)).fit()
fc = mr.forecast(30)
print(f"\n真实收益 AR(1) phi={mr.params['ar.L1']:.3f} → 接近0,近似白噪声")
plt.figure(figsize=(8, 3.2))
plt.plot(range(200), ret.values[-200:], lw=0.8, label='历史(末 200 日)')
plt.plot(range(200, 230), fc, color='crimson', lw=1.6, label='30 步预测')
plt.axhline(ret.mean(), color='gray', ls='--', lw=0.8, label='长期均值')
plt.title('收益 AR(1) 预测:很快收敛到均值(水平线)'); plt.legend(fontsize=8)
plt.tight_layout(); plt.show()
小结
- ARIMA(p,d,q):AR 用过去值、MA 用过去冲击、I 差分到平稳;
- 定阶: 看 ADF, 看 AIC/BIC;
- 真实收益的 AR 系数≈0 → 近似白噪声,均值类模型难以预测收益本身(这铺垫了下一节:波动率却有结构)。