跳到主内容
研究主线时间序列与统计套利 · 第43–50讲6/8模块导览 →
讲义

第48讲:ARCH、GARCH和GMM模型 (ARCH, GARCH, and GMM)

介绍 ARCH、GARCH 与 GMM 的建模假设、参数估计和诊断流程,并用模拟序列比较条件波动率模型的差异。

完成状态保存在当前浏览器,可随时取消。

关键概念解析#

ARCH模型(自回归条件异方差)#

ARCH模型认为波动率具有自回归性,当前方差取决于过去平方残差的移动平均:

σt2=α0+α1εt12+...+αpεtp2σ_t^2 = α_0 + α_1ε_{t-1}^2 + ... + α_pε_{t-p}^2

其中:

  • σt2σ_t^2 为t时刻的条件方差

  • εti2ε_{t-i}^2 为滞后i期的残差平方

  • αiα_i为模型参数

  • pp为滞后阶数

GARCH模型(广义自回归条件异方差)#

在ARCH基础上加入方差自身滞后项,形成更灵活的波动率模型:

σt2=ω+αεt12+βσt12σ_t^2 = ω + αε_{t-1}^2 + βσ_{t-1}^2

其中:

  • ωω 为常数项

  • αα 为ARCH项系数

  • ββ 为GARCH项系数

  • εt12ε_{t-1}^2 为滞后一期的残差平方

  • σt12σ_{t-1}^2 为滞后一期的条件方差

模型演进对比#

特性ARCH(p)GARCH(p,q)
方程结构仅过去残差平方项加入历史方差项
参数效率需要较多参数参数更精简
适用场景短期波动预测中长期波动预测

模拟GARCH(1,1)过程#

参数设置与模拟函数#

code
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

参数配置示例#

code
# 基本参数设置
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%的燃烧期数据

可视化对比#

code
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效应检验#

检验步骤#

  1. 对收益率序列进行OLS回归:εt2=γ0+γ1εt12+...+γpεtp2ε_t^2 = γ_0 + γ_1ε_{t-1}^2 + ... + γ_pε_{t-p}^2

  2. 计算检验统计量:TR2χ2(p)TR^2 \sim \chi^2(p)

  3. 判断显著性

其中:

  • εt2ε_t^2为残差平方序列

  • γiγ_i为回归系数

  • pp 为检验的滞后阶数

  • TT 为样本容量

  • R2R^2 为回归方程的判定系数

  • χ2(p)\chi^2(p) 表示自由度为p的卡方分布

零假设H0H_0:不存在ARCH效应(γ1=γ2=...=γp=0γ_1 = γ_2 = ... = γ_p = 0)

code
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),观察检验结果的变化,思考如何选择最优滞后阶数?

参数估计方法#

最大似然估计(MLE)#

通过最大化对数似然函数进行参数估计:

L(θ)=12t=1T(ln(σt2)+εt2σt2)L(θ) = -\frac{1}{2}\sum_{t=1}^T \left( \ln(σ_t^2) + \frac{ε_t^2}{σ_t^2} \right)

其中:

  • L(θ)L(θ)为对数似然函数

  • θθ 为待估计的参数集合

  • σt2σ_t^2 为条件方差

  • εt2ε_t^2 为残差平方

  • TT 为样本量

  • ln\ln 为自然对数

  • \sum表示求和

code
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)

GMM估计#

code
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

# 迭代估计过程需要多次优化

实战:预测波动率#

使用历史数据进行预测#

code
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)

蒙特卡洛模拟#

code
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)

练习题#

  1. 尝试修改ARCH项的系数a1,观察模拟序列的尖峰厚尾现象变化

  2. 使用yfinance获取真实股票数据,应用ARCH检验并比较结果

code
import yfinance as yf
data = yf.download('AAPL', start='2020-01-01', end='2023-01-01')
returns = data['Close'].pct_change().dropna()
  1. 比较不同初始值对MLE估计结果的影响,思考稳健性改进方法

通过本教程,您已掌握ARCH/GARCH模型的核心原理和实现方法。下一步可以探索:

  • 多元GARCH模型的实现

  • 结合波动率预测的交易策略

  • 使用机器学习方法改进传统GARCH模型