查看全集:💎Quantopia量化分析56讲
ARCH模型认为波动率具有自回归性,当前方差取决于过去平方残差的移动平均:
其中:
在ARCH基础上加入方差自身滞后项,形成更灵活的波动率模型:
其中:
特性 | ARCH(p) | GARCH(p,q) |
方程结构 | 仅过去残差平方项 | 加入历史方差项 |
参数效率 | 需要较多参数 | 参数更精简 |
适用场景 | 短期波动预测 | 中长期波动预测 |
import numpy as np
import math
def simulate_garch(T, a0, a1, b1, initial_vol):
"""模拟GARCH(1,1)过程"""
X = np.zeros(T)
sigma = np.zeros(T)
sigma[0] = initial_vol
for t in range(1, T):
X[t-1] = sigma[t-1] * np.random.normal(0, 1)
sigma[t] = math.sqrt(a0 + b1*sigma[t-1]**2 + a1*X[t-1]**2)
X[-1] = sigma[-1] * np.random.normal(0, 1)
return X, sigma
# 基本参数设置
a0 = 1.0 # 常数项
a1 = 0.1 # ARCH项系数
b1 = 0.8 # GARCH项系数
initial_vol = np.sqrt(a0 / (1 - a1 - b1)) # 初始波动率
# 模拟10000个样本
X, sigma = simulate_garch(10000, a0, a1, b1, initial_vol)
X = X[1000:] # 去除前10%的燃烧期数据
import matplotlib.pyplot as plt
plt.figure(figsize=(12,6))
plt.plot(X, label='GARCH Process')
plt.plot(sigma[1000:], label='Conditional Volatility', color='r')
plt.axhline(3*np.std(X), color='k', linestyle='--', label='3σ')
plt.legend()
plt.title('GARCH(1,1) Process Simulation');
其中:
零假设:不存在ARCH效应()
import statsmodels.api as sm
from scipy import stats
def arch_test(returns, p=5):
"""ARCH效应检验"""
squared_returns = returns**2
X = np.array([squared_returns[i-p:i] for i in range(p, len(returns))])
X = sm.add_constant(X)
model = sm.OLS(squared_returns[p:], X)
results = model.fit()
test_stat = len(returns)*results.rsquared
p_value = 1 - stats.chi2(df=p).cdf(test_stat)
return test_stat, p_value
# 示例应用
test_stat, p_val = arch_test(X, p=5)
print(f'卡方统计量: {test_stat:.2f}, p值: {p_val:.4f}')
尝试不同滞后阶数p(如3,5,10),观察检验结果的变化,思考如何选择最优滞后阶数?
通过最大化对数似然函数进行参数估计:
其中:
from scipy.optimize import minimize
def garch_loglikelihood(params, returns):
"""GARCH(1,1)对数似然函数"""
a0, a1, b1 = params
T = len(returns)
sigma2 = np.zeros(T)
# 初始化
sigma2[0] = np.var(returns)
for t in range(1,T):
sigma2[t] = a0 + a1*returns[t-1]**2 + b1*sigma2[t-1]
return -np.sum( -0.5*(np.log(sigma2) + returns**2/sigma2) )
# 参数估计示例
cons = ({'type': 'ineq', 'fun': lambda x: 1 - (x[1]+x[2])},
{'type': 'ineq', 'fun': lambda x: x[1]},
{'type': 'ineq', 'fun': lambda x: x[2]})
result = minimize(garch_loglikelihood, [0.1,0.1,0.8],
args=(X,), method='SLSQP', constraints=cons)
print('MLE估计参数:', result.x)
def gmm_objective(params, returns, W):
"""GMM目标函数"""
a0, a1, b1 = params
sigma2 = compute_sigma2(returns, a0, a1, b1)
residuals = returns / np.sqrt(sigma2)
# 构建矩条件
m1 = np.mean(residuals)
m2 = np.mean(residuals**2 - 1)
m3 = np.mean(residuals**3)
m4 = np.mean(residuals**4 - 3)
G = np.array([m1, m2, m3, m4])
return G.T @ W @ G
# 迭代估计过程需要多次优化
def forecast_volatility(params, last_vol, last_return, days=5):
"""向前预测波动率"""
a0, a1, b1 = params
forecasts = []
current_vol = last_vol
for _ in range(days):
next_vol = np.sqrt(a0 + a1*last_return**2 + b1*current_vol**2)
forecasts.append(next_vol)
current_vol = next_vol
last_return = 0 # 假设未来收益率为0
return forecasts
# 使用估计参数进行预测
params = [0.1, 0.1, 0.8]
last_vol = sigma[-1]
last_return = X[-1]
forecast = forecast_volatility(params, last_vol, last_return, days=10)
def monte_carlo_forecast(params, n_sims=1000, days=5):
"""蒙特卡洛波动率预测"""
all_sims = []
for _ in range(n_sims):
sim_returns, sim_vol = simulate_garch(days+1, *params, sigma[-1])
all_sims.append(sim_vol[1:])
return np.array(all_sims)
# 生成预测区间
forecasts = monte_carlo_forecast([0.1,0.1,0.8])
lower = np.percentile(forecasts, 5, axis=0)
upper = np.percentile(forecasts, 95, axis=0)
import yfinance as yf
data = yf.download('AAPL', start='2020-01-01', end='2023-01-01')
returns = data['Close'].pct_change().dropna()
通过本教程,您已掌握ARCH/GARCH模型的核心原理和实现方法。下一步可以探索: