查看全集:💎Quantopia量化分析56讲
自回归模型(Autoregressive Model)通过将时间序列的历史值作为自变量进行回归建模。AR(p)模型表示使用p个历史滞后项:
AR(1)模型公式
AR(p)模型公式
其中:
建立AR模型需满足协方差平稳性:
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
def generate_ar_process(coefs, n=1000):
p = len(coefs)
X = np.zeros(n)
for t in range(p, n):
X[t] = np.dot(coefs, X[t-p:t][::-1]) + np.random.normal()
return X
# 生成AR(2)序列:X_t = 0.5X_{t-1} + 0.3X_{t-2} + ε
ar_coefs = [0.5, 0.3]
X = generate_ar_process(ar_coefs)
plt.plot(X)
plt.title('模拟AR(2)序列')
plt.show()
小练习
尝试修改系数为[0.9, -0.5],观察序列形态变化
AR序列比正态分布更易出现极端值:
from scipy.stats import norm
def compare_tails(data):
plt.figure(figsize=(10,4))
plt.subplot(121)
plt.hist(data, bins=50, density=True)
x = np.linspace(-4,4,100)
plt.plot(x, norm.pdf(x), 'r')
plt.subplot(122)
plt.hist(np.diff(data), bins=50, density=True)
plt.plot(x, norm.pdf(x), 'r')
compare_tails(X)
传统方差估计会导致置信区间错误:
from statsmodels.tsa.ar_model import AutoReg
model = AutoReg(X, lags=2).fit()
print('真实方差:', np.var(model.resid))
print('朴素估计:', np.var(X))
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
plt.figure(figsize=(12,4))
plt.subplot(121)
plot_acf(X, lags=20, ax=plt.gca())
plt.subplot(122)
plot_pacf(X, lags=20, ax=plt.gca())
plt.show()
使用信息准则选择最优p值:
max_lag = 5
aic_values = []
bic_values = []
for p in range(1, max_lag+1):
model = AutoReg(X, lags=p).fit()
aic_values.append(model.aic)
bic_values.append(model.bic)
plt.plot(range(1,max_lag+1), aic_values, label='AIC')
plt.plot(range(1,max_lag+1), bic_values, label='BIC')
plt.legend()
plt.xlabel('滞后阶数')
plt.ylabel('信息准则值')
import yfinance as yf
import pandas as pd
# 获取苹果公司股价
data = yf.download('AAPL', start='2018-01-01', end='2023-01-01')
prices = data['Close'].pct_change().dropna() # 使用收益率序列
from statsmodels.tsa.ar_model import AutoReg
# 自动选择最佳滞后阶数
model = AutoReg(prices, lags=5).fit()
print(model.summary())
# 预测未来5日
forecast = model.predict(start=len(prices), end=len(prices)+5)
小练习
尝试对MSFT股票收益率建立AR模型,比较不同滞后阶数的预测效果
residuals = model.resid
# 正态性检验
from statsmodels.stats.diagnostic import normal_ad
_, p_value = normal_ad(residuals)
print(f'正态性检验p值:{p_value:.4f}')
# 自相关检验
from statsmodels.stats.stattools import durbin_watson
print(f'DW统计量:{durbin_watson(residuals):.2f}')
train_size = int(len(prices)*0.8)
train, test = prices[:train_size], prices[train_size:]
predictions = []
for t in range(len(test)):
model = AutoReg(train, lags=3).fit()
pred = model.predict(start=len(train), end=len(train))
predictions.append(pred[0])
train = train.append(test.iloc[t])
plt.plot(test.values, label='真实值')
plt.plot(predictions, label='预测值')
plt.legend()
延伸学习建议