GARCH波动率建模实战:条件方差、VaR回测与GJR非对称 简介这是一份面向金融计量、时间序列分析与量化投资学习者尤其是金融专业本科生与研究生的PPT课件围绕GARCH类模型展开适合课堂讲授、考前复习或实证建模参考。课件从ARCH过程讲起延伸到GARCH模型的检验与估计并覆盖EGARCH、TGARCH、GARCH-M等扩展形式同时结合金融时间序列的尖峰厚尾、波动丛聚与杠杆效应帮助读者理解条件异方差建模思路。压缩包内共1个PPT文件大小约749KB内容精炼便于直接放映、打印研读也适合作为公式推导、案例复盘与课堂笔记整理的辅助材料。目前已有266人学习下载说明其在相关课程与自学场景中具有一定参考价值。学完后可掌握GARCH模型的基本形式、参数含义、检验步骤及其在波动率预测、风险管理与金融数据分析中的典型应用。1. 波动率聚集GARCH 课件要讲清的第一件事同一只股票的日收益率连续两周的波动可能差出好几倍上一周每天在 0.6% 上下晃下一周天天 2.5% 起跳。更麻烦的是这种忽大忽小不是随机散布而是成串出现的——大波动后面跟着大波动平静期后面跟着平静期金融里管这叫波动率聚集。拿最小二乘去拟合这种序列残差图会呈现典型的纺锤形中间窄、两头宽。此时标准误被系统性低估t 检验和置信区间全部失真看似显著的因子可能只是异方差撑出来的假象。GARCH 模型针对的正是这个场景它不预测涨跌方向只估计收益率的条件方差把今天的波动有多大变成一个可估计、可检验、可外推的量。做风险计量的人用它算 VaR做量化的人拿它当波动率择时和期权定价的输入教时间序列课的人把它当作异方差建模的入口。一份能站住的 GARCH 课件必须回答三个问题参数怎么估、拟合结果怎么读、算出来的条件方差怎么落到风险数字上。下面按这条线从数学定义一路走到回测验证。2. 从条件方差方程到可运行的 GARCH(1,1)2.1 ARCH 到 GARCH方程里每一项在承担什么ARCH(q) 的想法很直接今天的方差取决于过去 q 期冲击的平方。问题在于金融数据的记忆很长为了覆盖足够长的记忆q 往往要取到 10 甚至 20参数一多就过拟合还容易出现负方差约束被破坏的情况。GARCH 的改进是把过去所有冲击压缩成一个递归项——用上一期的条件方差来替代无穷阶的滞后冲击。以 GARCH(1,1) 为例收益率方程和方差方程分别是均值方程r_t μ ε_tε_t σ_t · z_tz_t 服从均值为 0、方差为 1 的某种分布方差方程σ²_t ω α·ε²_{t-1} β·σ²_{t-1}三项各有分工。ω 对应长期方差的基准水平α 度量昨日新冲击对今日波动的影响强度β 度量波动记忆的衰减速度。α β 常被称为波动持久性越接近 1冲击衰减越慢等于 1 时就是 IGARCH冲击永不衰减。很多股票指数的日频数据估出来 α 在 0.08 附近、β 在 0.90 附近持久性 0.98 上下这个量级本身就说明波动一旦起来不会一两天就散掉。2.2 用 arch 包跑通 GARCH(1,1) 的最小命令Python 里最省事的路径是arch包它基于极大似然接口干净输出项也齐全。准备一份含日期和收盘价的 CSV下面这段就能跑出第一份拟合结果import numpy as np import pandas as pd from arch import arch_model # 读取日线收盘价date 列做索引 df pd.read_csv(close.csv, index_coldate, parse_datesTrue) price df[close].astype(float) # 对数收益率乘 100 做尺度缩放避免优化器数值下溢 ret 100 * np.log(price / price.shift(1)).dropna() # meanConstant 表示均值方程带常数项 # volGarch p1,q1 表示 GARCH(1,1) # distt 表示标准化残差服从 t 分布 model arch_model(ret, meanConstant, volGarch, p1, q1, distt) res model.fit(dispoff) # dispoff 关掉迭代日志 print(res.summary())代码逻辑分三步先做对数差分得到平稳的收益率序列再声明均值方程、方差方程和残差分布最后交给极大似然估计。dist这一项别省金融收益率尖峰厚尾是常态用正态分布会低估尾部后面的 VaR 会直接偏小。收益率乘 100 是行业习惯目的是把方差量级拉到 1 附近让优化器更容易收敛如果乘了 100最后把波动率换回百分比时记得除回去。2.3 拟合结果怎么读α、β 与波动持久性res.summary()会打印参数表、标准误、z 统计量和信息准则。关键几行对应的含义如下参数对应符号含义日频股票常见量级muμ均值方程常数项-0.05 ~ 0.10omegaω长期方差基准项0.01 ~ 0.10alpha[1]α昨日冲击权重0.05 ~ 0.15beta[1]β昨日条件方差权重0.80 ~ 0.92nuνt 分布自由度3 ~ 8读表时先看两处。第一nu的自由度估计值若落在 4 到 6 之间说明正态假设被数据明确否定尾部很厚如果nu估到 20 以上t 分布退化成近似正态说明这条序列其实没那么厚的尾。第二alpha[1] beta[1]的和它决定了波动率的记忆长度公式是半衰期约等于 ln(0.5)/ln(αβ)αβ0.98 时半衰期约 34 个交易日αβ0.90 时只剩 7 个交易日。res.conditional_volatility直接给出每期的 σ_t 序列可以直接画成图跟价格叠在一起看波动率抬升的时段是不是踩在行情剧烈波动的窗口上这是判断模型有没有抓对结构最快的办法。2.4 平稳性条件与三类典型报错GARCH(1,1) 要平稳需要 α β 1 且 ω 0、α ≥ 0、β ≥ 0。这三个约束在估计时是隐含的参数跑出区间外来多半不是模型的问题而是数据或设置的问题。常见报错和对应处理ConvergenceWarning: Maximum Likelihood optimization failed to converge。先试着把收益率乘 100 做尺度缩放多数情况能解决仍有警告就调res model.fit(dispoff, options{maxiter: 500})加大迭代次数。估出的 α 或 β 为负。检查输入序列是不是已经差分过两次或是不是把价格当收益率传了进去量纲错位会直接破坏约束。参数值大得离谱、标准误也离谱。通常是样本太短少于 250 个观测点或者序列里混入了涨跌停造成的零收益段前者扩样本后者去极值或换指数数据。提示如果 α β 估到 1.0 以上先别急着换 IGARCH。用res.params打印全部参数确认是不是omega被压到了接近 0这种情况往往说明序列的波动水平本身就在漂移需要考虑加结构突变或换更长的样本窗口。3. GARCH 定阶与参数估计ARCH-LM 检验和 AIC 网格搜索3.1 建模前的三道体检平稳性、自相关与 ARCH 效应直接上 GARCH 是最常见的错误。它的前提是序列本身平稳、均值方程已经把可预测的线性结构拿走、残差里确实还存在条件异方差。这三步按顺序做任何一步不过关后面估出来的参数都只是在拟合噪声。平稳性用 ADF 检验看单位根statsmodels.tsa.stattools.adfuller返回的 p 值小于 0.05 才算过。价格序列基本都不平稳收益率序列基本都平稳这一步主要是防止误把价格传进去。自相关看收益率本身的 ACF如果前几阶显著不为零说明均值方程要加 AR 项否则这部分结构会污染方差方程的估计。ARCH 效应对均值方程的残差做 ARCH-LM 检验这是决定要不要上 GARCH的判别步骤。3.2 ARCH-LM 检验的代码与滞后阶数取法ARCH-LM 检验的思路是把残差平方对自身滞后项做回归看回归是否显著。原假设是不存在 ARCH 效应p 值小于 0.05 才能拒绝原假设、确认有异方差结构可建模。from statsmodels.stats.diagnostic import het_arch # 取均值方程的残差 resid res.resid # nlags 是检验用的滞后阶数 lm_stat, p_value, f_stat, f_p het_arch(resid, nlags12) print(fLM统计量{lm_stat:.3f}, p值{p_value:.4f}) # 另外看残差平方的ACF前几阶是否明显跳出置信带 from statsmodels.tsa.stattools import acf acf_sq acf(resid**2, nlags20, fftFalse) print(acf_sq[:6])nlags怎么取是这一步最容易翻车的地方。取太小会漏掉中长记忆取太大在小样本下检验功效会掉。日频数据常用 10 到 12周频数据取 4 到 6样本量低于 500 时建议不超过 10。另外要注意这里的残差必须来自已经指定了均值方程的模型如果直接对原始收益率做检验检验结果会把均值结构误判成 ARCH 效应。判定完成后残差平方的 ACF 图还能给出一个直觉上的阶数提示如果只有前 1 到 2 阶显著GARCH(1,1) 通常就够用如果前 5 阶都显著可以在定阶时把 q 的范围放宽。3.3 用 AIC/BIC 网格搜索给 (p,q) 定阶GARCH 的阶数不像 ARIMA 那样有清晰的 ACF/PACF 截尾拖尾规则实践中最稳的办法就是把 p 和 q 各自扫一遍用信息准则挑。下面这段用一个嵌套循环把候选模型全跑一遍import pandas as pd results [] for p in range(1, 4): for q in range(1, 4): try: m arch_model(ret, meanConstant, volGarch, pp, qq, distt) r m.fit(dispoff) results.append({p: p, q: q, aic: r.aic, bic: r.bic, loglik: r.loglikelihood}) except Exception as e: # 个别组合可能不收敛跳过并记录 results.append({p: p, q: q, aic: None, bic: None, loglik: None}) table pd.DataFrame(results).sort_values(bic) print(table.head(8))跑出来的典型结果大致是这样pqAICBIC对数似然113.4123.451-1690.2123.4083.457-1688.1213.4063.455-1687.0223.4093.468-1686.5133.4153.474-1689.3AIC 倾向于选参数更多的模型BIC 对参数个数惩罚更重。两种准则打架时优先看 BIC因为 GARCH 多一个参数就多一组约束样本量不够时高阶模型很容易在样本外崩掉。上表里 AIC 最小的是 (2,1)BIC 最小的是 (1,1)这种情况我会直接用 (1,1)除非残差诊断明确显示还有结构没被吃掉。3.4 残差分布假设正态、t 与偏 t 的取舍分布假设直接决定尾部风险定价的高低三个选项的差别很实在distnormal只有均值方程残差确实接近正态时才用。日频股票数据里几乎不会通过跑出来最大的问题是 VaR 系统性偏小。distt默认首选多估一个自由度参数 ν用 t 分布替代正态去承接厚尾。代价是参数多一个样本太短时会不稳。distskewt在 t 基础上再加一个偏度参数适合收益率分布明显左偏的品种比如带杠杆效应的股指。样本量建议在 1000 以上再考虑。换分布之后AIC 不能直接跨分布比较绝对值因为似然函数的常数项不同。可行的比较方式是看残差诊断把标准化残差 z_t ε_t / σ_t 提出来看它的峰度是不是降到了接近 0正态为 3再看 ARCH-LM 检验的 p 值是不是足够大。3.5 估计不收敛时的排查顺序不收敛是 GARCH 建模最高频的故障按下面的顺序排查效率最高尺度问题。把收益率乘 100 或乘 1000让数值落在优化器友好的区间这一条能解决大半问题。样本问题。样本量低于 250 时参数不稳低于 100 基本没有估计价值先补数据。数据问题。检查有没有缺失值被填成 0、有没有单日翻倍这种没复权的异常点异常点会主导整个似然函数。分布问题。正态假设下不收敛时换 t 分布有时反而更稳。阶数问题。把 p、q 都退回 1 再试高阶模型在短样本上几乎必炸。注意不要为了让模型收敛去手动改omega的初值除非你清楚数据的方差量级。arch提供的res model.fit(starting_values...)应该留给需要复用上一轮估计结果的批量场景而不是当作调参手段。4. 把 GARCH 条件方差换成 VaR 与波动率回测4.1 一步向前波动率预测的解析式与代码条件方差估出来之后预测一步向前波动率并不需要重新拟合套递推式即可σ²_{t1|t} ω α·ε²_t β·σ²_tarch包把这一步封装成了forecast# horizon1 表示只预测未来一期 # reindexFalse 表示不把预测结果对齐到原始时间索引 fc res.forecast(horizon1, reindexFalse) # 取最后一期对应的预测方差 var_next fc.variance.values[-1, 0] sigma_next np.sqrt(var_next) print(f下一期条件波动率 {sigma_next:.4f}%)注意这里输出的单位跟输入一致。前面收益率乘了 100所以sigma_next是百分比波动率日频股票典型的量级在 1.0 到 2.5 之间。如果你的数据没做缩放这个数字会小两个数量级换算时要小心。多步预测可以直接把horizon调大fc.variance会返回一个矩阵行是时间点、列是预测步长。多步预测的方差会逐步收敛到长期方差 ω/(1-α-β)这个收敛过程本身也是课件里可以画的一张图——它直观说明了波动预测在短期有效、长期只能回归均值。4.2 把条件方差换成 VaR 与 ESGARCH 的价值在于它给出的是时变方差而不是一个常数。用常数方差算 VaR等于假设风险水平每天一样遇到行情切换必然失效。用 GARCH 的条件方差算风险数字会自己跟着市场变。以多头持仓、置信水平 99% 为例单期 VaR 的表达式是 VaR_t -(μ q_α · σ_t)其中 q_α 是标准化残差分布的 α 分位数。t 分布的分位数要做方差归一化因为标准 t 分布的方差是 ν/(ν-2) 而不是 1from scipy.stats import t nu res.params[nu] # 估计出的自由度 mu res.params[mu] # 均值方程常数项 alpha_level 0.01 # 99% 置信水平 # 标准化 t 分布的分位数先算 t 分位再除以标准差 q t.ppf(alpha_level, nu) / np.sqrt(nu / (nu - 2)) # 逐期 VaR 序列cond_vol 来自模型拟合结果 cond_vol res.conditional_volatility var_series -(mu q * cond_vol) print(var_series.tail(5))逻辑上分两步先把分位数从 t 分布转成标准化残差尺度再乘上每期各自的条件波动率。少了归一化这一步VaR 会被系统性放大ν 越小尾部越厚偏差越大ν5 时误差接近 12%。期望损失 ES 的做法类似用 t 分布在 α 处的条件期望公式为 ES -σ_t · (f(q) / α)其中 f 是标准化 t 分布的密度函数。ES 的好处是它满足次可加性多个头寸合并时不会出现分散后风险更大的悖论。4.3 回测Kupiec POF 检验与失败率VaR 算出来必须回测否则没人知道它是保守还是激进。Kupiec 的 POF比例失败检验是最常用的工具思路是统计实际突破次数跟理论失败率比较构造似然比统计量。import numpy as np # 实际收益率是否击穿 VaR取负号后比较 hits (ret.values -var_series.values).astype(int) n len(hits) x hits.sum() p alpha_level # 理论失败率 phat x / n # 实际失败率 # 似然比统计量 lr -2 * np.log(((1 - p) ** (n - x) * p ** x) / ((1 - phat) ** (n - x) * phat ** x)) print(f突破次数{x}, 实际失败率{phat:.4f}, LR{lr:.3f}) # 自由度1的卡方分布临界值95% 置信下为 3.841结果判读要看两件事指标含义合格范围实际失败率突破次数 / 总样本与理论值偏离不超过 30%LR 统计量偏离显著性小于 3.841突破聚集度突破是否扎堆出现不应连续多期突破第三项经常被忽略。LR 检验通过不代表模型合格如果所有突破都挤在两周之内说明模型在波动率切换的拐点上反应太慢典型原因是 β 被估得偏高导致条件方差对新冲击响应迟钝。这时可以试试加一个 GJR 项让负冲击有额外权重。4.4 课件里最该摆的两组数做课件时把结果堆成参数表意义不大观众记不住 ω、α、β 的具体数值。更有效的做法是摆两组对比数一组是 GARCH 条件方差算出的 VaR 与常数方差算出的 VaR 在同一段行情里的走势对比让波动率的时变性肉眼可见另一组是两种方法的回测失败率对照表用数字说明差距。表格设计上一列放模型设定常数方差 / GARCH-N / GARCH-t / GJR-GARCH一列放实际失败率一列放 LR 统计量一列放平均 VaR 水平。四行摆在一起能同时讲清哪个模型更准和哪个模型更省资本这两个经常冲突的目标比单看 AIC 有说服力得多。5. 非对称 GARCH 与 GJR 项的显著性验证标准 GARCH 有一个前提正冲击和负冲击对波动率的影响完全对称。现实里这个假设经常不成立股市下跌带来的波动抬升通常比同幅度上涨更猛这就是杠杆效应。GJR-GARCH 的做法是在方差方程里加一项只在冲击为负时生效σ²_t ω α·ε²_{t-1} γ·ε²_{t-1}·I(ε_{t-1} 0) β·σ²_{t-1}在arch里对应的是o1参数o就是非对称项阶数# o1 开启非对称项其余设置与对称模型保持一致 m_gjr arch_model(ret, meanConstant, volGarch, p1, o1, q1, distt) res_gjr m_gjr.fit(dispoff) # gamma[1] 即杠杆系数显著为正说明负冲击放大波动 print(res_gjr.summary()) print(gamma:, res_gjr.params.get(gamma[1]))判读方式很直接gamma[1]的 p 值小于 0.05 且符号为正杠杆效应成立此时对称 GARCH 的 VaR 在下跌行情里会明显偏小。把两个模型并排对比结论一目了然模型gamma[1]p 值BIC99% 失败率GARCH(1,1)-t无无3.4511.42%GJR-GARCH(1,1,1)-t0.0860.0033.4381.09%gamma 显著、BIC 变小、失败率向 1% 收敛三个信号同时出现才值得换模型。只凭 AIC 变小就切过去多半是过拟合。另一个容易踩的坑是加非对称项后 α 会明显变小这是正常的因为部分冲击的权重被 γ 分走了不要误以为模型出了问题。验证完非对称性顺手做一次参数敏感性检查——把样本末 200 个观测点截掉重估一遍看 αβ 和 gamma 的符号是否稳定。符号翻转说明这两个参数是被少数极端值撑起来的这样的模型拿去算 VaR在样本外遇到新的行情结构会立刻失效剩下的选择要么扩大样本要么换 EGARCH 把非对称写进对数方差里再比一次。本文还有配套的精品资源点击获取