WP46: reporting (plot style, figures, tables), paper skeleton, build_paper, tier C analysis, data manifests
40 changed files +9,391 −0
added
model_cards/aparch11.md
+39 −0
@@ -0,0 +1,39 @@ | |||||
| 1 | +# Model card — `aparch11` (APARCH(1,1), asymmetric power ARCH) | ||||
| 2 | + | ||||
| 3 | +## 1. Identity | ||||
| 4 | +- **model_id:** `aparch11` · **family:** power · **tier:** A · **status:** implemented · **impl:** arch 8.0.0 (`APARCH(p=1, o=1, q=1)`, δ estimated) | ||||
| 5 | +- **Label:** APARCH(1,1) · **distributions:** normal, t, ged, skewt | ||||
| 6 | +- **Seminal citation:** `ding1993long` | ||||
| 7 | +- **Other references:** `ling2002necessary` (moment conditions), `he1999properties`, `giot2003value` (skewed-t APARCH for VaR), `brownlees2011practical`, `hansen2005forecast`. | ||||
| 8 | + | ||||
| 9 | +## 2. Definition (arch parameterisation) | ||||
| 10 | +$$r_t = \mu + \varepsilon_t,\ \varepsilon_t = \sigma_t z_t,\qquad \sigma_t^{\delta} = \omega + \alpha\big(|\varepsilon_{t-1}| - \gamma\,\varepsilon_{t-1}\big)^{\delta} + \beta\,\sigma_{t-1}^{\delta} ,$$ | ||||
| 11 | +`aparch_recursion`: pre-sample shock $= \sqrt{\text{backcast}}$ (variance backcast) and $\sigma_0^\delta$ term $= \text{backcast}^{\delta/2}$; $\sigma_t^2 = (\sigma_t^\delta)^{2/\delta}$, clamped to arch's variance bounds. Innovations: normal, t, GED, Hansen skew-t. | ||||
| 12 | + | ||||
| 13 | +## 3. Parameter space and admissibility | ||||
| 14 | +- Parameters: `mu, omega, alpha[1], gamma[1], beta[1], delta` (+ distribution). | ||||
| 15 | +- arch bounds: $\omega \in [0, 10v]$ with $v = \max(\overline{|\varepsilon|^{0.5}}, \overline{\varepsilon^2})$, $\alpha \in [0,1]$, $\gamma \in [-0.9997, 0.9997]$, $\beta \in [0,1]$, $\delta \in [0.05, 4]$; linear constraints $\omega, \alpha \ge 0$, $|\gamma| < 0.9997$, $\beta \ge 0$, $0.05 < \delta < 4$, $\alpha + \beta < 1$ (arch's generic persistence constraint, **not** the Ding–Granger–Engle stationarity condition $\alpha E[(|z| - \gamma z)^\delta] + \beta < 1$, `ling2002necessary`). | ||||
| 16 | +- Admissibility flag: **always `True`** (no model-specific check in `ArchModel.fit`). | ||||
| 17 | + | ||||
| 18 | +## 4. Nesting and relations | ||||
| 19 | +Nests `garch11` (δ = 2, γ = 0), `gjr11` (δ = 2; with $\alpha_{GJR} = \alpha(1-\gamma)^2$, $\gamma_{GJR} = \alpha[(1+\gamma)^2 - (1-\gamma)^2]$), `avgarch11` (δ = 1, γ = 0), `tarch11` (δ = 1), Higgins–Bera NARCH (γ = 0, free δ). Literature-matrix caveat: "multi-step forecast of h not closed-form when δ ≠ 2". | ||||
| 20 | + | ||||
| 21 | +## 5. Estimation | ||||
| 22 | +arch `ConstantMean` + `APARCH(1,1,1)` + distribution; SLSQP (`maxiter` 1000) with the bounds/constraints of §3; starting values from arch's grid α ∈ {0.03, 0.05, 0.08, 0.15} × γ ∈ {−0.5, 0, 0.5} × (α+β) ∈ {0.8, 0.9, 0.95, 0.975, 0.99} × δ ∈ {0.5, 1.2, 1.8}, best Gaussian log-likelihood; variance backcast (0.94ⁱ weights on ε²); ≤ 2 restarts (`ArchModel.fit`). Point estimates only. | ||||
| 23 | + | ||||
| 24 | +## 6. Forecasting | ||||
| 25 | +h = 1 analytic (recursion, then $(\cdot)^{2/\delta}$). **h > 1 by simulation** (arch raises for analytic APARCH multi-step): 2,000 paths of $\sigma^\delta_{t+k}$ via `APARCH._simulate_paths` (shock $= z\,\sigma$, $(|{\rm shock}| - \gamma\,{\rm shock})^\delta$ feeds the next step), $\hat\sigma^2_{t+k|t}$ = path mean of $(\sigma^\delta_{t+k})^{2/\delta}$. Normal: seeded (46 + origin); t/GED/skew-t: arch's unseeded fitted-distribution simulator (`_discrepancies.md`). Cumulative = sum over k ≤ h. Method: `simulation` (h > 1). | ||||
| 26 | + | ||||
| 27 | +## 7. Implementation | ||||
| 28 | +- `src/wp46/models/arch_models.py` (`SPECS["aparch11"]`), arch 8.0.0 (`sheppard2025arch`). | ||||
| 29 | +- Cross-check (`results/metrics/rugarch_crosscheck.json`, rugarch `apARCH`, t): −3372.7593 (ours) vs −3372.8489 (rugarch), **difference +0.0896** (ours higher; δ = 1.81, γ = 0.232, ν = 7.02 on GJR-t data). | ||||
| 30 | +- Tests: `tests/replication/test_rugarch.py` (fit recorded in the JSON); pilot `aparch11__t`: 207/207 refits `ok`, 1,032/1,032 forecasts `ok` on CL. | ||||
| 31 | + | ||||
| 32 | +## 8. Known limitations / failure modes | ||||
| 33 | +δ and γ are jointly weakly identified (flat likelihood ridges; δ can run to the bounds 0.05/4 or the persistence constraint binds); γ bound ±0.9997; simulation forecasts with Monte-Carlo error, unseeded for non-normal laws; no admissibility flag beyond optimizer constraints; stationarity under the estimated (γ, δ) is not verified. | ||||
| 34 | + | ||||
| 35 | +## 9. Computational footprint | ||||
| 36 | +Most expensive arch-backed estimation (6–8 parameters, 180 grid starting values evaluated before SLSQP): pilot median fit time per refit (t) 0.0321 s (CL) / 0.0406 s (EURUSD), max 0.07 s; forecasts by simulation (22 × 2,000 draws per origin). | ||||
| 37 | + | ||||
| 38 | +## 10. Literature expectations | ||||
| 39 | +`ding1993long` found δ ≈ 1.4 on S&P 500 with strong asymmetry; `hansen2005forecast` report APARCH among the best on IBM; `giot2003value` favour skewed-t APARCH for VaR; `brownlees2011practical` include APARCH among the top asymmetric models. Expectation: competitive with GJR/EGARCH at h = 1 on equities (H1) at the highest estimation and forecasting cost of Tier A (H5), with the largest failure/boundary rate. | ||||
added
model_cards/avgarch11.md
+39 −0
@@ -0,0 +1,39 @@ | |||||
| 1 | +# Model card — `avgarch11` (AVGARCH(1,1), Taylor–Schwert absolute-value GARCH) | ||||
| 2 | + | ||||
| 3 | +## 1. Identity | ||||
| 4 | +- **model_id:** `avgarch11` · **family:** power · **tier:** A · **status:** implemented · **impl:** arch 8.0.0 (`GARCH(p=1, o=0, q=1, power=1.0)`, arch name "AVGARCH") | ||||
| 5 | +- **Label:** AVGARCH(1,1) (Taylor-Schwert) · **distributions:** normal, t, ged, skewt | ||||
| 6 | +- **Seminal citation:** `taylor2008modelling` (2nd ed. of Taylor 1986; the 1986 first edition has no verified record — see `docs/literature_matrix.md`, Unverified) and `schwert1989why`. | ||||
| 7 | +- **Other references:** `ding1993long` (APARCH nests it, δ = 1, γ = 0), `zakoian1994threshold`. | ||||
| 8 | + | ||||
| 9 | +## 2. Definition (arch, power = 1) | ||||
| 10 | +$$r_t = \mu + \varepsilon_t,\ \varepsilon_t = \sigma_t z_t,\qquad \sigma_t = \omega + \alpha\,|\varepsilon_{t-1}| + \beta\,\sigma_{t-1} ,$$ | ||||
| 11 | +pre-sample $|\varepsilon|$ and $\sigma$ replaced by the power-1 backcast ($\sum_{i<75} w_i|\varepsilon_i|$, $w_i \propto 0.94^i$). Innovations: normal, t, GED, Hansen skew-t. | ||||
| 12 | + | ||||
| 13 | +## 3. Parameter space and admissibility | ||||
| 14 | +- Parameters: `mu, omega, alpha[1], beta[1]` (+ distribution). | ||||
| 15 | +- arch bounds/constraints: $\omega \in [10^{-8}v_1, 10v_1]$ ($v_1 = \overline{|\varepsilon|}$), $\alpha, \beta \in [0,1]$, $\omega > 0$, $\alpha, \beta \ge 0$, $\alpha + \beta < 1$ (arch's generic constraint; the stationarity of $\sigma_t$ requires $\alpha E|z| + \beta < 1$, which is implied). | ||||
| 16 | +- Admissibility flag: **always `True`** (no check in `ArchModel.fit` for `avgarch11`). | ||||
| 17 | + | ||||
| 18 | +## 4. Nesting and relations | ||||
| 19 | +`aparch11` with δ = 1, γ = 0; `tarch11` with γ = 0. Not nested in `garch11` (power 1 vs 2). Symmetric; the only symmetric power-1 model of the registry. | ||||
| 20 | + | ||||
| 21 | +## 5. Estimation | ||||
| 22 | +arch SLSQP (`maxiter` 1000), grid starting values, power-1 backcast, ≤ 2 restarts (`ArchModel.fit`). Point estimates only. | ||||
| 23 | + | ||||
| 24 | +## 6. Forecasting | ||||
| 25 | +h = 1 analytic ($\hat\sigma_{t+1|t}^2 = (\omega + \alpha|\varepsilon_t| + \beta\sigma_t)^2$); h > 1 by **simulation** (2,000 paths of $\sigma_{t+k}$ via `GARCH._simulate_paths`, power 1; variance forecast = path mean of $\sigma_{t+k}^2$; note $E[\sigma_{t+k}^2] \ne (E\sigma_{t+k})^2$, which is why no analytic rule is used). Normal: seeded (46 + origin); t/GED/skew-t: arch's unseeded distribution simulator (`_discrepancies.md`). Cumulative = sum over k ≤ h. Method: `simulation` for h > 1. | ||||
| 26 | + | ||||
| 27 | +## 7. Implementation | ||||
| 28 | +- `src/wp46/models/arch_models.py` (`SPECS["avgarch11"]`), arch 8.0.0. | ||||
| 29 | +- Cross-check: none (not in the rugarch fixture script; rugarch `fGARCH(AVGARCH)` was not run). | ||||
| 30 | +- Tests: none dedicated. | ||||
| 31 | + | ||||
| 32 | +## 8. Known limitations / failure modes | ||||
| 33 | +No admissibility flag beyond optimizer constraints; simulation forecasts (Monte-Carlo error, unseeded for non-normal laws); boundary optima as for GARCH(1,1). | ||||
| 34 | + | ||||
| 35 | +## 9. Computational footprint | ||||
| 36 | +Estimation like `garch11`; simulation forecasts (22 × 2,000 draws per origin). No pilot timing. | ||||
| 37 | + | ||||
| 38 | +## 10. Literature expectations | ||||
| 39 | +`taylor2008modelling`/`schwert1989why` introduced absolute-value dynamics as more robust to outliers; `ding1993long` found δ ≈ 1.4 for S&P 500 (between AVGARCH and GARCH); `hansen2005forecast` include TS-GARCH variants without finding them superior to GARCH(1,1). Expectation: similar to GARCH(1,1), possibly more robust in stressed regimes (H6), at a higher forecasting cost (H5). | ||||
added
model_cards/egarch11.md
+39 −0
@@ -0,0 +1,39 @@ | |||||
| 1 | +# Model card — `egarch11` (EGARCH(1,1)) | ||||
| 2 | + | ||||
| 3 | +## 1. Identity | ||||
| 4 | +- **model_id:** `egarch11` · **family:** asymmetric · **tier:** A · **status:** implemented · **impl:** arch 8.0.0 (`EGARCH(p=1, o=1, q=1)`) | ||||
| 5 | +- **Label:** EGARCH(1,1) · **distributions:** normal, t, ged, skewt | ||||
| 6 | +- **Seminal citation:** `nelson1991conditional` | ||||
| 7 | +- **Other references:** `straumann2006quasi` (EGARCH QMLE theory), `harvey2013dynamic`/`harvey2014egarch` (Beta-t-EGARCH, score-driven relative), `hansen2005forecast`, `brownlees2011practical`. | ||||
| 8 | + | ||||
| 9 | +## 2. Definition (arch parameterisation) | ||||
| 10 | +$$r_t = \mu + \varepsilon_t,\ \varepsilon_t = \sigma_t z_t,\ e_t = \varepsilon_t/\sigma_t,\qquad \ln\sigma_t^2 = \omega + \alpha\big(|e_{t-1}| - \sqrt{2/\pi}\big) + \gamma\,e_{t-1} + \beta\,\ln\sigma_{t-1}^2 .$$ | ||||
| 11 | +Here **arch's `alpha[1]` multiplies the magnitude term and `gamma[1]` the sign term** (Nelson writes $g(z) = \theta z + \gamma(|z| - E|z|)$; rugarch writes α on the sign and γ on the magnitude — the cross-check confirms the swap: our α = 0.1565 ↔ rugarch γ₁ = 0.1565, our γ = −0.0444 ↔ rugarch α₁ = −0.0444). The centring constant is $\sqrt{2/\pi} = E|z|$ for the normal only; for t/GED/skew-t $E|z| \ne \sqrt{2/\pi}$ and the difference $\alpha(E|z| - \sqrt{2/\pi})$ is absorbed by ω (observationally equivalent, but ω is not Nelson's ω). Pre-sample: $\ln\sigma_0^2 = \omega + \beta\cdot\ln(\text{backcast})$ (the α, γ terms are omitted at t = 0). $\ln\sigma_t^2$ is capped at `LNSIGMA_MAX` and $\sigma_t^2$ clamped to arch's variance bounds. Innovations: normal, t, GED, Hansen skew-t. | ||||
| 12 | + | ||||
| 13 | +## 3. Parameter space and admissibility | ||||
| 14 | +- Parameters: `mu, omega, alpha[1], gamma[1], beta[1]` (+ distribution). | ||||
| 15 | +- arch bounds: $\omega \in [\ln v - \ln 10^4, \ln v + \ln 10^4]$ ($v = \overline{\varepsilon^2}$), $\alpha, \gamma \in (-\infty, \infty)$, $\beta \in [0, 1]$; constraint $\beta < 1$. arch therefore excludes $\beta < 0$ (Nelson's condition is $|\beta| < 1$). | ||||
| 16 | +- Admissibility flag (`ArchModel.fit`): $|\beta| < 1$ (log-variance stationarity). No positivity constraints are needed (log specification). Note the literature matrix caveat: stationarity is $|\beta| < 1$, not $\alpha + \beta < 1$. | ||||
| 17 | + | ||||
| 18 | +## 4. Nesting and relations | ||||
| 19 | +Does not nest `garch11` (log vs level). γ = 0 gives a symmetric log-GARCH; the Beta-t-EGARCH of Harvey is the score-driven counterpart (not in the registry; `gas_t11` is the variance-level GAS). Exponential form of the asymmetry shared with `realegarch11` (unsupported). | ||||
| 20 | + | ||||
| 21 | +## 5. Estimation | ||||
| 22 | +arch `ConstantMean` + `EGARCH(1,1,1)` + distribution; SLSQP (`maxiter` 1000) with the bounds of §3; starting values from arch's grid (α ∈ {0.01, 0.05, 0.1, 0.2}, γ ∈ {−0.1, 0, 0.1}, β ∈ {0.5, 0.7, 0.9, 0.98}, ω = (1−β)·ln v̄; best Gaussian log-likelihood); backcast = log of the exponentially weighted mean of the first min(75, T) squared residuals; ≤ 2 restarts (`ArchModel.fit`). Point estimates only; daily filtering with `am.fix(params)`. | ||||
| 23 | + | ||||
| 24 | +## 6. Forecasting | ||||
| 25 | +h = 1: analytic, $\hat\sigma^2_{t+1|t} = \exp(\omega + \alpha(|e_t| - \sqrt{2/\pi}) + \gamma e_t + \beta\ln\sigma_t^2)$. **h > 1: simulation** (`SPECS["egarch11"]["analytic"] = False`; arch has no analytic EGARCH multi-step): 2,000 paths, $\ln\sigma^2_{t+k} = \omega + \alpha(|z_{t+k-1}| - \sqrt{2/\pi}) + \gamma z_{t+k-1} + \beta\ln\sigma^2_{t+k-1}$ with simulated standardised shocks, $\hat\sigma^2_{t+k|t}$ = path mean of $\exp(\ln\sigma^2_{t+k})$. Normal: seeded `default_rng(46 + origin).standard_normal`; t/GED/skew-t: arch's fitted-distribution simulator, **unseeded** (`_discrepancies.md`). Cumulative = sum over k ≤ h. Method: `simulation` (h > 1). | ||||
| 26 | + | ||||
| 27 | +## 7. Implementation | ||||
| 28 | +- `src/wp46/models/arch_models.py` (`SPECS["egarch11"]`), arch 8.0.0 (`sheppard2025arch`). | ||||
| 29 | +- Cross-check (`results/metrics/rugarch_crosscheck.json`, rugarch `eGARCH`, t): −3376.6704 (ours) vs −3376.6833 (rugarch), **difference +0.0129**; coefficients agree after the α/γ label swap (β 0.96868 vs 0.96871, ν 6.98 vs 6.99); ω differs (−0.0110 vs −0.0171) because rugarch uses the distribution-specific $E|z|$ in the centring (observational equivalence through ω). | ||||
| 30 | +- Tests: `tests/replication/test_rugarch.py` (fit recorded; no assertion on EGARCH beyond the JSON); pilot `egarch11__t` 1,032/1,032 forecasts `ok` on CL, 207/207 refits `ok`. | ||||
| 31 | + | ||||
| 32 | +## 8. Known limitations / failure modes | ||||
| 33 | +β frequently close to 1 (log-variance near unit root) → explosive multi-step simulations are bounded only by `LNSIGMA_MAX`/variance bounds; multi-step forecasts carry Monte-Carlo error and, for non-normal laws, are unseeded; $E[\sigma^2_{t+k}]$ is a mean of log-normal-like paths and is sensitive to tail draws (large variance of the path mean at h = 22); the centring constant mismatch for non-normal laws is harmless for the fit but makes `omega` non-comparable across distributions. | ||||
| 34 | + | ||||
| 35 | +## 9. Computational footprint | ||||
| 36 | +Estimation cheap (pilot median fit time per refit, t: 0.0088 s CL / 0.0095 s EURUSD); forecasting by simulation (22 × 2,000 draws per origin) is the dominant cost. | ||||
| 37 | + | ||||
| 38 | +## 10. Literature expectations | ||||
| 39 | +`hansen2005forecast`: EGARCH-type leverage models among those that beat GARCH(1,1) on IBM; `brownlees2011practical` rank EGARCH/asymmetric models best for US equities; `nelson1991conditional` originally with GED innovations. Expectation: strong at h = 1 on equities (H1), weaker at h = 22 where the simulation mean of exponentials inflates forecasts; no gain expected on FX (`hansen2005forecast`). | ||||
added
model_cards/figarch11.md
+40 −0
@@ -0,0 +1,40 @@ | |||||
| 1 | +# Model card — `figarch11` (FIGARCH(1,d,1)) | ||||
| 2 | + | ||||
| 3 | +## 1. Identity | ||||
| 4 | +- **model_id:** `figarch11` · **family:** fractional · **tier:** A · **status:** implemented · **impl:** arch 8.0.0 (`FIGARCH(p=1, q=1, truncation=1000)`) | ||||
| 5 | +- **Label:** FIGARCH(1,d,1) · **distributions:** normal, t, ged, skewt · registry note: "arch truncates the ARCH(∞) representation at 1000 lags" | ||||
| 6 | +- **Seminal citation:** `baillie1996fractionally` | ||||
| 7 | +- **Other references:** `conrad2006inequality` (necessary and sufficient positivity), `ding1996modeling` (long memory in volatility), `bollerslev1996modeling` (FIEGARCH), `davidson2004moment` (HYGARCH); `chung1999estimating` is **unverified and not in the .bib** (literature matrix). | ||||
| 8 | + | ||||
| 9 | +## 2. Definition (arch parameterisation) | ||||
| 10 | +Model: $[1 - \beta L]\,\sigma_t^2 = \omega + [1 - \beta L - (1 - \phi L)(1-L)^d]\,\varepsilon_t^2$, estimated through the truncated ARCH(∞) representation | ||||
| 11 | +$$\sigma_t^2 = \frac{\omega}{1-\beta} + \sum_{i=1}^{1000}\lambda_i\,\varepsilon_{t-i}^2,\qquad \lambda_1 = \phi - \beta + d,\ \ \delta_1 = d,\ \ \delta_j = \frac{j-1-d}{j}\,\delta_{j-1},\ \ \lambda_j = \beta\lambda_{j-1} + \delta_j - \phi\,\delta_{j-1} .$$ | ||||
| 12 | +Lags beyond the available sample use the backcast (`figarch_recursion`: $\sigma_t^2 = \tilde\omega + (\sum_{i > t}\lambda_i)\,\text{backcast} + \sum_{i \le \min(t,1000)}\lambda_i\varepsilon_{t-i}^2$). Innovations: normal, t, GED, Hansen skew-t. | ||||
| 13 | + | ||||
| 14 | +## 3. Parameter space and admissibility | ||||
| 15 | +- Parameters: `mu, omega, phi, d, beta` (+ distribution). | ||||
| 16 | +- arch bounds: $\omega \in [0, 10v]$, $\phi \in [0, 0.5]$, $d \in [0, 1-\epsilon]$, $\beta \in [0, 1-\epsilon]$; linear constraints $\omega > 0$, $0 \le d \le 1$, $0 \le \phi \le (1-d)/2$, $0 \le \beta \le d + \phi$ (sufficient positivity conditions of the (1,d,1) case as coded in arch; the necessary and sufficient set of `conrad2006inequality` is larger). | ||||
| 17 | +- Admissibility flag (`ArchModel.fit`): $0 \le d \le 1$. FIGARCH is strictly but not covariance stationary for d > 0 (infinite unconditional variance), so no $\alpha+\beta<1$-type flag applies. | ||||
| 18 | + | ||||
| 19 | +## 4. Nesting and relations | ||||
| 20 | +d = 0 gives GARCH(1,1) with $\alpha = \phi - \beta$ (…) and d = 1 the IGARCH-type unit root; `igarch11` and `garch11` are the end points. `rm2006` and HAR are non-estimated / regression analogues of hyperbolic memory. FIEGARCH/FIAPARCH/HYGARCH (unsupported) are its extensions. | ||||
| 21 | + | ||||
| 22 | +## 5. Estimation | ||||
| 23 | +arch `ConstantMean` + `FIGARCH(1,1)` + distribution; SLSQP (`maxiter` 1000) with the bounds/constraints of §3; starting values from arch's grid d ∈ {0.2, 0.5, 0.7} × φ-ratio ∈ {0.2, 0.5, 0.8} × β-ratio ∈ {0.1, 0.5, 0.9}, $\omega = (1-\beta)\,\overline{\varepsilon^2}\,(1 - \sum_i\lambda_i)$, best Gaussian log-likelihood; backcast = exponentially weighted mean of the first 75 squared residuals; ≤ 2 restarts (`ArchModel.fit`). Point estimates only. Each likelihood evaluation convolves 1,000 weights over the 1,000-day window. | ||||
| 24 | + | ||||
| 25 | +## 6. Forecasting | ||||
| 26 | +arch `FIGARCH._analytic_forecast`: the ARCH(∞) recursion is iterated forward with future $\varepsilon^2$ replaced by their forecasts, $\hat\sigma^2_{t+k|t} = \tilde\omega + \sum_{i=1}^{1000}\lambda_i\,\widetilde{\varepsilon^2}_{t+k-i}$ ($\widetilde{\varepsilon^2}_s = \varepsilon_s^2$ for $s \le t$, $= \hat\sigma^2_{s|t}$ for $s > t$; pre-sample lags = backcast). Exact under $E z^2 = 1$. Cumulative = sum over k ≤ h. Method: `analytic`. | ||||
| 27 | + | ||||
| 28 | +## 7. Implementation | ||||
| 29 | +- `src/wp46/models/arch_models.py` (`SPECS["figarch11"]`), arch 8.0.0 (`sheppard2025arch`). | ||||
| 30 | +- Cross-check (`results/metrics/rugarch_crosscheck.json`, rugarch `fiGARCH`, t): −3383.4506 (ours) vs −3381.9798 (rugarch), **difference −1.4708** (ours lower) — the only cross-check outside ±0.3; attributed to different truncation / constraint handling between arch and rugarch (D-14, `progress.md` open issue). Estimates: d = 0.546, φ = 0.227, β = 0.693, ν = 6.45 (arch). Reported as an implementation caveat; not resolved. | ||||
| 31 | +- Tests: `tests/replication/test_rugarch.py` (fit recorded, no assertion on FIGARCH). No simulation-recovery test. | ||||
| 32 | + | ||||
| 33 | +## 8. Known limitations / failure modes | ||||
| 34 | +ω is small and poorly identified (literature matrix); d near 0 or 1 hits the bounds; the sufficient constraints exclude admissible parameter sets; the 1,000-lag truncation inside a 1,000-day window means every in-sample variance uses the backcast for the oldest lags; the 1.47 log-likelihood discrepancy with rugarch is unexplained; infinite unconditional variance makes long-horizon forecasts grow slowly without bound. | ||||
| 35 | + | ||||
| 36 | +## 9. Computational footprint | ||||
| 37 | +Analytic but O(T × 1000) per likelihood evaluation (the heaviest analytic model of Tier A); forecasts are O(22 × 1000). Not in the pilot. | ||||
| 38 | + | ||||
| 39 | +## 10. Literature expectations | ||||
| 40 | +`baillie1996fractionally` and `ding1996modeling` document hyperbolic decay in volatility autocorrelations; `hansen2005forecast` include FIGARCH among models that do not beat GARCH(1,1) at the 1-day horizon; `lamoureux1990persistence`/`hillebrand2005neglecting` warn that breaks mimic long memory. Pre-registered H4 (persistence structure) predicts gains, if any, at h = 22 rather than h = 1. | ||||
added
model_cards/garchm11.md
+39 −0
@@ -0,0 +1,39 @@ | |||||
| 1 | +# Model card — `garchm11` (GARCH-in-mean(1,1)) | ||||
| 2 | + | ||||
| 3 | +## 1. Identity | ||||
| 4 | +- **model_id:** `garchm11` · **family:** classical · **tier:** A · **status:** implemented · **impl:** custom (`src/wp46/models/custom.py::GARCHM11`) | ||||
| 5 | +- **Label:** GARCH-M(1,1) · **distributions:** normal, t, ged, skewt | ||||
| 6 | +- **Seminal citation:** `engle1987estimating` (Engle, Lilien & Robins 1987, ARCH-M) | ||||
| 7 | +- **Other references:** `bollerslev1986generalized`; literature matrix §a.1 ("mean and variance parameters not separable → affects multi-step forecasts of cumulative returns"). | ||||
| 8 | + | ||||
| 9 | +## 2. Definition | ||||
| 10 | +$$r_t = \mu + \delta\,\sigma_t^2 + \varepsilon_t,\quad \varepsilon_t = \sigma_t z_t,\qquad \sigma_t^2 = \omega + \alpha\,\varepsilon_{t-1}^2 + \beta\,\sigma_{t-1}^2 ,$$ | ||||
| 11 | +with the risk-premium function $g(\sigma_t^2) = \sigma_t^2$ (variance in the mean, not $\sigma_t$ or $\log\sigma_t^2$). Recursion `rec_garchm`: $\sigma_0^2 = \omega + (\alpha+\beta)s_0$, $\varepsilon_t = r_t - \mu - \delta\sigma_t^2$ computed jointly with $\sigma_t^2$. Innovations: normal, t, GED, Hansen skew-t. | ||||
| 12 | + | ||||
| 13 | +## 3. Parameter space and admissibility | ||||
| 14 | +- Parameters: `mu, delta, omega, alpha, beta` (+ distribution). `delta` is unconstrained. | ||||
| 15 | +- Reparameterisation: $\omega = e^{\theta}$, persistence $s = \alpha + \beta = \sigma(\theta)$, share $\alpha/s = \sigma(\theta')$. | ||||
| 16 | +- Admissibility flag: $\omega > 0$, $\alpha, \beta \ge 0$, $\alpha + \beta < 1$ (variance equation as GARCH(1,1)). | ||||
| 17 | + | ||||
| 18 | +## 4. Nesting and relations | ||||
| 19 | +Nests `garch11` ($\delta = 0$). Only registry model whose conditional mean depends on the variance; its variance recursion is GARCH(1,1) but the residuals differ ($\varepsilon_t$ depends on δ). | ||||
| 20 | + | ||||
| 21 | +## 5. Estimation | ||||
| 22 | +Custom MLE with a model-specific objective (`GARCHM11._negll`): $-\sum_t[\log f_z(\varepsilon_t/\sigma_t) - \tfrac12\log\sigma_t^2]$ where $(\sigma_t^2, \varepsilon_t)$ come from `rec_garchm`. L-BFGS-B (maxiter 2000) from three starts (δ, ω, α, β) ∈ {(0, 0.05v, 0.05, 0.90), (0.02, 0.02v, 0.10, 0.88), (−0.02, 0.2v, 0.15, 0.65)}, Nelder–Mead polish on failure, μ start = sample mean, backcast $s_0$ from the demeaned returns (computed once with μ = sample mean, i.e. ignoring the in-mean term, and reused for filtering/forecasting). Point estimates only; no standard errors. | ||||
| 23 | + | ||||
| 24 | +## 6. Forecasting | ||||
| 25 | +`GARCHM11.forecast` recomputes $(\sigma_t^2, \varepsilon_t)$ with `rec_garchm`, then $\hat\sigma^2_{t+1|t} = \omega + \alpha\varepsilon_t^2 + \beta\sigma_t^2$ and $\hat\sigma^2_{t+k|t} = \omega + (\alpha+\beta)\hat\sigma^2_{t+k-1|t}$ (identical to GARCH(1,1)); mean forecast $\hat\mu_{t+1} = \mu + \delta\hat\sigma^2_{t+1|t}$ (used for VaR). Cumulative $h$-day variance = sum of per-step variances (the variance of the h-day return induced by the time-varying mean $\delta\sigma^2_{t+k}$ is ignored, as for all models). Method: `analytic`. | ||||
| 26 | + | ||||
| 27 | +## 7. Implementation | ||||
| 28 | +- `src/wp46/models/custom.py::GARCHM11` (numba `rec_garchm`). | ||||
| 29 | +- Cross-check: **none** — `garchm11` is not in `results/metrics/rugarch_crosscheck.json` (rugarch `archm` was not included in `tests/replication/rugarch_crosscheck.R`). | ||||
| 30 | +- Tests: **no unit, simulation or integration test references `GARCHM11`** (it is absent from `tests/unit/test_custom_models.py` imports and parametrisations). This is a gap relative to CLAUDE.md rule 6 — recorded in `_discrepancies.md`. | ||||
| 31 | + | ||||
| 32 | +## 8. Known limitations / failure modes | ||||
| 33 | +δ is weakly identified on daily data (risk-premium effects are second order; literature matrix: "low priority in a variance-forecast benchmark"); the joint mean/variance likelihood can be flat in δ and produce spurious large |δ| with near-integrated variance. The backcast ignores δ (minor). Positivity of $\sigma_t^2$ is guaranteed by the reparameterisation. | ||||
| 34 | + | ||||
| 35 | +## 9. Computational footprint | ||||
| 36 | +Analytic; 5–7 parameters; the recursion must recompute residuals at each likelihood evaluation (same cost order as `garch11` custom). Not in the pilot. | ||||
| 37 | + | ||||
| 38 | +## 10. Literature expectations | ||||
| 39 | +`engle1987estimating` motivate ARCH-M for term premia, not for variance forecasting; the literature matrix states the mean effect on h-day variance is second order. Expectation: variance forecasts essentially equal to GARCH(1,1); any difference comes from estimation noise in δ (H5: more failures, no accuracy gain). | ||||
added
model_cards/gjr11.md
+42 −0
@@ -0,0 +1,42 @@ | |||||
| 1 | +# Model card — `gjr11` (GJR-GARCH(1,1)) | ||||
| 2 | + | ||||
| 3 | +## 1. Identity | ||||
| 4 | +- **model_id:** `gjr11` · **family:** asymmetric · **tier:** A · **status:** implemented · **impl:** arch 8.0.0 (`GARCH(p=1, o=1, q=1)`); a custom twin `gjr11_custom` (`src/wp46/models/custom.py::GJR11`) exists for cross-checks and simulation tests only. | ||||
| 5 | +- **Label:** GJR-GARCH(1,1) · **distributions:** normal, t, ged, skewt | ||||
| 6 | +- **Seminal citation:** `glosten1993relation` | ||||
| 7 | +- **Other references:** `engle1993measuring` (news-impact curve, sign-bias tests), `zakoian1994threshold` (TGARCH — not the same model, see `tarch11`), `ling2002stationarity` (moments of asymmetric GARCH), `hansen2005forecast`, `brownlees2011practical`, `bollerslev2010glossary` (naming: EViews "TARCH" = GJR). | ||||
| 8 | + | ||||
| 9 | +## 2. Definition (arch parameterisation) | ||||
| 10 | +$$r_t = \mu + \varepsilon_t,\ \varepsilon_t = \sigma_t z_t,\qquad \sigma_t^2 = \omega + \alpha\,\varepsilon_{t-1}^2 + \gamma\,\varepsilon_{t-1}^2\,\mathbb 1\{\varepsilon_{t-1} < 0\} + \beta\,\sigma_{t-1}^2 .$$ | ||||
| 11 | +arch `garch_recursion` with power 2: pre-sample terms use the backcast for $\varepsilon^2$ and $\sigma^2$ and $0.5\times$ backcast for the asymmetric term. Innovations: normal, t, GED, Hansen skew-t. | ||||
| 12 | + | ||||
| 13 | +## 3. Parameter space and admissibility | ||||
| 14 | +- Parameters: `mu, omega, alpha[1], gamma[1], beta[1]` (+ distribution). | ||||
| 15 | +- arch bounds: $\omega \in [10^{-8}v, 10v]$, $\alpha \in [0,1]$, $\gamma \in [-1, 2]$, $\beta \in [0,1]$; linear constraints $\omega > 0$, $\alpha \ge 0$, $\alpha + \gamma \ge 0$, $\beta \ge 0$, $\alpha + \tfrac12\gamma + \beta < 1$ (arch uses the symmetric weight ½ in the optimizer constraint for every distribution). | ||||
| 16 | +- Admissibility flag (`ArchModel.fit`): $\alpha + \beta + 0.5\gamma < 1$ — the covariance-stationarity condition under a **symmetric** innovation law. For the skew-t the exact condition is $\alpha + \beta + \kappa\gamma < 1$ with $\kappa = E[z^2\mathbb 1\{z<0\}] \neq 0.5$ (`distributions.neg_half_moment`); it is used by the custom twin (`GJR11.admissible`) but **not** by the registry implementation (recorded in `_discrepancies.md`). | ||||
| 17 | +- Custom twin reparameterisation: $\omega = e^{\theta}$, persistence $s = \sigma(\theta)$, softmax shares of $s$ among $(\alpha, \kappa\gamma, \beta)$. | ||||
| 18 | + | ||||
| 19 | +## 4. Nesting and relations | ||||
| 20 | +Nests `garch11` (γ = 0). Special case of `aparch11` with δ = 2 and $\gamma_{APARCH}$ mapped to the GJR indicator form only approximately (APARCH uses $(|\varepsilon| - \gamma\varepsilon)^\delta$, which for δ = 2 is $(1\mp\gamma)^2\varepsilon^2$: GJR corresponds to $\alpha_{GJR} = \alpha(1-\gamma)^2$, $\alpha_{GJR}+\gamma_{GJR} = \alpha(1+\gamma)^2$). Not the same as `tarch11` (threshold on σ, power 1). Same news-impact asymmetry as `nagarch11`/`qgarch11` but with a kink rather than a shift. | ||||
| 21 | + | ||||
| 22 | +## 5. Estimation | ||||
| 23 | +arch `ConstantMean` + `GARCH(1,1,1)` + distribution; SLSQP (`fit(disp="off", options={"maxiter": 1000})`) with the bounds/constraints of §3; starting values from arch's grid (α ∈ {0.01, 0.05, 0.1, 0.2}, γ same grid, persistence ∈ {0.5, 0.7, 0.9, 0.98}; best Gaussian log-likelihood); backcast = exponentially weighted mean of the first min(75, T) squared residuals (0.94ⁱ); ≤ 2 restarts (previous estimate × (0.9 + 0.2(i+1)/3), maxiter 2000) when `convergence_flag ≠ 0`. Only point estimates are used in the rolling benchmark; daily filtering with `am.fix(params)`. | ||||
| 24 | + | ||||
| 25 | +## 6. Forecasting | ||||
| 26 | +arch `GARCH._analytic_forecast` (power 2): $\hat\sigma^2_{t+1|t} = \omega + \alpha\varepsilon_t^2 + \gamma\varepsilon_t^2\mathbb 1\{\varepsilon_t<0\} + \beta\sigma_t^2$ and, for $k \ge 2$, | ||||
| 27 | +$$\hat\sigma^2_{t+k|t} = \omega + (\alpha + 0.5\,\gamma + \beta)\,\hat\sigma^2_{t+k-1|t},$$ | ||||
| 28 | +because arch sets the future asymmetric term to $0.5\times$ the variance forecast (`_asym_resids[h+m] = sqrt(0.5 * forecast)`). This is exact for symmetric $z$ (normal, t, GED) and **approximate for the skew-t** (exact weight $\kappa = E[z^2\mathbb 1\{z<0\}]$, > 0.5 for λ < 0). The custom twin implements $\hat\sigma^2_{t+k|t} = \omega + (\alpha + \kappa\gamma + \beta)\hat\sigma^2_{t+k-1|t}$ with κ from `neg_half_moment` (D-09 describes this κ-version; the scored `gjr11` is the arch version). Cumulative = sum over k ≤ h. Method: `analytic`. | ||||
| 29 | + | ||||
| 30 | +## 7. Implementation | ||||
| 31 | +- `src/wp46/models/arch_models.py` (`SPECS["gjr11"]`), arch 8.0.0 (`sheppard2025arch`); custom twin `custom.py::GJR11` (`model_id = "gjr11_custom"`, not in the registry). | ||||
| 32 | +- Cross-check (`results/metrics/rugarch_crosscheck.json`, rugarch `gjrGARCH`, t): −3372.9536 (ours, arch) vs −3372.9905 (rugarch), **difference +0.0369**; parameters agree to 4 decimals (α 0.04267/0.04264, γ 0.06203/0.06202, β 0.90036/0.90040, ν 7.002/7.010). | ||||
| 33 | +- Tests: `tests/replication/test_rugarch.py` (arch GJR vs rugarch, assert ours ≥ rugarch − 1); custom twin: `tests/unit/test_custom_models.py::test_nesting_and_admissibility[GJR11]`, `test_no_lookahead_in_forecasts`, `test_edge_cases_constant_and_extreme` (spike of 60 % at t = 700), `tests/simulation/test_recovery.py::test_gjr_recovery_median_over_replications` (12 seeded replications, T = 4,000, t(6) innovations; median within 0.02–0.03 of (0.04, 0.03, 0.10, 0.88)); driver: `tests/integration/test_rolling_driver.py::test_driver_tier_b_and_failure_flags` (`gjr11`, t). The fixture of the rugarch cross-check is itself GJR-t data. | ||||
| 34 | + | ||||
| 35 | +## 8. Known limitations / failure modes | ||||
| 36 | +α often converges to the zero bound on equities (all news impact loaded on γ) — a boundary optimum flagged by SLSQP; near-integrated $\alpha + \gamma/2 + \beta$; the symmetric-κ forecast/admissibility rule under skew-t (above); the optimizer bound $\gamma \le 2$. Positivity requires $\alpha + \gamma \ge 0$ (imposed). | ||||
| 37 | + | ||||
| 38 | +## 9. Computational footprint | ||||
| 39 | +Analytic; 5–7 parameters. Pilot median fit time per refit (t innovations): 0.0081 s (CL), 0.0101 s (EURUSD). | ||||
| 40 | + | ||||
| 41 | +## 10. Literature expectations | ||||
| 42 | +`hansen2005forecast`: on IBM, models with a leverage effect (GJR among them) significantly outperform GARCH(1,1); on DM/$ they do not. `brownlees2011practical`, `awartani2005predicting`: asymmetric GARCH best overall for equity indices, especially in stressed periods. Pre-registered H1 (asymmetry) and H6 (regimes) concern this model directly; the matrix notes the GJR/TGARCH naming confusion that the registry resolves by keeping both definitions. | ||||
added
model_cards/igarch11.md
+39 −0
@@ -0,0 +1,39 @@ | |||||
| 1 | +# Model card — `igarch11` (Integrated GARCH(1,1)) | ||||
| 2 | + | ||||
| 3 | +## 1. Identity | ||||
| 4 | +- **model_id:** `igarch11` · **family:** classical · **tier:** A · **status:** implemented · **impl:** custom (`src/wp46/models/custom.py::IGARCH11`) | ||||
| 5 | +- **Label:** IGARCH(1,1) · **distributions:** normal, t, ged, skewt | ||||
| 6 | +- **Seminal citation:** `engle1986modelling` (Engle & Bollerslev 1986) | ||||
| 7 | +- **Other references:** `nelson1990stationarity` (strict stationarity of IGARCH), `lumsdaine1996consistency`, `lee1994asymptotic`, `jensen2004asymptotic` (QMLE under unit persistence); `lamoureux1990persistence`, `mikosch2004nonstationarities`, `hillebrand2005neglecting` (spurious IGARCH from breaks); `jpmorgan1996riskmetrics` (EWMA, nested). | ||||
| 8 | + | ||||
| 9 | +## 2. Definition | ||||
| 10 | +$$r_t = \mu + \varepsilon_t,\ \varepsilon_t = \sigma_t z_t,\qquad \sigma_t^2 = \omega + \alpha\,\varepsilon_{t-1}^2 + (1-\alpha)\,\sigma_{t-1}^2 ,$$ | ||||
| 11 | +i.e. GARCH(1,1) with $\beta = 1 - \alpha$ imposed (`rec_garch(eps, omega, alpha, 1 - alpha, s0)`), $\sigma_0^2 = \omega + s_0$ ($s_0$ = backcast, since $\alpha + \beta = 1$). Innovations: normal, t(ν), GED(ν), Hansen skew-t(η, λ) (standardised, `distributions.py`). | ||||
| 12 | + | ||||
| 13 | +## 3. Parameter space and admissibility | ||||
| 14 | +- Parameters: `mu, omega, alpha` (+ `nu` | `eta, lambda`). | ||||
| 15 | +- Reparameterisation (unconstrained θ): $\omega = e^{\theta_0}$, $\alpha = \sigma(\theta_1) \in (0,1)$ (logistic); t: $\nu = 2.05 + e^{\theta}$; GED: $\nu = 0.3 + e^{\theta}$; skew-t: $\eta = 2.05 + e^{\theta}$, $\lambda = 0.99\tanh(\theta')$. | ||||
| 16 | +- Admissibility flag: $\omega > 0$ and $0 < \alpha < 1$. No covariance stationarity (unconditional variance does not exist); strictly stationary for $\alpha < 1$ (`nelson1990stationarity`). | ||||
| 17 | + | ||||
| 18 | +## 4. Nesting and relations | ||||
| 19 | +Boundary case of `garch11` ($\alpha + \beta = 1$); nests `ewma094` ($\omega = 0$, $\alpha = 0.06$ — registry `ewma094: nested_in: igarch11`). Variance forecasts grow linearly in the horizon (unit root in $\varepsilon_t^2$). Related to `figarch11` with d = 1. | ||||
| 20 | + | ||||
| 21 | +## 5. Estimation | ||||
| 22 | +Custom MLE (`CustomModel.fit`): objective $-\sum_t[\log f_z(z_t) - \tfrac12\log\sigma_t^2]$ with numba recursion; L-BFGS-B (maxiter 2000, ftol 1e-10, gtol 1e-6) on θ from three starting vectors (ω, α) ∈ {(0.01 v, 0.06), (0.003 v, 0.03), (0.03 v, 0.12)} with $v = \operatorname{var}(r)$ (at least two starts are tried; the third only if the second fails), Nelder–Mead polish (maxiter 4000) if L-BFGS-B does not report success; μ starts at the sample mean; distribution starts ν = 6 / 1.5 / (6, −0.05). Initial variance: arch-style backcast of the demeaned returns ($\sum_{i<75} w_i (r_i - \bar r)^2$, $w_i \propto 0.94^i$), stored in `aux["backcast"]`. `converged` = optimizer success with finite objective; inadmissible optima kept and flagged. No standard errors; point estimates only. | ||||
| 23 | + | ||||
| 24 | +## 6. Forecasting | ||||
| 25 | +`IGARCH11.step_forecast`: $\hat\sigma^2_{t+1|t} = \omega + \alpha\varepsilon_t^2 + (1-\alpha)\sigma_t^2$, $\hat\sigma^2_{t+k|t} = \omega + \hat\sigma^2_{t+k-1|t}$ for $k = 2..22$ (linear growth by ω per day). Cumulative $h$-day variance $= h\hat\sigma^2_{t+1|t} + \omega h(h-1)/2$. Method: `analytic`. | ||||
| 26 | + | ||||
| 27 | +## 7. Implementation | ||||
| 28 | +- `src/wp46/models/custom.py::IGARCH11` (custom, numba `rec_garch`), standardised densities from `src/wp46/models/distributions.py` (equal to arch's to 1e-12, `tests/unit/test_distributions.py`). | ||||
| 29 | +- Cross-check (`results/metrics/rugarch_crosscheck.json`, rugarch `iGARCH`, Student-t, shared fixture): log-likelihood −3385.4670 (ours) vs −3385.5171 (rugarch), **difference +0.0502**. | ||||
| 30 | +- Tests: `tests/replication/test_rugarch.py` (asserts ours ≥ rugarch − 1.0); `tests/unit/test_custom_models.py::test_nesting_and_admissibility[IGARCH11]` (convergence, admissibility, positive finite 22-step forecasts; excluded from the "nests GARCH(1,1)" log-likelihood assertion). No simulation-recovery test. | ||||
| 31 | + | ||||
| 32 | +## 8. Known limitations / failure modes | ||||
| 33 | +Imposes unit persistence even when the data are stationary: on the GJR-t fixture the IGARCH likelihood is 6.0 units below GARCH(1,1) (−3385.47 vs −3379.46). Forecast variance grows without bound with h (h = 22 cumulative variance inflated by $\omega \cdot 231$). $\omega$ near zero makes the model indistinguishable from EWMA. Linear growth makes long-horizon forecasts sensitive to $\hat\omega$. | ||||
| 34 | + | ||||
| 35 | +## 9. Computational footprint | ||||
| 36 | +Analytic recursion and forecasts; 3–5 parameters; L-BFGS-B with numerical gradients. Not in the pilot; cost comparable to `garch11` custom estimation (a few milliseconds per refit on a 1,000-day window). | ||||
| 37 | + | ||||
| 38 | +## 10. Literature expectations | ||||
| 39 | +Near-integrated GARCH estimates are common in long daily samples (`engle1986modelling`, `lamoureux1990persistence`); `hansen2005forecast` include IGARCH among the models that do not beat GARCH(1,1). Expectation: close to GARCH(1,1) at h = 1 for highly persistent instruments, worse at h = 22 because of the absent mean reversion (literature matrix §a.1). | ||||
added
model_cards/nagarch11.md
+41 −0
@@ -0,0 +1,41 @@ | |||||
| 1 | +# Model card — `nagarch11` (NAGARCH(1,1), Engle–Ng nonlinear asymmetric GARCH) | ||||
| 2 | + | ||||
| 3 | +## 1. Identity | ||||
| 4 | +- **model_id:** `nagarch11` · **family:** asymmetric · **tier:** A · **status:** implemented · **impl:** custom (`src/wp46/models/custom.py::NAGARCH11`) | ||||
| 5 | +- **Label:** NAGARCH(1,1) (Engle-Ng) · **distributions:** normal, t, ged, skewt | ||||
| 6 | +- **Seminal citation:** `engle1993measuring` | ||||
| 7 | +- **Other references:** `higgins1992class` (NARCH — a *different* "NGARCH", literature-matrix caveat #3), `glosten1993relation`, `sentana1995quadratic` (QGARCH, the other shifted/linear-asymmetry form), `brownlees2011practical` (NGARCH in their comparison). | ||||
| 8 | + | ||||
| 9 | +## 2. Definition | ||||
| 10 | +$$r_t = \mu + \varepsilon_t,\ \varepsilon_t = \sigma_t z_t,\qquad \sigma_t^2 = \omega + \alpha\big(\varepsilon_{t-1} - \theta\,\sigma_{t-1}\big)^2 + \beta\,\sigma_{t-1}^2 ,$$ | ||||
| 11 | +`rec_nagarch` with $\sigma_0^2 = \omega + [\alpha(1+\theta^2) + \beta]\,s_0$ ($s_0$ = backcast). Equivalent to rugarch's fGARCH/NAGARCH $\sigma_t^2 = \omega + \alpha\sigma_{t-1}^2(z_{t-1} - \eta)^2 + \beta\sigma_{t-1}^2$ with $\eta = \theta$. Innovations: normal, t, GED, Hansen skew-t. | ||||
| 12 | + | ||||
| 13 | +## 3. Parameter space and admissibility | ||||
| 14 | +- Parameters: `mu, omega, alpha, theta, beta` (+ distribution). | ||||
| 15 | +- Reparameterisation: $\omega = e^{\theta_0}$; persistence $s = \alpha(1+\theta^2) + \beta = \sigma(\theta_1) \in (0,1)$; share $w = \alpha(1+\theta^2)/s = \sigma(\theta_2)$; $\theta$ unconstrained. Hence $\alpha = s w/(1+\theta^2)$, $\beta = s(1-w)$. | ||||
| 16 | +- Admissibility flag: $\omega > 0$, $\alpha, \beta \ge 0$, $\alpha(1+\theta^2) + \beta < 1$ (covariance stationarity under $E z = 0$, $E z^2 = 1$ — holds for all four laws, including Hansen's skew-t which is standardised to zero mean and unit variance). | ||||
| 17 | + | ||||
| 18 | +## 4. Nesting and relations | ||||
| 19 | +Nests `garch11` (θ = 0). News-impact curve = GARCH parabola shifted to the right by $\theta\sigma_{t-1}$ (asymmetry via a shift, not a kink as in `gjr11`); QGARCH is the linear-term version ($\gamma\varepsilon_{t-1}$ instead of the shift, same quadratic form with $\gamma = -2\alpha\theta\sigma_{t-1}$ varying over time). | ||||
| 20 | + | ||||
| 21 | +## 5. Estimation | ||||
| 22 | +Custom MLE (`CustomModel.fit`): L-BFGS-B on θ (maxiter 2000, ftol 1e-10, gtol 1e-6) from three starts (ω, α, θ, β) ∈ {(0.05v, 0.05, 0.5, 0.88), (0.02v, 0.08, 1.0, 0.85), (0.1v, 0.1, 0.0, 0.8)}, Nelder–Mead polish on failure; μ start = sample mean, ν/η/λ starts 6 / 1.5 / (6, −0.05); backcast $s_0$ = arch-style exponentially weighted mean of the first 75 squared demeaned returns. Point estimates only. | ||||
| 23 | + | ||||
| 24 | +## 6. Forecasting | ||||
| 25 | +`NAGARCH11.step_forecast`: $\hat\sigma^2_{t+1|t} = \omega + \alpha(\varepsilon_t - \theta\sigma_t)^2 + \beta\sigma_t^2$; for $k \ge 2$, | ||||
| 26 | +$$\hat\sigma^2_{t+k|t} = \omega + \big[\alpha(1+\theta^2) + \beta\big]\,\hat\sigma^2_{t+k-1|t},$$ | ||||
| 27 | +exact because $E[(\varepsilon - \theta\sigma)^2 \mid \sigma^2] = \sigma^2(1 + \theta^2)$ when $E z = 0$, $E z^2 = 1$. Cumulative = sum over k ≤ h. Method: `analytic`. | ||||
| 28 | + | ||||
| 29 | +## 7. Implementation | ||||
| 30 | +- `src/wp46/models/custom.py::NAGARCH11` (numba `rec_nagarch`). | ||||
| 31 | +- Cross-check (`results/metrics/rugarch_crosscheck.json`, rugarch `fGARCH` submodel `NAGARCH`, t): −3373.3123 (ours) vs −3373.3505 (rugarch), **difference +0.0382**. | ||||
| 32 | +- Tests: `tests/replication/test_rugarch.py` (assert ours ≥ rugarch − 1); `tests/unit/test_custom_models.py::test_nesting_and_admissibility[NAGARCH11]` (log-likelihood ≥ GARCH(1,1) − 0.5, admissible, positive 22-step forecasts), `test_no_lookahead_in_forecasts`; `tests/simulation/test_recovery.py::test_nagarch_recovery` (T = 5,000, normal, θ = 0.8 recovered within 0.3, β within 0.05); pilot `nagarch11__t`: 207/207 refits `ok` on CL. | ||||
| 33 | + | ||||
| 34 | +## 8. Known limitations / failure modes | ||||
| 35 | +θ is weakly identified when α is small (the shift multiplies α); large |θ| with tiny α yields flat likelihoods and slow L-BFGS-B progress (pilot max fit time 0.17 s on CL vs median 0.009 s). Near-integrated persistence as in GARCH. The sigmoid reparameterisation cannot return exactly $s = 1$ (inadmissible optima can only arise from numerical failure). | ||||
| 36 | + | ||||
| 37 | +## 9. Computational footprint | ||||
| 38 | +Analytic; 5–7 parameters. Pilot median fit time per refit (t): 0.0089 s (CL), 0.0218 s (EURUSD). | ||||
| 39 | + | ||||
| 40 | +## 10. Literature expectations | ||||
| 41 | +`engle1993measuring` show the NAGARCH news-impact curve fits Japanese equity data better than GARCH; `brownlees2011practical` include NGARCH among the best performers on US equities; `hansen2005forecast` find leverage specifications superior on IBM only. Expectation: comparable to GJR/EGARCH at h = 1 on equities (H1); exact analytic multi-step forecasts are an advantage over the simulation-based asymmetric models at h = 22 (H5). | ||||
added
model_cards/qgarch11.md
+40 −0
@@ -0,0 +1,40 @@ | |||||
| 1 | +# Model card — `qgarch11` (QGARCH(1,1), Sentana's quadratic GARCH) | ||||
| 2 | + | ||||
| 3 | +## 1. Identity | ||||
| 4 | +- **model_id:** `qgarch11` · **family:** asymmetric · **tier:** A · **status:** implemented · **impl:** custom (`src/wp46/models/custom.py::QGARCH11`) | ||||
| 5 | +- **Label:** QGARCH(1,1) (Sentana) · **distributions:** normal, t, ged, skewt | ||||
| 6 | +- **Seminal citation:** `sentana1995quadratic` | ||||
| 7 | +- **Other references:** `engle1993measuring` (NAGARCH, the shifted form), `glosten1993relation`. | ||||
| 8 | + | ||||
| 9 | +## 2. Definition | ||||
| 10 | +$$r_t = \mu + \varepsilon_t,\ \varepsilon_t = \sigma_t z_t,\qquad \sigma_t^2 = \omega + \alpha\,\varepsilon_{t-1}^2 + \gamma\,\varepsilon_{t-1} + \beta\,\sigma_{t-1}^2 ,$$ | ||||
| 11 | +`rec_qgarch` with $\sigma_0^2 = \omega + (\alpha+\beta)s_0$ and a floor $\sigma_t^2 \ge 10^{-12}$ inside the recursion. Innovations: normal, t, GED, Hansen skew-t. | ||||
| 12 | + | ||||
| 13 | +## 3. Parameter space and admissibility | ||||
| 14 | +- Parameters: `mu, omega, alpha, gamma, beta` (+ distribution). | ||||
| 15 | +- Positivity: $\omega + \alpha\varepsilon^2 + \gamma\varepsilon > 0$ for all ε ⇔ $\gamma^2 < 4\alpha\omega$ (minimum of the quadratic at $\varepsilon = -\gamma/(2\alpha)$ equals $\omega - \gamma^2/(4\alpha)$). | ||||
| 16 | +- Reparameterisation: $\omega = e^{\theta_0}$, $s = \alpha+\beta = \sigma(\theta_1)$, $\alpha = s\,\sigma(\theta_2)$, $\gamma = 2\sqrt{\alpha\omega}\,\tanh(\theta_3)$ (so the positivity condition holds by construction). | ||||
| 17 | +- Admissibility flag: $\omega > 0$, $\alpha > 0$ (strict), $\beta \ge 0$, $\alpha + \beta < 1$, $\gamma^2 < 4\alpha\omega$. | ||||
| 18 | + | ||||
| 19 | +## 4. Nesting and relations | ||||
| 20 | +Nests `garch11` (γ = 0). Linear-asymmetry counterpart of `nagarch11` (news-impact parabola shifted by $-\gamma/(2\alpha)$, a constant shift in ε rather than one proportional to σ). Sentana's general quadratic ARCH includes cross terms not used here. | ||||
| 21 | + | ||||
| 22 | +## 5. Estimation | ||||
| 23 | +Custom MLE (`CustomModel.fit`): L-BFGS-B on θ from three starts (ω, α, γ, β) ∈ {(0.05v, 0.06, −0.3√(0.05v·0.06), 0.90), (0.03v, 0.10, 0, 0.87), (0.1v, 0.1, −0.5√(0.1v·0.1), 0.8)}, Nelder–Mead polish on failure; μ start = sample mean; backcast $s_0$ arch-style. Point estimates only. | ||||
| 24 | + | ||||
| 25 | +## 6. Forecasting | ||||
| 26 | +`QGARCH11.step_forecast`: $\hat\sigma^2_{t+1|t} = \max(\omega + \alpha\varepsilon_t^2 + \gamma\varepsilon_t + \beta\sigma_t^2,\ 10^{-12})$; for $k \ge 2$, $\hat\sigma^2_{t+k|t} = \omega + (\alpha+\beta)\hat\sigma^2_{t+k-1|t}$ (uses $E[\varepsilon_{t+j}\mid\mathcal F_t] = 0$, exact for all four zero-mean laws). Cumulative = sum over k ≤ h. Method: `analytic`. | ||||
| 27 | + | ||||
| 28 | +## 7. Implementation | ||||
| 29 | +- `src/wp46/models/custom.py::QGARCH11` (numba `rec_qgarch`). | ||||
| 30 | +- Cross-check: **none** — QGARCH is in neither arch 8.0.0 nor rugarch 1.5-6; not in `results/metrics/rugarch_crosscheck.json`. The registry marks it `custom (validated vs arch/rugarch)` by the generic `impl` comment, but no library reference exists for this architecture (recorded in `_discrepancies.md`; it is the only scored custom architecture without any library counterpart besides `gas_t11` and `garchx_rv11`). | ||||
| 31 | +- Tests: `tests/unit/test_custom_models.py::test_nesting_and_admissibility[QGARCH11]` (converged, admissible, log-likelihood ≥ GARCH(1,1) − 0.5, positive finite 22-step forecasts). No simulation-recovery test, no rugarch test. | ||||
| 32 | + | ||||
| 33 | +## 8. Known limitations / failure modes | ||||
| 34 | +The positivity bound $\gamma^2 < 4\alpha\omega$ is restrictive when ω is small (highly persistent series): γ is then forced toward zero and the model collapses to GARCH(1,1), so the asymmetry cannot be large on persistent equity series. Admissibility requires α > 0 strictly (α → 0 makes γ → 0 by construction). Floors at 1e-12 silently mask any numerical negativity. | ||||
| 35 | + | ||||
| 36 | +## 9. Computational footprint | ||||
| 37 | +Analytic; 5–7 parameters; same cost order as `nagarch11`. Not in the pilot. | ||||
| 38 | + | ||||
| 39 | +## 10. Literature expectations | ||||
| 40 | +`sentana1995quadratic` shows the quadratic form captures asymmetry with a linear term; the literature matrix lists QGARCH as "custom (if time permits)" and notes the positivity restriction. `hansen2005forecast` do not include QGARCH. Expectation: between GARCH(1,1) and NAGARCH on equities; the positivity constraint is the main practical limitation (H5: more boundary optima). | ||||
added
model_cards/tarch11.md
+39 −0
@@ -0,0 +1,39 @@ | |||||
| 1 | +# Model card — `tarch11` (TGARCH(1,1), Zakoïan threshold on the conditional standard deviation) | ||||
| 2 | + | ||||
| 3 | +## 1. Identity | ||||
| 4 | +- **model_id:** `tarch11` · **family:** asymmetric · **tier:** A · **status:** implemented · **impl:** arch 8.0.0 (`GARCH(p=1, o=1, q=1, power=1.0)`, arch name "TARCH/ZARCH") | ||||
| 5 | +- **Label:** TGARCH(1,1) (Zakoian, threshold on sigma) · **distributions:** normal, t, ged, skewt | ||||
| 6 | +- **Seminal citation:** `zakoian1994threshold` | ||||
| 7 | +- **Other references:** `glosten1993relation` (GJR, the **different** variance-threshold model), `ding1993long` (APARCH nests it with δ = 1), `taylor2008modelling`/`schwert1989why` (absolute-value dynamics), `bollerslev2010glossary` (definition caveat #1 of the literature matrix: "TGARCH ≠ GJR"). | ||||
| 8 | + | ||||
| 9 | +## 2. Definition (arch parameterisation, power = 1) | ||||
| 10 | +$$r_t = \mu + \varepsilon_t,\ \varepsilon_t = \sigma_t z_t,\qquad \sigma_t = \omega + \alpha\,|\varepsilon_{t-1}| + \gamma\,|\varepsilon_{t-1}|\,\mathbb 1\{\varepsilon_{t-1} < 0\} + \beta\,\sigma_{t-1} .$$ | ||||
| 11 | +Mapping to Zakoïan's $\sigma_t = \omega + \alpha^+\varepsilon_{t-1}^+ - \alpha^-\varepsilon_{t-1}^- + \beta\sigma_{t-1}$ ($\varepsilon^+ = \max(\varepsilon,0)$, $\varepsilon^- = \min(\varepsilon,0)$): $\alpha^+ = \alpha$, $\alpha^- = \alpha + \gamma$. arch's recursion runs on $\sigma_t^{1}$ (`fresids = |ε|`), then squares; pre-sample terms use the power-1 backcast (weighted mean of $|\varepsilon|$) and $0.5\times$ it for the asymmetric term. Innovations: normal, t, GED, Hansen skew-t. | ||||
| 12 | + | ||||
| 13 | +## 3. Parameter space and admissibility | ||||
| 14 | +- Parameters: `mu, omega, alpha[1], gamma[1], beta[1]` (+ distribution). | ||||
| 15 | +- arch bounds: $\omega \in [10^{-8}v_1, 10v_1]$ with $v_1 = \overline{|\varepsilon|}$, $\alpha \in [0,1]$, $\gamma \in [-1, 2]$, $\beta \in [0,1]$; constraints $\omega > 0$, $\alpha \ge 0$, $\alpha+\gamma \ge 0$ (so $\alpha^- \ge 0$), $\beta \ge 0$, $\alpha + \tfrac12\gamma + \beta < 1$. The last constraint is arch's generic GARCH constraint applied to power-1 coefficients; it is **not** the second-order stationarity condition of the TGARCH (which involves $E[(\alpha|z| + \gamma|z|\mathbb 1\{z<0\} + \beta)^2] < 1$, see `he1999properties`/`ling2002necessary` for the APARCH family). | ||||
| 16 | +- Admissibility flag: **always `True`** in `ArchModel.fit` (no model-specific check for `tarch11`; only the optimizer constraints apply). Recorded in `_discrepancies.md`. | ||||
| 17 | + | ||||
| 18 | +## 4. Nesting and relations | ||||
| 19 | +APARCH with δ = 1 and $\gamma_{APARCH}$ mapped via $(1-\gamma_A)\alpha_A = \alpha$, $(1+\gamma_A)\alpha_A = \alpha + \gamma$. Nests `avgarch11` (γ = 0). Not nested in and not nesting `gjr11`/`garch11` (different power). Same sign asymmetry as GJR but on σ, which makes the variance response to a shock quadratic in $|\varepsilon|$ with a kink at zero. | ||||
| 20 | + | ||||
| 21 | +## 5. Estimation | ||||
| 22 | +arch `ConstantMean` + `GARCH(1,1,1,power=1.0)` + distribution, SLSQP (`maxiter` 1000), grid starting values (same grid as GJR, target scaled to the power-1 moment), power-1 backcast, ≤ 2 restarts (`ArchModel.fit`). Point estimates only. | ||||
| 23 | + | ||||
| 24 | +## 6. Forecasting | ||||
| 25 | +h = 1: analytic ($\hat\sigma_{t+1|t}$ from the recursion, squared). **h > 1: simulation** (`SPECS["tarch11"]["analytic"] = False`; arch raises for analytic multi-step when power ≠ 2): 2,000 paths of $\sigma_{t+k}$ via `GARCH._simulate_paths` with power 1 (shock $= z\,\sigma$, $|{\rm shock}|$ and its negative part feed the next step), forecast $\hat\sigma^2_{t+k|t}$ = mean over paths of $\sigma_{t+k}^2$. Shocks: for the normal, `np.random.default_rng(seed).standard_normal` with seed = 46 + origin index (reproducible); **for t/GED/skew-t, `rng=None` → arch draws from the fitted distribution with an unseeded generator** (`Distribution(seed=None)` → `default_rng()`), so multi-step forecasts are not bit-reproducible (recorded in `_discrepancies.md`). Cumulative = sum over k ≤ h. Method recorded: `simulation` (h > 1). | ||||
| 26 | + | ||||
| 27 | +## 7. Implementation | ||||
| 28 | +- `src/wp46/models/arch_models.py` (`SPECS["tarch11"]`), arch 8.0.0. | ||||
| 29 | +- Cross-check: rugarch `fGARCH(TGARCH)`-t was fitted on the fixture (`results/metrics/rugarch_crosscheck.json["rugarch"]["tgarch11_t"]`, log-likelihood −3378.2657, converged) **but no arch fit of `tarch11` was computed in `tests/replication/test_rugarch.py`, so no comparison exists** (the `comparison` block has no `tgarch11_t` entry). Gap recorded in `_discrepancies.md`. | ||||
| 30 | +- Tests: none dedicated (not in the pilot). | ||||
| 31 | + | ||||
| 32 | +## 8. Known limitations / failure modes | ||||
| 33 | +Boundary optima at α = 0 (all asymmetry on γ); the power-1 recursion is less conditioned for very small |ε| (percent units mitigate); simulation forecasts carry Monte-Carlo error (2,000 paths) and, for non-normal laws, are not seeded; no admissibility flag beyond the optimizer constraints. | ||||
| 34 | + | ||||
| 35 | +## 9. Computational footprint | ||||
| 36 | +Estimation like GJR; forecasts by simulation (22 × 2,000 draws per origin) — one of the slower forecast steps with `aparch11`, `egarch11`, `avgarch11`. No pilot timing. | ||||
| 37 | + | ||||
| 38 | +## 10. Literature expectations | ||||
| 39 | +`zakoian1994threshold` and `hansen2005forecast` (who include "TGARCH"/"TS-GARCH" power-1 variants) report that absolute-value/threshold specifications are competitive on equities; the matrix flags the definitional ambiguity rather than a ranking. Expectation: close to GJR and APARCH on equities (H1), with the simulation step adding cost (H5). | ||||
added
paper/appendices/data_provenance.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% appendix data_provenance placeholder | ||||
added
paper/appendices/extra_tables.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% appendix extra_tables placeholder | ||||
added
paper/appendices/formulas.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% appendix formulas placeholder | ||||
added
paper/appendices/verification.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% appendix verification placeholder | ||||
added
paper/figures/fig_coverage.pdf
+0 −0
Binary file not shown.
added
paper/figures/fig_timeline.pdf
+0 −0
Binary file not shown.
added
paper/figures/fig_volseries.pdf
+0 −0
Binary file not shown.
added
paper/main.tex
+88 −0
@@ -0,0 +1,88 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +% UQO Working Paper No. 46 — Four Decades of Conditional Volatility Modeling | ||||
| 3 | +% ============================================================================ | ||||
| 4 | +\documentclass[12pt,letterpaper]{article} | ||||
| 5 | +\usepackage[utf8]{inputenc} | ||||
| 6 | +\usepackage[T1]{fontenc} | ||||
| 7 | +\usepackage[english]{babel} | ||||
| 8 | +\usepackage[letterpaper,top=1in,bottom=1in,left=1in,right=1in]{geometry} | ||||
| 9 | +\usepackage{amsmath,amsthm} | ||||
| 10 | +\usepackage{mathtools} | ||||
| 11 | +\allowdisplaybreaks | ||||
| 12 | +\usepackage{newtxtext} | ||||
| 13 | +\usepackage[varvw,cmintegrals,cmbraces]{newtxmath} | ||||
| 14 | +\usepackage{bm} | ||||
| 15 | +\usepackage{dsfont} | ||||
| 16 | +\usepackage{microtype} | ||||
| 17 | +\usepackage{setspace} | ||||
| 18 | +\onehalfspacing | ||||
| 19 | +\usepackage{booktabs,tabularx,multirow,threeparttable,longtable,adjustbox,rotating} | ||||
| 20 | +\usepackage{siunitx} | ||||
| 21 | +\sisetup{input-symbols = {()}, table-format = -1.3, parse-numbers = false} | ||||
| 22 | +\usepackage{graphicx,subcaption,float} | ||||
| 23 | +\usepackage[dvipsnames]{xcolor} | ||||
| 24 | +\usepackage[pdftitle={Four Decades of Conditional Volatility Modeling: A Comprehensive Empirical Benchmark Across Assets, Frequencies, and Market Regimes}, | ||||
| 25 | + pdfauthor={Simon-Pierre Boucher}, colorlinks=true, linkcolor=NavyBlue, citecolor=NavyBlue, urlcolor=NavyBlue, breaklinks=true]{hyperref} | ||||
| 26 | +\usepackage[authoryear,round,semicolon]{natbib} | ||||
| 27 | +\bibliographystyle{aer} | ||||
| 28 | +\usepackage[font=small,labelfont=bf,labelsep=period,justification=justified,singlelinecheck=false]{caption} | ||||
| 29 | +\usepackage{fancyhdr} | ||||
| 30 | +\pagestyle{fancy}\fancyhf{}\renewcommand{\headrulewidth}{0pt}\fancyfoot[C]{\thepage} | ||||
| 31 | +\usepackage{titlesec} | ||||
| 32 | +\titleformat{\section}{\large\bfseries}{\thesection.}{0.5em}{} | ||||
| 33 | +\titleformat{\subsection}{\normalsize\bfseries}{\thesubsection.}{0.5em}{} | ||||
| 34 | +\titleformat{\subsubsection}{\normalsize\itshape}{\thesubsubsection.}{0.5em}{} | ||||
| 35 | +\usepackage[toc,page]{appendix} | ||||
| 36 | +\usepackage{enumitem} | ||||
| 37 | +\setlist{nosep,leftmargin=*} | ||||
| 38 | +\theoremstyle{definition} | ||||
| 39 | +\newtheorem{hypothesis}{Hypothesis} | ||||
| 40 | + | ||||
| 41 | +% ============================================================================ | ||||
| 42 | +% METADATA (numbers.tex is generated by scripts/build_paper.py — never edited by hand) | ||||
| 43 | +% ============================================================================ | ||||
| 44 | +\input{numbers} | ||||
| 45 | +\newcommand{\WPnumber}{46} | ||||
| 46 | +\newcommand{\WPtitle}{Four Decades of Conditional Volatility Modeling: A Comprehensive Empirical Benchmark Across Assets, Frequencies, and Market Regimes} | ||||
| 47 | +\newcommand{\WPsubtitle}{Does Anything Beat GARCH(1,1) Once Information Sets, Failures and Compute Are Priced In?} | ||||
| 48 | +\newcommand{\WPdate}{November 2026} | ||||
| 49 | +\newcommand{\WPversion}{1.0} | ||||
| 50 | +\newcommand{\WPabstract}{\input{sections/abstract}} | ||||
| 51 | +\newcommand{\WPkeywords}{volatility forecasting, GARCH, realized volatility, model confidence set, pre-registration, forecast evaluation, tail risk} | ||||
| 52 | +\newcommand{\WPjel}{C22, C52, C53, C58, G17} | ||||
| 53 | +\newcommand{\WPauthor}{Simon-Pierre Boucher} | ||||
| 54 | +\newcommand{\WPaffiliation}{Département des sciences administratives\\Université du Québec en Outaouais} | ||||
| 55 | +\newcommand{\WPemail}{simon-pierre.boucher@uqo.ca} | ||||
| 56 | +\newcommand{\WPaddress}{Gatineau -- Pavillon Alexandre-Taché\\283, boulevard Alexandre-Taché\\Gatineau, Québec, Canada J9A 1L8} | ||||
| 57 | + | ||||
| 58 | +% --- Notation --- | ||||
| 59 | +\newcommand{\E}{\mathbb{E}} | ||||
| 60 | +\newcommand{\Var}{\mathrm{Var}} | ||||
| 61 | +\newcommand{\Prob}{\mathbb{P}} | ||||
| 62 | +\newcommand{\ind}[1]{\mathds{1}\!\left[#1\right]} | ||||
| 63 | +\newcommand{\RV}{\mathrm{RV}} | ||||
| 64 | +\newcommand{\QLIKE}{\mathrm{QLIKE}} | ||||
| 65 | +\newcommand{\F}{\mathcal{F}} | ||||
| 66 | + | ||||
| 67 | +\begin{document} | ||||
| 68 | +\input{sections/titlepage} | ||||
| 69 | +\input{sections/introduction} | ||||
| 70 | +\input{sections/literature} | ||||
| 71 | +\input{sections/taxonomy} | ||||
| 72 | +\input{sections/data} | ||||
| 73 | +\input{sections/design} | ||||
| 74 | +\input{sections/results_daily} | ||||
| 75 | +\input{sections/results_realized} | ||||
| 76 | +\input{sections/results_tail_multivariate} | ||||
| 77 | +\input{sections/results_heterogeneity} | ||||
| 78 | +\input{sections/frontier} | ||||
| 79 | +\input{sections/conclusion} | ||||
| 80 | +\bibliography{references} | ||||
| 81 | +\clearpage | ||||
| 82 | +\begin{appendices} | ||||
| 83 | +\input{appendices/formulas} | ||||
| 84 | +\input{appendices/data_provenance} | ||||
| 85 | +\input{appendices/verification} | ||||
| 86 | +\input{appendices/extra_tables} | ||||
| 87 | +\end{appendices} | ||||
| 88 | +\end{document} | ||||
added
paper/numbers.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% generated by scripts/build_paper.py | ||||
added
paper/sections/abstract.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% abstract — generated draft placeholder (to be written after the benchmark) | ||||
added
paper/sections/conclusion.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% conclusion — generated draft placeholder (to be written after the benchmark) | ||||
added
paper/sections/data.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% data — generated draft placeholder (to be written after the benchmark) | ||||
added
paper/sections/design.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% design — generated draft placeholder (to be written after the benchmark) | ||||
added
paper/sections/frontier.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% frontier — generated draft placeholder (to be written after the benchmark) | ||||
added
paper/sections/introduction.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% introduction — generated draft placeholder (to be written after the benchmark) | ||||
added
paper/sections/literature.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% literature — generated draft placeholder (to be written after the benchmark) | ||||
added
paper/sections/results_daily.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% results_daily — generated draft placeholder (to be written after the benchmark) | ||||
added
paper/sections/results_heterogeneity.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% results_heterogeneity — generated draft placeholder (to be written after the benchmark) | ||||
added
paper/sections/results_realized.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% results_realized — generated draft placeholder (to be written after the benchmark) | ||||
added
paper/sections/results_tail_multivariate.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% results_tail_multivariate — generated draft placeholder (to be written after the benchmark) | ||||
added
paper/sections/taxonomy.tex
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +% taxonomy — generated draft placeholder (to be written after the benchmark) | ||||
added
results/manifests/figure_audit.csv
+5 −0
@@ -0,0 +1,5 @@ | |||||
| 1 | +figure,sources,n,note | ||||
| 2 | +fig_timeline.pdf,configs/model_registry.yaml,26, | ||||
| 3 | +fig_coverage.pdf,results/manifests/panels_manifest.json,42, | ||||
| 4 | +fig_volseries.pdf,panels/SPY.parquet;panels/CL.parquet;panels/EURUSD.parquet;panels/BTC.parquet,4, | ||||
| 5 | +fig_timeline.pdf,configs/model_registry.yaml,26, | ||||
added
results/manifests/ingest_manifest.json
+7930 −0
Large diff (7,931 lines) is not loaded by default to keep the page fast.Load diff
added
results/manifests/panels_manifest.json
+464 −0
Large diff (465 lines) is not loaded by default to keep the page fast.Load diff
added
scripts/analyze_tier_c.py
+54 −0
Large diff (54 lines) is not loaded by default to keep the page fast.Load diff
added
scripts/build_paper.py
+120 −0
Large diff (120 lines) is not loaded by default to keep the page fast.Load diff
added
src/wp46/reporting/__init__.py
+0 −0
Large diff (0 lines) is not loaded by default to keep the page fast.Load diff
added
src/wp46/reporting/figures.py
+234 −0
Large diff (234 lines) is not loaded by default to keep the page fast.Load diff
added
src/wp46/reporting/plotstyle.py
+40 −0
Large diff (40 lines) is not loaded by default to keep the page fast.Load diff
added
src/wp46/reporting/tables.py
+42 −0
Large diff (43 lines) is not loaded by default to keep the page fast.Load diff