Realized GARCH — the bridge between GARCH and realized volatility¶
Phase 3: Hansen, Huang & Shek (2012)¶
The arc has run two separate tracks: GARCH/SV infer a latent variance $h_t$ from daily returns, while HAR models the observed realized variance $RV_t$ directly. Realized GARCH joins them. It keeps GARCH's latent $h_t$ but (i) lets the informative $RV$ drive the variance recursion instead of the noisy squared return, and (ii) adds a measurement equation tying the observed $RV_t$ to the latent $h_t$:
$$r_t=\sqrt{h_t}\,z_t,\qquad \log h_t=\omega+\beta\log h_{t-1}+\gamma\log RV_{t-1},\qquad \log RV_t=\xi+\varphi\log h_t+\underbrace{\tau_1 z_t+\tau_2(z_t^2-1)}_{\text{leverage}}+u_t.$$
Parameters are estimated by joint maximum likelihood of returns and realized measures (realgarch.py); the effective persistence is $\beta+\varphi\gamma$. Data: spx_rv_ret.csv (S&P 500 returns + 5-min RV, 2000–2013).
import numpy as np, pandas as pd, matplotlib.pyplot as plt
import realgarch as RG, garch_scratch as G
df = pd.read_csv("spx_rv_ret.csv", parse_dates=["date"])
r = df["ret"].values; RV = df["rv"].values * 1e4; dates = df["date"] # returns %, RV %^2
th, logh0 = RG.mle(r, RV); p = RG.params_readable(th) # joint ML fit
print("Realized GARCH: omega %.3f beta %.3f gamma %.3f phi %.3f tau1 %.3f tau2 %.3f sigma_u %.3f"
% (p["omega"], p["beta"], p["gamma"], p["phi"], p["tau1"], p["tau2"], p["sigma_u"]))
print(" effective persistence (beta + phi*gamma) = %.3f" % p["persistence"])
h_rg = np.exp(RG.filter_logh(th, r, np.log(RV), logh0)) # RealGARCH latent variance
thg, _, _ = G.garch_mle(r, student=True); r2, s0 = G.prepare(r); neg = (r < 0).astype(float)
h_g = G.garch_var(thg, r2, s0, neg, False) # standard GARCH-t variance
print(" corr with RV: RealGARCH %.3f standard GARCH-t %.3f" % (np.corrcoef(h_rg, RV)[0,1], np.corrcoef(h_g, RV)[0,1]))
fig, ax = plt.subplots(1, 2, figsize=(13, 4.6))
w = (dates >= "2007-06-01") & (dates <= "2010-06-01")
ax[0].plot(dates[w], np.sqrt(252 * RV[w]), color="0.7", lw=.8, label="realized vol $\\sqrt{RV}$")
ax[0].plot(dates[w], np.sqrt(252 * h_rg[w]), color="firebrick", lw=1.5, label="Realized GARCH $\\sqrt{h}$")
ax[0].plot(dates[w], np.sqrt(252 * h_g[w]), color="seagreen", lw=1.3, label="standard GARCH-t $\\sqrt{h}$")
ax[0].set_ylabel("annualized vol (%)"); ax[0].legend(fontsize=8)
ax[0].set_title("Realized GARCH's variance tracks RV\n(RV drives the recursion; standard GARCH lags)")
for lab in ax[0].get_xticklabels(): lab.set_rotation(20)
z = np.linspace(-3, 3, 200); tau = p["tau1"] * z + p["tau2"] * (z ** 2 - 1)
ax[1].plot(z, tau, color="slateblue", lw=2)
ax[1].axvline(0, color="0.6", lw=.8); ax[1].axhline(0, color="0.6", lw=.8)
ax[1].fill_between(z, tau, where=(z < 0), color="firebrick", alpha=.12)
ax[1].set_xlabel("return shock $z_t = r_t/\\sqrt{h_t}$"); ax[1].set_ylabel("leverage effect on $\\log RV_t$")
ax[1].set_title("Measurement-equation leverage $\\tau(z)$\n(a down move $z<0$ lifts realized volatility more)")
plt.tight_layout(); plt.show()
Realized GARCH: omega 0.127 beta 0.654 gamma 0.330 phi 0.975 tau1 -0.076 tau2 0.132 sigma_u 0.524 effective persistence (beta + phi*gamma) = 0.976 corr with RV: RealGARCH 0.753 standard GARCH-t 0.711
Reading the figure¶
- Left — it tracks RV. Because $RV_{t-1}$ (not $r_{t-1}^2$) drives the recursion, Realized GARCH's $\sqrt{h_t}$ follows realized volatility closely and reacts fast; standard GARCH-$t$, updating from squared returns, is smoother and lags — most visibly in early 2009, where it stays elevated while realized vol (and Realized GARCH) has already come down. Realized GARCH correlates 0.75 with RV versus 0.71 for standard GARCH.
- Right — leverage lives in the measurement equation. $\tau(z)=\tau_1 z+\tau_2(z^2-1)$ maps a return shock to contemporaneous log-RV. With $\tau_1<0$ the curve tilts so a down move ($z<0$) lifts realized volatility more than an up move of the same size — the leverage effect, recovered from the joint return-and-RV likelihood.
Results¶
- Realized GARCH is GARCH that "sees" realized volatility. The RV loading $\gamma=0.33$ pulls the precise realized measure into the variance recursion; the measurement slope $\varphi=0.98$ says RV is nearly proportional to the latent $h$; $\tau_1<0$ carries the leverage; and the effective persistence $\beta+\varphi\gamma=0.98$ reproduces the near-integrated volatility seen throughout the arc.
- This is the formal bridge between the GARCH/SV track and the HAR/realized track — and it sets up the forecasting tournament (next notebook): do the models that use realized measures (HAR, Realized GARCH) actually out-forecast the ones that use only returns (GARCH, SV)?
Reference¶
- Hansen, P. R., Huang, Z. & Shek, H. H. (2012). Realized GARCH: a joint model for returns and realized measures of volatility. J. Applied Econometrics 27, 877–906.
Next: rv_forecast_horserace.ipynb — HAR vs GARCH vs SV vs Realized GARCH, forecasting RV out of sample.