SPB Git

spb/wp46_uqo

Public
7.0 KB

# Model card — garch11 (GARCH(1,1), the benchmark)

# 1. Identity

  • model_id: garch11 · family: classical · tier: A · status: implemented · benchmark: true · impl: arch 8.0.0 (GARCH(p=1, o=0, q=1))
  • Label: GARCH(1,1) · distributions: normal, t, ged, skewt
  • Seminal citation: bollerslev1986generalized
  • Other references: engle1982autoregressive (ARCH); nelson1990stationarity (strict stationarity); bollerslev1992quasi, lee1994asymptotic, lumsdaine1996consistency (QMLE theory); hansen2005forecast ("does anything beat a GARCH(1,1)?"); engle2001garch, bollerslev2010glossary (nomenclature); distributions bollerslev1987conditionally, nelson1991conditional, hansen1994autoregressive.

# 2. Definition

$$r_t = \mu + \varepsilon_t,\quad \varepsilon_t = \sigma_t z_t,\qquad \sigma_t^2 = \omega + \alpha,\varepsilon_{t-1}^2 + \beta,\sigma_{t-1}^2 ,$$ with $\sigma_0^2$ initialised as $\omega + (\alpha+\beta)\cdot\text{backcast}$ (arch garch_recursion: both pre-sample terms use the backcast). Innovations $z_t$ i.i.d. with unit variance: normal; Student-t(ν), ν > 2; GED(ν); Hansen skew-t(η, λ). Order convention: arch's p = ARCH order, q = GARCH order (Bollerslev's (p,q) is the reverse; irrelevant for (1,1)).

# 3. Parameter space and admissibility

  • Parameters: mu, omega, alpha[1], beta[1] (+ nu or eta, lambda).
  • arch bounds: $\omega \in [10^{-8}v, 10v]$ ($v = \overline{\varepsilon^2}$), $\alpha, \beta \in [0, 1]$; linear constraints $\omega > 0$, $\alpha \ge 0$, $\beta \ge 0$, $\alpha + \beta < 1$ (SLSQP inequality constraints; no reparameterisation). Distribution bounds: ν ∈ [2.05, 500] (t), ν ∈ [1.01, 500] (GED), η ∈ [2.05, 300], λ ∈ [−1, 1].
  • Admissibility flag: $\alpha + \beta < 1$ (covariance stationarity, unconditional variance $\omega/(1-\alpha-\beta)$). The strict-stationarity condition $E\log(\alpha z^2 + \beta) < 0$ (nelson1990stationarity) is weaker and not used as the flag.
  • (The custom cross-check class garch11_custom in src/wp46/models/custom.py uses the reparameterisation $\omega = e^{\theta_0}$, $s = \alpha+\beta = \sigma(\theta_1)$, $\alpha = s,\sigma(\theta_2)$; it is not the registry implementation.)

# 4. Nesting and relations

Nests constvar (α = β = 0) and ARCH(1) (β = 0). Nested in garch21, garch12, gjr11 (γ = 0), nagarch11 (θ = 0), qgarch11 (γ = 0), aparch11 (δ = 2, γ = 0), avgarch11/tarch11 only through the power change (δ = 1 vs 2, not nested), cgarch11 (φ = 0, ρ = 0 collapse), figarch11 (d = 0), garchx_rv11 (γ = 0), msgarch2 (identical regimes), and is the ν → ∞ limit of gas_t11 up to reparameterisation. igarch11 is the boundary α + β = 1; ewma094 additionally sets ω = 0.

# 5. Estimation

arch ConstantMean + GARCH(1,0,1) + distribution; fit(disp="off", options={"maxiter": 1000}) → SLSQP on the exact log-likelihood $\sum_t[\log f_z(\varepsilon_t/\sigma_t) - \tfrac12\log\sigma_t^2]$ with bounds/constraints of §3 (src/wp46/models/arch_models.py::ArchModel.fit). Starting values: arch grid α ∈ {0.01, 0.05, 0.1, 0.2} × persistence ∈ {0.5, 0.7, 0.9, 0.98}, $\omega = (1-\text{pers}),\overline{\varepsilon^2}$, best Gaussian log-likelihood; distribution start ν from arch. Initial variance: arch backcast (exponentially weighted mean of the first min(75, T) squared residuals, weights ∝ 0.94ⁱ). Retries: ≤ 2 restarts (previous estimate × (0.9 + 0.2(i+1)/3), maxiter 2000) if convergence_flag ≠ 0; the better of the fits is kept. arch warns (DataScaleWarning) but does not rescale when var(ε) ∉ [0.1, 10 000) (percent units keep equities/FX inside the range; very low-volatility instruments may warn). Standard errors: arch's robust covariance is computed by arch but only point estimates are used in the rolling benchmark (rolling.py: refit every 5 days, daily filtering with am.fix(params)).

