SPB Git

Repository Public Research preview

Commit

WP46: extension-vs-parent heatmap generator, extensions section slot

Simon-Pierre Boucher committed · Nov 9, 2026 parent b2f3f61
4 changed files +43 −0 Browse files
modified paper/main.tex +1 −0
@@ -76,6 +76,7 @@
76 76 \input{sections/results_tail_multivariate}
77 77 \input{sections/results_heterogeneity}
78 78 \input{sections/frontier}
79 +\input{sections/results_extensions}
79 80 \input{sections/conclusion}
80 81 \bibliography{references}
81 82 \clearpage
added paper/sections/results_extensions.tex +1 −0
@@ -0,0 +1 @@
1 +% extensions section — written after the extension run
modified scripts/build_paper.py +2 −0
@@ -141,6 +141,8 @@ def main() -> None:
141 141 TB.regime_table(per_symbol, rep_specs, labels, ["vol_tercile=low", "vol_tercile=mid", "vol_tercile=high", "prev_sign=neg", "prev_sign=pos", "episode=covid", "episode=rate_shock_2022", "episode=tariff_shock_2025"], tdir / "tab_regimes_h22.tex", 22)
142 142 if len(TR):
143 143 TB.tailrisk_table(TR, [s for s in rep_specs] + [s for s in specs_all if s.startswith("garch11__") and s not in rep_specs], labels, tdir / "tab_tailrisk.tex")
144 + if any(sp.split("__")[0] in F.EXT_PARENT for sp in specs_all):
145 + F.extension_heatmap(per_symbol, 1, F.FIG / "fig_extensions_h1.pdf"); F.extension_heatmap(per_symbol, 22, F.FIG / "fig_extensions_h22.pdf")
144 146 # pooled by asset class for the representative specs
145 147 P[P.spec_id.isin(rep_specs)].to_csv(ROOT / "results" / "tables" / f"pooled_by_class_{a.run}_{a.period}.csv", index=False)
146 148 # --- numbers.tex
modified src/wp46/reporting/figures.py +39 −0
@@ -303,3 +303,42 @@ def regime_profile(per_symbol: dict, specs: list[str], path: Path, h: int = 1) -
303 303 ax.set_ylabel(f"Pooled QLIKE ratio to GARCH(1,1)-N, h = {h}"); ax.legend(ncol=3, fontsize=6)
304 304 ps.save(fig, path); _audit(path.name, ["results/metrics/analysis_*/per_symbol/*.json"], len(specs) * len(keys))
305 305 return path
306 +
307 +
308 +# ----------------------------------------------------------------------------- 13. extensions vs parents (exploratory)
309 +EXT_PARENT = {"stgarch11": "gjr11", "betategarch11": "egarch11", "garch_midas": "garch11", "hygarch11": "figarch11",
310 + "fiaparch11": "aparch11", "fiegarch11": "egarch11", "realegarch11": "realgarch11"}
311 +
312 +
313 +def extension_heatmap(per_symbol: dict, h: int, path: Path, dist_pref=("t", "normal")) -> Path:
314 + """Instruments x (extension, parent) pairs: QLIKE ratio of the extension to its parent (same innovation law), log colour scale."""
315 + syms = sorted(per_symbol, key=lambda s: (CLASS_ORDER.index(CLASS_OF[s]), s))
316 + pairs = []
317 + for ext, par in EXT_PARENT.items():
318 + for d in dist_pref:
319 + e_id, p_id = f"{ext}__{d}__w1000_r5", f"{par}__{d}__w1000_r5"
320 + if any(e_id in per_symbol[s]["horizons"][str(h)]["specs"] and p_id in per_symbol[s]["horizons"][str(h)]["specs"] for s in syms):
321 + pairs.append((e_id, p_id)); break
322 + M = np.full((len(syms), len(pairs)), np.nan)
323 + for i, s in enumerate(syms):
324 + d = per_symbol[s]["horizons"][str(h)]["specs"]
325 + for j, (e_id, p_id) in enumerate(pairs):
326 + re_, rp = d.get(e_id, {}).get("ratio", np.nan), d.get(p_id, {}).get("ratio", np.nan)
327 + if np.isfinite(re_) and np.isfinite(rp) and rp > 0:
328 + M[i, j] = re_ / rp
329 + fig, ax = plt.subplots(figsize=(ps.W1 * 1.4, 0.16 * len(syms) + 1.5))
330 + im = ax.imshow(np.log(M), cmap=ps.DIV, vmin=np.log(0.8), vmax=np.log(1.25), aspect="auto")
331 + for i in range(len(syms)):
332 + for j in range(len(pairs)):
333 + if np.isfinite(M[i, j]):
334 + ax.text(j, i, f"{M[i, j]:.2f}", ha="center", va="center", fontsize=4.8, color=ps.INK)
335 + ax.set_xticks(range(len(pairs))); ax.set_xticklabels([f"{spec_label(e)}\nvs {spec_label(p)}" for e, p in pairs], rotation=90, fontsize=5.5)
336 + ax.set_yticks(range(len(syms))); ax.set_yticklabels(syms, fontsize=5.5)
337 + for k in range(1, len(syms)):
338 + if CLASS_OF[syms[k]] != CLASS_OF[syms[k - 1]]:
339 + ax.axhline(k - 0.5, color=ps.INK, lw=0.6)
340 + cb = fig.colorbar(im, ax=ax, fraction=0.03, pad=0.01); cb.set_ticks(np.log([0.8, 0.9, 1.0, 1.1, 1.25])); cb.set_ticklabels(["0.80", "0.90", "1.00", "1.10", "1.25"])
341 + cb.set_label("QLIKE ratio, extension / parent")
342 + ax.grid(False); ax.set_title(f"Post-registration extensions vs their parents, h = {h} (exploratory)", loc="left", fontsize=8)
343 + ps.save(fig, path); _audit(path.name, ["results/metrics/analysis_*/per_symbol/*.json"], int(np.isfinite(M).sum()), "exploratory")
344 + return path
306 345
Menu

Theme