SPB Git

spb/wp46_uqo

Public
8.4 KB

# Model card — garch_midas (GARCH-MIDAS, fixed-span, own monthly realized variance, K = 24) — post-registration extension

# 1. Identity

  • model_id: garch_midas · family: component · tier: A · status: extension (E-01, added 2026-11-09 after the protocol freeze; scored with the frozen protocol, reported separately as exploratory) · impl: custom (src/wp46/models/extensions.py::GARCHMIDAS)
  • Label: GARCH-MIDAS (own monthly RV, 24 months) · distributions: normal, t (registry dists; the class also accepts ged/skewt but those pairs are not scored) · information set: the instrument's own daily returns only (Tier A) — the former registry note "requires a low-frequency series outside the pre-registered information set" no longer applies because the long-run component is built from the window's own returns.
  • Seminal citation: engle2013stock
  • Other references: ghysels2006predicting, ghysels2007midas (MIDAS weighting), engle2008spline (Spline-GARCH, the other multiplicative low-frequency component), engle1999long (additive component GARCH, scored as cgarch11), andersen2003modeling (realized variance as the low-frequency regressor). This card replaces the former unsupported stub (same id).

# 2. Definition (as coded)

Day t belongs to calendar month $m(t)$ (from the dates in rolling.py: datetime64[M]; the unit tests use 21-day blocks when no calendar is supplied). $$r_t = \mu + \varepsilon_t,\quad \varepsilon_t = \sqrt{\tau_t g_t},z_t,\qquad g_t = (1 - \alpha - \beta) + \alpha,\frac{\varepsilon_{t-1}^2}{\tau_{t-1}} + \beta,g_{t-1},\qquad g_0 = 1,$$ $$\tau_t = m + \theta\sum_{k=1}^{K}\varphi_k(w),RV^{(m)}{m(t)-k},\qquad RV^{(m)}j = \sum{s:,m(s)=j}(r_s - \bar r)^2,\qquad \varphi_k(w) = \frac{(1 - k/K)^{w-1}}{\sum{j=1}^{K}(1 - j/K)^{w-1}},\quad K = 24,$$ i.e. the fixed-span (rolling-window) GARCH-MIDAS of engle2013stock with the own monthly realized variance as the low-frequency variable and the Beta-polynomial weights with $w_1 = 1$ fixed (one free weight parameter $w \equiv w_2$; $\varphi_K = 0$ exactly for w > 1, so 23 lags carry weight). $\tau_t$ is constant within a month and uses only the K completed months before $m(t)$; $\bar r$ is the sample mean of the window; $\tau$ is floored at 1e-10. Short histories at the start of the window (_tau): months with index $6 \le m < K$ use the available months with renormalised weights $(1 - k/K)^{w-1}$, k = 1..m; months $m < 6$ use $m + \theta\times$ (plain mean of the available monthly RVs, and for the first month its own RV). Innovations: standardised normal or Student-t.

# 3. Parameter space and admissibility

  • Parameters: mu, m, theta, w, alpha, beta (+ nu for t).
  • Reparameterisation: $m = e^{\theta_0} > 0$; $\theta = e^{\theta_1} > 0$; $w = 1 + e^{\theta_2} > 1$ (monotonically decreasing weights); persistence $s = \sigma(\theta_3)$ and share $\sigma(\theta_4)$ give $\alpha = s,\sigma(\theta_4)$, $\beta = s(1 - \sigma(\theta_4))$, so $\alpha, \beta \ge 0$, $\alpha + \beta < 1$ and $g$ has unit unconditional mean.
  • Admissibility flag: $m > 0$, $\theta \ge 0$, $w \ge 1$, $\alpha, \beta \ge 0$, $\alpha + \beta < 1$ — all by construction. $\tau_t > 0$ follows from $m > 0$, $\theta \ge 0$, $RV \ge 0$. engle2013stock leave the sign of θ free (needed for macro regressors); with a variance regressor θ ≥ 0 is the economically meaningful region and is imposed here.

# 4. Nesting and relations

  • θ → 0: $\tau_t = m$ and $\sigma_t^2 = m,g_t$ is GARCH(1,1) with $\omega = m(1-\alpha-\beta)$ — reached only in the limit ($\theta = e^{\theta_1}$), and w is then unidentified. The nesting test allows a 2.0 log-likelihood slack (§7).
  • cgarch11 (Engle–Lee) is the additive two-component analogue with a daily-updated long-run component; engle2008spline the deterministic-spline analogue; histvar252/rm2006 are parameter-free long-memory proxies.
  • Relation to Tier B: the long-run regressor is the sum of squared daily returns, not an intraday realized measure, so the model stays in Tier A.