# 6. Forecasting

arch GARCH._analytic_forecast: $$\hat\sigma^2_{t+1|t} = \omega + \alpha\varepsilon_t^2 + \beta\sigma_t^2,\qquad \hat\sigma^2_{t+k|t} = \omega + (\alpha + \beta),\hat\sigma^2_{t+k-1|t},\ k = 2..22,$$ exact under $E[z^2] = 1$ for every supported innovation law. Cumulative $h$-day variance $=\sum_{k\le h}\hat\sigma^2_{t+k|t}$. Method: analytic. The custom class reproduces arch's 22-step forecasts to relative 1e-10 (test_custom_garch_equals_arch_loglik_and_forecast).

# 7. Implementation

  • src/wp46/models/arch_models.py (SPECS["garch11"]), arch 8.0.0 (sheppard2025arch).
  • Cross-check (results/metrics/rugarch_crosscheck.json, rugarch 1.5-6, fixture tests/replication/fixture_returns.csv: T = 3,000 GJR-t data): garch11_t log-likelihood −3379.4618 (ours) vs −3379.5028 (rugarch), difference +0.0410; parameters agree (α 0.07667 vs 0.07664, β 0.89790 vs 0.89793, ν 6.916 vs 6.923). garch11_skewt: −3379.2756 vs −3379.3148, +0.0392 — note rugarch sstd is Fernández–Steel skewing while arch is Hansen's skew-t (fernandez1998bayesian vs hansen1994autoregressive): the two likelihoods are not the same density, only the orders of magnitude are compared.
  • Tests: tests/replication/test_rugarch.py::test_rugarch_crosscheck (asserts |Δℓ| < 0.5 and |Δα|, |Δβ| < 5e-3); tests/unit/test_custom_models.py::test_custom_garch_equals_arch_loglik_and_forecast (recursion identical to arch's compute_variance to 1e-9, forecasts to 1e-10); tests/integration/test_rolling_driver.py::test_driver_refit_cadence_and_outputs (driver with garch11, normal); tests/unit/test_distributions.py (densities equal arch's to 1e-12).

# 8. Known limitations / failure modes

Near-integrated estimates ($\alpha + \beta \to 1$) on long windows or after breaks (lamoureux1990persistence, hillebrand2005neglecting) produce boundary optima and the flag admissible = False when SLSQP ends with $\alpha + \beta \ge 1$ (constraint is strict only up to solver tolerance); in the pilot, garch11__t on SPY had 26/202 refits flagged inadmissible in an earlier version of pilot_report.json (the current file holds CL and EURUSD: 207/207 ok). ω is poorly identified when persistence is high (small ω, large unconditional variance). Symmetric response to news (no leverage) — the main mis-specification for equities.

# 9. Computational footprint

Analytic recursion and forecasts; 4–6 parameters. Pilot fit time per refit (results/metrics/pilot/pilot_report.json, laptop, 1,000-obs window, median s): normal 0.0042 (CL) / 0.0049 (EURUSD); t 0.0065 / 0.0074. The cheapest estimated dynamic model of the registry.

# 10. Literature expectations

hansen2005forecast: nothing beats GARCH(1,1) on DM/$ (FX), while leverage models do on IBM (equities). awartani2005predicting, brownlees2011practical: asymmetric models beat GARCH(1,1) on equity indices, more so in crises. marcucci2005forecasting: regime models win at short horizons only. The literature matrix (§G) frames GARCH(1,1) as the benchmark that the MCS/SPA machinery tests against; the pre-registered hypotheses H1–H6 (docs/preregistered_protocol.md) are all stated relative to this model.

Files · main
Menu

Theme