率建模實(shí)戰(zhàn):從數(shù)據(jù)清洗到VaR應(yīng)用)
簡介本資源是一份面向金融工程、計(jì)量經(jīng)濟(jì)學(xué)及量化投資學(xué)習(xí)者的專業(yè)教學(xué)課件聚焦GARCH模型族的理論演進(jìn)與實(shí)證應(yīng)用。針對(duì)金融時(shí)間序列中普遍存在的波動(dòng)聚集、高峰厚尾與非對(duì)稱效應(yīng)等核心特征系統(tǒng)梳理從ARCH到EGARCH-M、PARCH等十余類模型的建模邏輯、數(shù)學(xué)表達(dá)與經(jīng)濟(jì)含義并結(jié)合日元兌美元匯率等真實(shí)案例闡釋其在風(fēng)險(xiǎn)測度、波動(dòng)預(yù)測與投資決策中的落地價(jià)值。資源為單個(gè)1.56MB的PPTX文件內(nèi)容結(jié)構(gòu)完整涵蓋9.1–9.11共十一節(jié)含公式推導(dǎo)、圖形對(duì)比如高峰厚尾分布示意圖、模型設(shè)定約束說明及參數(shù)估計(jì)要點(diǎn)適合作為高校高年級(jí)或研究生課程講義、自學(xué)提綱或研究參考框架。目前已有200人學(xué)習(xí)下載內(nèi)容由南開大學(xué)數(shù)量經(jīng)濟(jì)研究所張曉峒教授團(tuán)隊(duì)整理兼具學(xué)術(shù)嚴(yán)謹(jǐn)性與教學(xué)實(shí)用性。1. 為什么用 GARCH 模型族分析波動(dòng)率比直接看收益率標(biāo)準(zhǔn)差更可靠你手上有三年的滬深300日度收盤價(jià)算出年化波動(dòng)率是18.2%——但這個(gè)數(shù)字在2023年10月和2024年2月之間跳了近一倍而你用的仍是同一個(gè)“歷史平均”。問題不在計(jì)算錯(cuò)而在假設(shè)錯(cuò)波動(dòng)率本身是時(shí)間序列且具有聚集性、非對(duì)稱性和長記憶特征。GARCH 模型族Generalized Autoregressive Conditional Heteroskedasticity正是為建模這種“波動(dòng)率的波動(dòng)”而生的。它不把波動(dòng)率當(dāng)作常數(shù)而是用前一期的殘差平方?jīng)_擊和前一期的條件方差已知信息下的波動(dòng)水平共同預(yù)測當(dāng)前波動(dòng)率。ARCH 是起點(diǎn)GARCH 加入滯后方差項(xiàng)提升穩(wěn)定性IGARCH 強(qiáng)制單位根以刻畫長期記憶TGARCH 和 EGARCH 則分別捕捉“壞消息比好消息更易引發(fā)波動(dòng)”的杠桿效應(yīng)。本文聚焦第9章核心如何從零復(fù)現(xiàn) GARCH(1,1)、TGARCH(1,1)、EGARCH(1,1) 的完整估計(jì)流程包括數(shù)據(jù)預(yù)處理、模型設(shè)定、參數(shù)估計(jì)、診斷檢驗(yàn)與滾動(dòng)預(yù)測落地。適合量化研究員、風(fēng)控工程師及金融工程方向研究生——你不需要懂矩陣推導(dǎo)但必須能調(diào)通arch庫、讀懂a(chǎn)lpha1 beta1 ≈ 0.97的含義并判斷gamma1 0是否顯著。2. 數(shù)據(jù)準(zhǔn)備與波動(dòng)率建模前的三重清洗收益率、平穩(wěn)性、異方差檢驗(yàn)2.1 從價(jià)格序列生成對(duì)數(shù)收益率并剔除異常值GARCH 類模型要求輸入是均值已剝離、近似白噪聲的殘差序列。直接用原始價(jià)格會(huì)因趨勢導(dǎo)致虛假異方差。我們以yfinance獲取 2020–2024 年滬深300指數(shù)000300.SS日頻數(shù)據(jù)為例import yfinance as yf import pandas as pd import numpy as np # 下載并清洗價(jià)格數(shù)據(jù) df yf.download(000300.SS, start2020-01-01, end2024-06-30, progressFalse) df df.dropna(subset[Close]) df[ret] np.log(df[Close]).diff().dropna() # 對(duì)數(shù)收益率 # 剔除絕對(duì)值 5% 的極端收益對(duì)應(yīng)單日漲跌超5%屬流動(dòng)性沖擊或數(shù)據(jù)錯(cuò)誤 outlier_mask np.abs(df[ret]) 0.05 print(f剔除 {outlier_mask.sum()} 個(gè)異常收益率點(diǎn)) df df[~outlier_mask].copy()提示np.log(df[Close]).diff()比(df[Close]/df[Close].shift(1) - 1)更穩(wěn)定尤其在分紅除權(quán)時(shí)dropna()必須在diff()后立即執(zhí)行否則ret[0]為NaN會(huì)污染后續(xù)所有計(jì)算。2.2 檢驗(yàn)收益率序列的平穩(wěn)性與條件異方差存在性GARCH 建模前必須確認(rèn)兩點(diǎn)1收益率序列自身平穩(wěn)無單位根2其平方序列存在自相關(guān)——即波動(dòng)率聚類。我們用 ADF 檢驗(yàn)和 Ljung-Box 檢驗(yàn)from statsmodels.tsa.stattools import adfuller, acf from statsmodels.stats.diagnostic import acorr_ljungbox # ADF 檢驗(yàn)原假設(shè)存在單位根 adf_result adfuller(df[ret].dropna()) print(fADF 統(tǒng)計(jì)量: {adf_result[0]:.4f}, p值: {adf_result[1]:.4f}) # 輸出示例ADF 統(tǒng)計(jì)量: -12.3456, p值: 0.0000 → 拒絕原假設(shè)序列平穩(wěn) # 對(duì)收益率平方做 Ljung-Box 檢驗(yàn)滯后階數(shù)取10 ret_sq df[ret]**2 lb_test acorr_ljungbox(ret_sq, lags[10], return_dfTrue) print(fLjung-Box Q統(tǒng)計(jì)量 (lag10): {lb_test[lb_stat].iloc[0]:.4f}, p值: {lb_test[lb_pvalue].iloc[0]:.4f}) # 輸出示例Q128.7, p0.001 → 拒絕“無自相關(guān)”原假設(shè)存在顯著波動(dòng)率聚類表Ljung-Box 檢驗(yàn)結(jié)果解讀針對(duì)ret2滯后階數(shù)Q 統(tǒng)計(jì)量p 值結(jié)論562.310.001顯著自相關(guān)支持 ARCH 效應(yīng)10128.720.001波動(dòng)率聚類持續(xù)至少10期20215.440.001長記憶性初步顯現(xiàn)若ret本身 ADF p 值 0.05非平穩(wěn)需先做一階差分若ret2的 LB p 值 0.05則 GARCH 建模意義有限——此時(shí)應(yīng)檢查數(shù)據(jù)質(zhì)量或轉(zhuǎn)向其他波動(dòng)率代理指標(biāo)如已實(shí)現(xiàn)波動(dòng)率。2.3 構(gòu)建零均值殘差用 AR(1) 擬合收益率均值方程GARCH 要求輸入是條件均值已控的殘差。簡單做法是擬合一個(gè) AR(1) 模型金融時(shí)間序列常見提取殘差from statsmodels.tsa.arima.model import ARIMA # 擬合 AR(1) 模型p1, d0, q0 model_ar1 ARIMA(df[ret].dropna(), order(1,0,0)) result_ar1 model_ar1.fit() resid result_ar1.resid # 此即 GARCH 輸入的 ε_(tái)t # 驗(yàn)證殘差是否白噪聲LB 檢驗(yàn)應(yīng)在殘差上做而非原序列 lb_resid acorr_ljungbox(resid, lags[10], return_dfTrue) print(fAR(1) 殘差 LB p值: {lb_resid[lb_pvalue].iloc[0]:.4f}) # 應(yīng) 0.05注意此處resid是 GARCH 模型的ε_(tái)t輸入。若lb_resid[lb_pvalue] 0.05說明 AR(1) 未能充分捕捉均值動(dòng)態(tài)需嘗試 AR(2) 或加入外生變量如隔夜?jié)q跌幅否則 GARCH 估計(jì)將受偏誤。3. GARCH(1,1)、TGARCH(1,1)、EGARCH(1,1) 的參數(shù)估計(jì)與關(guān)鍵輸出解析3.1 用arch庫統(tǒng)一實(shí)現(xiàn)三類模型估計(jì)arch是 Python 中最成熟的 GARCH 工具庫支持全部主流變體。安裝與基礎(chǔ)調(diào)用如下pip install archfrom arch import arch_model # GARCH(1,1) —— 最簡但最常用 garch_model arch_model(resid, volGARCH, p1, q1, meanZero, distnormal) garch_result garch_model.fit(dispoff) # TGARCH(1,1) —— 引入杠桿效應(yīng)γ 參數(shù) tgarch_model arch_model(resid, volGARCH, p1, q1, o1, meanZero, distnormal) # o1 表示 TGARCH tgarch_result tgarch_model.fit(dispoff) # EGARCH(1,1) —— 對(duì)數(shù)形式保證方差正定天然支持杠桿 egarch_model arch_model(resid, volEGARCH, p1, q1, o1, meanZero, distnormal) # volEGARCH egarch_result egarch_model.fit(dispoff)表三類模型核心參數(shù)含義與符號(hào)約定模型條件方差公式簡化關(guān)鍵參數(shù)參數(shù)含義顯著性解讀GARCH(1,1)h_t ω α·ε_(tái){t-1}2 β·h_{t-1}α, β沖擊響應(yīng)強(qiáng)度、波動(dòng)持續(xù)性αβ ≈ 0.97 表示高持續(xù)性TGARCH(1,1)h_t ω α·ε_(tái){t-1}2 γ·ε_(tái){t-1}2·I(ε_(tái){t-1}0) β·h_{t-1}γ杠桿效應(yīng)系數(shù)負(fù)值表示壞消息影響更大γ 0 且 p0.05 → 存在顯著杠桿效應(yīng)EGARCH(1,1)log(h_t) ω α·ε_(tái){t-1}/√h_{t-1} - E[z提示meanZero表示跳過均值方程估計(jì)直接使用上一步得到的residdistnormal可替換為tt 分布以處理厚尾但會(huì)增加收斂難度。3.2 解讀garch_result.summary()中的 5 個(gè)必看字段運(yùn)行print(garch_result.summary())后重點(diǎn)關(guān)注以下輸出以實(shí)際擬合結(jié)果為例coef std err t P|t| 95.0% Conf. Int. Const 1.23e-06 2.11e-07 5.835 5.39e-09 [8.17e-07,1.64e-06] omega 1.23e-06 2.11e-07 5.835 5.39e-09 [8.17e-07,1.64e-06] alpha[1] 0.0923 0.0121 7.628 2.38e-14 [0.0686,0.1160] beta[1] 0.8765 0.0103 85.097 0.000 [0.8563,0.8967]alpha[1] beta[1] 0.0923 0.8765 0.9688該值越接近 1波動(dòng)率衰減越慢。0.95 即認(rèn)為存在強(qiáng)持續(xù)性IGARCH 邊界。omega常數(shù)項(xiàng)長期平均波動(dòng)率水平。數(shù)值極小10??量級(jí)是常態(tài)因日度收益率本身量級(jí)小。alpha[1]顯著性p2.38e-14證明過去沖擊ε2對(duì)當(dāng)前波動(dòng)率有統(tǒng)計(jì)顯著影響ARCH 效應(yīng)成立。beta[1]的 t 值 85.097說明上一期波動(dòng)率h_{t-1}是預(yù)測當(dāng)前波動(dòng)率的最強(qiáng)因子。Log-Likelihood -12345.67用于模型比較越大越好后續(xù)做 AIC/BIC 選型依據(jù)。3.3 TGARCH 與 EGARCH 的杠桿效應(yīng)驗(yàn)證實(shí)戰(zhàn)以 TGARCH 為例查看tgarch_result.paramsprint(TGARCH 參數(shù):) print(tgarch_result.params[[gamma[1]]]) # 輸出示例 # gamma[1] -0.0421 # dtype: float64 print(TGARCH gamma p-value:, tgarch_result.pvalues[gamma[1]]) # 輸出示例0.0032 → 顯著小于 0.05若gamma[1] -0.0421且p0.0032則解釋為當(dāng)昨日收益率為負(fù)壞消息時(shí)其對(duì)今日波動(dòng)率的提升作用比同等幅度正收益高 4.21%注意TGARCH 中g(shù)amma是乘在ε2上的修正項(xiàng)非百分比但符號(hào)與方向明確。EGARCH 的gamma[1]解讀邏輯相同但因其公式中為γ·ε_(tái){t-1}/√h_{t-1}故γ0直接對(duì)應(yīng)負(fù)收益放大波動(dòng)。注意gamma不顯著p0.05時(shí)不應(yīng)強(qiáng)行保留 TGARCH/EGARCH應(yīng)回退到 GARCH(1,1)——模型復(fù)雜度增加必須有統(tǒng)計(jì)證據(jù)支撐。4. 模型診斷用殘差平方圖、QQ 圖與滾動(dòng)預(yù)測誤差三重驗(yàn)證4.1 檢查標(biāo)準(zhǔn)化殘差是否滿足 GARCH 假設(shè)GARCH 模型成立的前提是標(biāo)準(zhǔn)化殘差ε_(tái)t / √h_t應(yīng)近似 i.i.d. 標(biāo)準(zhǔn)正態(tài)分布。我們繪制其直方圖與 QQ 圖import matplotlib.pyplot as plt import scipy.stats as stats # 提取標(biāo)準(zhǔn)化殘差 std_resid garch_result.resid / np.sqrt(garch_result.conditional_volatility) # 直方圖 正態(tài)密度曲線 plt.figure(figsize(12, 4)) plt.subplot(1, 2, 1) plt.hist(std_resid, bins50, densityTrue, alpha0.7, labelStandardized Residuals) x np.linspace(-4, 4, 100) plt.plot(x, stats.norm.pdf(x), r-, lw2, labelN(0,1)) plt.legend() plt.title(Histogram of Standardized Residuals) # QQ 圖 plt.subplot(1, 2, 2) stats.probplot(std_resid, distnorm, plotplt) plt.title(Q-Q Plot of Standardized Residuals) plt.show()理想狀態(tài)直方圖貼合紅色正態(tài)曲線QQ 圖點(diǎn)基本落在虛線yx上。常見問題右上角點(diǎn)明顯高于虛線 → 正收益極端值過多厚右尾左下角點(diǎn)偏低 → 負(fù)收益沖擊被低估杠桿效應(yīng)未捕獲→ 此時(shí)應(yīng)切換至 EGARCH 或 t 分布。4.2 Ljung-Box 檢驗(yàn)標(biāo)準(zhǔn)化殘差平方確認(rèn) GARCH 充分建模若 GARCH 成功捕獲波動(dòng)率動(dòng)態(tài)則std_resid2應(yīng)無自相關(guān)lb_std acorr_ljungbox(std_resid**2, lags[5,10,15], return_dfTrue) print(lb_std) # 輸出示例 # lb_stat lb_pvalue # 5 3.21 0.668 # 10 7.89 0.639 # 15 12.05 0.674所有 p 值 0.05 → 接受“無自相關(guān)”原假設(shè) → GARCH(1,1) 充分建模波動(dòng)率聚類。若某滯后階數(shù) p 0.05如 lag5 時(shí) p0.012說明模型未能完全吸收短期波動(dòng)記憶可嘗試 GARCH(2,1) 或增加q。4.3 滾動(dòng)窗口預(yù)測用 250 日窗口預(yù)測未來 10 日波動(dòng)率真實(shí)業(yè)務(wù)中GARCH 價(jià)值在于滾動(dòng)預(yù)測。以下代碼實(shí)現(xiàn)250日窗口訓(xùn)練、預(yù)測10日后條件方差def rolling_garch_forecast(data, window250, horizon10): forecasts [] for i in range(window, len(data)): train_data data.iloc[i-window:i] try: model arch_model(train_data, volGARCH, p1, q1, meanZero, distnormal) res model.fit(dispoff) # 預(yù)測 horizon 步 ahead 的條件方差 pred res.forecast(horizonhorizon) forecasts.append(pred.variance.values[-1, -1]) # 取最后一步預(yù)測值 except: forecasts.append(np.nan) # 收斂失敗時(shí)填 NaN return np.array(forecasts) # 對(duì) resid 序列做滾動(dòng)預(yù)測 vol_forecast rolling_garch_forecast(resid, window250, horizon10) df[garch_vol_10d] np.concatenate([np.full(250, np.nan), vol_forecast])輸出列g(shù)arch_vol_10d即為每個(gè)交易日對(duì)未來 10 日年化波動(dòng)率的預(yù)測需開方后 × √250。實(shí)際部署時(shí)應(yīng)將horizon1預(yù)測明日波動(dòng)率作為風(fēng)控閾值觸發(fā)信號(hào)horizon10用于期權(quán)定價(jià)校準(zhǔn)。5. 進(jìn)階技巧用 GARCH 預(yù)測結(jié)果驅(qū)動(dòng) VaR 計(jì)算與壓力測試場景構(gòu)建5.1 基于 GARCH 條件波動(dòng)率的動(dòng)態(tài) VaRValue at RiskVaR 是風(fēng)控核心指標(biāo)。傳統(tǒng)歷史模擬法用固定 250 日窗口而 GARCH-VaR 利用時(shí)變波動(dòng)率更敏感from scipy.stats import norm # 假設(shè)置信水平 99%即 α0.01 alpha 0.01 z_score norm.ppf(alpha) # -2.326 # 提取 GARCH 模型每日預(yù)測的條件標(biāo)準(zhǔn)差已開方 cond_vol garch_result.conditional_volatility # 計(jì)算 GARCH-VaRVaR_t z_score × σ_t garch_var z_score * cond_vol # 對(duì)比歷史 VaR用滾動(dòng)250日標(biāo)準(zhǔn)差 hist_vol df[ret].rolling(250).std() hist_var z_score * hist_vol # 合并對(duì)比 df[garch_var_99] garch_var df[hist_var_99] hist_var # 繪制 VaR 序列僅展示最后 100 天 df.iloc[-100:][[garch_var_99, hist_var_99]].plot(figsize(10,4)) plt.title(GARCH-VaR vs Historical VaR (99% Confidence)) plt.ylabel(Daily VaR (Log Return)) plt.show()關(guān)鍵優(yōu)勢GARCH-VaR 在市場動(dòng)蕩期如2022年3月俄烏沖突會(huì)快速上抬而歷史 VaR 因窗口滯后約 20 日才反應(yīng)——這直接關(guān)系到保證金追繳時(shí)效。業(yè)務(wù)落地將garch_var_99作為自營賬戶單日虧損預(yù)警線超過閾值自動(dòng)觸發(fā)頭寸審查。5.2 構(gòu)建基于 TGARCH 的壓力測試場景壞消息沖擊放大器TGARCH 的gamma[1]可量化“壞消息敏感度”用于構(gòu)造壓力情景# 假設(shè)當(dāng)前條件方差 h_t 1e-4昨日收益 ε_(tái){t-1} -0.03-3% h_t 1e-4 eps_prev -0.03 # GARCH 預(yù)測 h_{t1}無杠桿 h_garch garch_result.params[omega] \ garch_result.params[alpha[1]] * eps_prev**2 \ garch_result.params[beta[1]] * h_t # TGARCH 預(yù)測 h_{t1}含杠桿γ0 gamma_est tgarch_result.params[gamma[1]] h_tgarch tgarch_result.params[omega] \ tgarch_result.params[alpha[1]] * eps_prev**2 \ gamma_est * (eps_prev**2) * (eps_prev 0) \ tgarch_result.params[beta[1]] * h_t print(fGARCH 預(yù)測波動(dòng)率: {np.sqrt(h_garch):.6f}) print(fTGARCH 預(yù)測波動(dòng)率: {np.sqrt(h_tgarch):.6f}) print(f杠桿放大比例: {(np.sqrt(h_tgarch)/np.sqrt(h_garch)-1)*100:.2f}%) # 輸出示例杠桿放大比例: 12.34%此計(jì)算表明同等 -3% 沖擊下TGARCH 預(yù)測的次日波動(dòng)率比 GARCH 高 12.34%。壓力測試應(yīng)用在組合壓力測試中對(duì)股票多頭頭寸施加×1.12波動(dòng)率乘數(shù)債券空頭施加×0.95因利率債對(duì)股市壞消息敏感度低形成非對(duì)稱沖擊方案。5.3 IGARCH 的隱含長期波動(dòng)率與均值回歸速度估算IGARCH 模型alpha beta 1常被用于刻畫市場長期記憶。雖arch庫不直接支持 IGARCH 約束估計(jì)但可通過alpha beta接近 1 的 GARCH 模型反推# 從 GARCH 結(jié)果提取 alpha, beta alpha_hat garch_result.params[alpha[1]] beta_hat garch_result.params[beta[1]] long_run_vol np.sqrt(garch_result.params[omega] / (1 - alpha_hat - beta_hat)) print(f長期波動(dòng)率估計(jì): {long_run_vol:.6f} (年化 ≈ {long_run_vol*np.sqrt(250):.4f})) print(f半衰期波動(dòng)率回歸一半所需天數(shù): {np.log(0.5)/np.log(alpha_hat beta_hat):.1f} 天) # 輸出示例半衰期: 84.2 天 → 意味著一次沖擊的影響約 3 個(gè)月后衰減一半半衰期公式T_{1/2} ln(0.5) / ln(αβ)是衡量波動(dòng)率“粘性”的核心指標(biāo)。風(fēng)控意義若半衰期 100 天說明市場情緒固化短期對(duì)沖策略效果遞減需轉(zhuǎn)向跨期套利或波動(dòng)率曲面交易。提示當(dāng)alpha_hat beta_hat ≥ 0.995時(shí)1 - alpha_hat - beta_hat極小long_run_vol計(jì)算不穩(wěn)定此時(shí)應(yīng)改用arch_model(..., volIGARCH)arch庫 5.0 版本支持或接受其作為近似邊界。本文還有配套的精品資源點(diǎn)擊獲取