# 5. Estimation

Shared custom MLE (CustomModel.fit; GARCHMIDAS.fit first builds the day→month map and the monthly RV series from the window): L-BFGS-B (maxiter 2000, ftol 1e-10, gtol 1e-6) from up to three starts (m, θ, w, α, β) ∈ {(0.5v, 0.5, 3, 0.06, 0.90), (0.8v, 0.2, 5, 0.04, 0.93), (0.3v, 0.8, 2, 0.08, 0.85)}, v = sample variance of the demeaned window; μ start = sample mean; ν start 6; stop after the second start if converged; Nelder–Mead polish (maxiter 4000) + final L-BFGS-B if not converged or stalled; A-05 floor vs GARCH(1,1) with the same law (−50 units → two perturbed restarts → degenerate flag). The backcast $s_0$ is computed but not used by the recursion ($g_0 = 1$, $\tau_0$ from the first month's own RV). fit.aux["months"] stores the calendar so that filter/forecast rebuild the same monthly RVs. Point estimates only.

# 6. Forecasting

GARCHMIDAS.step_forecast (method analytic), with $\tau$ frozen at the last in-sample value $\tau_t$ (the next month's $\tau$ would require the current month's completed RV): $$\hat g_{t+1|t} = (1-\alpha-\beta) + \alpha,\varepsilon_t^2/\tau_t + \beta g_t,\qquad \hat g_{t+k|t} = (1-\alpha-\beta) + (\alpha+\beta),\hat g_{t+k-1|t},\qquad \hat\sigma^2_{t+k|t} = \tau_t,\hat g_{t+k|t}.$$ Exact under $E z^2 = 1$ for the short-run component; the frozen $\tau$ is an approximation whenever the 22-day horizon crosses a month end. Cumulative h-day variance = sum of the first h steps.

# 7. Implementation and verification

  • src/wp46/models/extensions.py::GARCHMIDAS, numba rec_garch_midas, pure-numpy _tau/_month_rv; rolling.py passes months = calendar months of the window dates (special-cased on job.model_id == "garch_midas").
  • Tests (tests/unit/test_extensions.py::test_garch_midas_nests_garch_with_calendar_months): fit (normal) on the GARCH-t fixture with 21-day months converges with log-likelihood ≥ GARCH11 custom − 2.0; 22-step forecast positive and finite. Not covered by test_no_lookahead_extensions.
  • No external-package cross-check (no GARCH-MIDAS in arch 8.0.0 — arch's MIDASHyperbolic is a MIDAS-weighted ARCH on daily squared returns — nor in rugarch 1.5-6; the R package mfGARCH is not part of the version-locked toolchain and was not run), no simulation-recovery test, no likelihood identity test. The only external identity in the extension set is HYGARCH(amp = 1) vs arch's FIGARCH (hygarch11.md §7). CLAUDE.md rule 6 is not met in full — hence extension status.

# 8. Known limitations / failure modes

Post-registration, exploratory. A 1,000-day window holds ≈ 47 calendar months, so with K = 24 the first half of every window uses the shortened-history rules of §2 (renormalised weights for months 6–23; plain means before; the first month uses its own, contemporaneous RV — an in-sample initialisation artefact confined to the first month, with no effect on the forecasts, which are issued ≥ 47 months into the window). $g_t$ divides by $\tau_{t-1}$ rather than $\tau_t$, which differs from engle2013stock only on the first trading day of each month. Monthly RV uses demeaned returns (the paper uses raw squared returns). θ and w are weakly identified when the long-run component is flat (θ small); w is unidentified at θ = 0; $\tau$ frozen over the horizon; no data-driven choice of K (fixed at 24 months). Rolling windows of unequal month counts (holidays, missing days) are handled through the calendar map, not by trading-day counts.

# 9. Computational footprint

O(T) GARCH recursion plus an O(n_months × K) weight convolution per likelihood evaluation — comparable to cgarch11, i.e. a small multiple of garch11_custom; analytic forecasts are O(22). Far below the fractional extensions. Not timed in the pilot.

# 10. Literature expectations

engle2013stock find that a realized-variance MIDAS component already captures most of the long-run movement and that macro components add at long horizons; ghysels2006predicting show the value of mixed-frequency variance regressors; engle1999long/engle2008spline document gains of two-component models mainly at long horizons. Under H4 (persistence structure) the expectation is no gain at h = 1 and a possible gain at h = 22 relative to garch11, comparable to cgarch11; under H6 the frozen long-run component should hurt in stressed regimes when the level shifts within the month.

Files · main
Menu

Theme