Ultron28 commited on
Commit
f56e349
·
verified ·
1 Parent(s): fe5fe45

Upload scripts/generate_paper_figures.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. scripts/generate_paper_figures.py +162 -157
scripts/generate_paper_figures.py CHANGED
@@ -2,8 +2,9 @@
2
  ⚡ ULTRON Systems // 100% Deterministic Empirical Figure Generator (300 DPI)
3
  Zero synthetic data. Reads directly from:
4
  - logs/pretraining_telemetry_verified.json (855 real logged pre-training steps)
5
- - logs/oos_evaluation_results.json (95,040-window 27-shard OOS benchmark)
6
- - logs/tier1_verified_audit.json (Multi-epoch, Frobenius drift, 7-horizon ablation, causal backtest)
 
7
  """
8
  import os
9
  import json
@@ -17,21 +18,20 @@ plt.style.use('seaborn-v0_8-whitegrid' if 'seaborn-v0_8-whitegrid' in plt.style.
17
  mpl.rcParams['font.family'] = 'serif'
18
  mpl.rcParams['font.size'] = 9.5
19
  mpl.rcParams['axes.labelsize'] = 10
20
- mpl.rcParams['axes.titlesize'] = 11
21
  mpl.rcParams['xtick.labelsize'] = 8.5
22
  mpl.rcParams['ytick.labelsize'] = 8.5
23
- mpl.rcParams['legend.fontsize'] = 8
24
  mpl.rcParams['figure.titlesize'] = 12
25
 
26
  with open("logs/pretraining_telemetry_verified.json") as f:
27
  pre_data = json.load(f)
28
 
29
- with open("logs/oos_evaluation_results.json") as f:
30
- oos_27 = json.load(f)
31
-
32
- with open("logs/tier1_verified_audit.json") as f:
33
  audit = json.load(f)
34
 
 
 
35
  # =========================================================================
36
  # Figure 1: REAL Empirical Pre-Training Telemetry (855 Logged Steps)
37
  # =========================================================================
@@ -41,7 +41,6 @@ steps = np.array([r["step"] for r in records])
41
  t_loss = np.array([r["total_loss"] for r in records])
42
  d_acc = np.array([r["dir_acc_total"] for r in records])
43
 
44
- # Compute strictly causal 25-point moving average for trend visibility alongside raw points
45
  def causal_sma(arr, w=25):
46
  out = np.zeros_like(arr, dtype=np.float64)
47
  for i in range(len(arr)):
@@ -80,60 +79,53 @@ fig.savefig("papers/figures/fig1_pretraining_curves.png", dpi=300, bbox_inches='
80
  plt.close()
81
 
82
  # =========================================================================
83
- # Figure 2: 27-Shard OOS Benchmark + Epoch 1/2/3 Progression vs Baselines
84
  # =========================================================================
85
- print("Rendering Figure 2 from real OOS benchmark & Epoch progression...")
86
- horizons = ["1m", "3m", "5m", "15m", "30m", "60m", "1d"]
87
- acc_2024 = [oos_27["static_oos_zero_shot"]["2024"]["metrics"]["per_horizon"][h]["dir_acc"] for h in horizons]
88
- acc_2025 = [oos_27["static_oos_zero_shot"]["2025"]["metrics"]["per_horizon"][h]["dir_acc"] for h in horizons]
89
- acc_2026 = [oos_27["static_oos_zero_shot"]["2026"]["metrics"]["per_horizon"][h]["dir_acc"] for h in horizons]
90
-
91
  fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(11, 4.0), dpi=300)
92
 
 
 
 
 
 
 
 
93
  x = np.arange(len(horizons))
94
- w = 0.25
95
- ax1.bar(x - w, acc_2024, w, label='2024 OOS (42,240 win)', color='#0284C7', edgecolor='black', lw=0.5)
96
- ax1.bar(x, acc_2025, w, label='2025 OOS (42,240 win)', color='#0D9488', edgecolor='black', lw=0.5)
97
- ax1.bar(x + w, acc_2026, w, label='2026 OOS (10,560 win)', color='#D97706', edgecolor='black', lw=0.5)
98
- ax1.axhline(50.0, color='#E11D48', linestyle='--', lw=1.2, label='Random Walk Null (50.0%)')
99
  ax1.set_xticks(x)
100
  ax1.set_xticklabels(horizons)
101
- ax1.set_ylim(46.0, 56.0)
102
- ax1.set_ylabel('Directional Accuracy (%)')
103
- ax1.set_title('(a) 95,040-Window Zero-Shot OOS Accuracy by Horizon')
104
  ax1.legend(loc='upper right', frameon=True)
105
  ax1.grid(axis='y', alpha=0.3)
106
 
107
- # Panel (b): Epoch 1 vs Epoch 2 vs Epoch 3 vs Baselines (2024 OOS Cohort)
108
- models_lbl = ["Always\nLong", "1-Bar\nMom", "EMA\n12/26", "5-Bar\nRev", "Conformer\nEpoch 1", "Conformer\nEpoch 2", "Conformer\nEpoch 3"]
109
- raw_vals = [
110
- audit["quantitative_baselines_oos"]["2024"]["Always_Long_Drift"]["overall_raw_dir_acc"],
111
- audit["quantitative_baselines_oos"]["2024"]["Momentum_1Bar"]["overall_raw_dir_acc"],
112
- audit["quantitative_baselines_oos"]["2024"]["EMA_12_26_Crossover"]["overall_raw_dir_acc"],
113
- audit["quantitative_baselines_oos"]["2024"]["MeanReversion_5Bar"]["overall_raw_dir_acc"],
114
- audit["multi_checkpoint_oos_audit"]["epoch1"]["2024"]["overall_raw_dir_acc"],
115
- audit["multi_checkpoint_oos_audit"]["epoch2"]["2024"]["overall_raw_dir_acc"],
116
- audit["multi_checkpoint_oos_audit"]["epoch3"]["2024"]["overall_raw_dir_acc"]
117
- ]
118
- nz_vals = [
119
- audit["quantitative_baselines_oos"]["2024"]["Always_Long_Drift"]["overall_nonzero_dir_acc"],
120
- audit["quantitative_baselines_oos"]["2024"]["Momentum_1Bar"]["overall_nonzero_dir_acc"],
121
- audit["quantitative_baselines_oos"]["2024"]["EMA_12_26_Crossover"]["overall_nonzero_dir_acc"],
122
- audit["quantitative_baselines_oos"]["2024"]["MeanReversion_5Bar"]["overall_nonzero_dir_acc"],
123
- audit["multi_checkpoint_oos_audit"]["epoch1"]["2024"]["overall_nonzero_dir_acc"],
124
- audit["multi_checkpoint_oos_audit"]["epoch2"]["2024"]["overall_nonzero_dir_acc"],
125
- audit["multi_checkpoint_oos_audit"]["epoch3"]["2024"]["overall_nonzero_dir_acc"]
126
- ]
127
- xb = np.arange(len(models_lbl))
128
- ax2.bar(xb - 0.18, raw_vals, 0.35, label='Raw Directional Acc (%)', color='#1E3A8A', edgecolor='black', lw=0.5)
129
- ax2.bar(xb + 0.18, nz_vals, 0.35, label='Non-Zero Strict Acc (%)', color='#38BDF8', edgecolor='black', lw=0.5)
130
- ax2.axhline(50.0, color='#E11D48', linestyle='--', lw=1.2)
131
  ax2.set_xticks(xb)
132
- ax2.set_xticklabels(models_lbl, fontsize=7.5)
133
- ax2.set_ylim(48.0, 53.2)
134
- ax2.set_ylabel('7-Horizon Mean Accuracy (%)')
135
- ax2.set_title('(b) Epoch Progression vs. Classical Baselines (2024 OOS)')
136
- ax2.legend(loc='upper left', frameon=True)
137
  ax2.grid(axis='y', alpha=0.3)
138
 
139
  plt.tight_layout()
@@ -141,146 +133,159 @@ fig.savefig("papers/figures/fig2_oos_directional_accuracy.png", dpi=300, bbox_in
141
  plt.close()
142
 
143
  # =========================================================================
144
- # Figure 3: Exact Frobenius Weight Drift & Walk-Forward ROC-AUC / IC Transfer
145
  # =========================================================================
146
- print("Rendering Figure 3 from real Frobenius weight drift & walk-forward telemetry...")
147
  fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(11, 4.0), dpi=300)
148
 
149
- modules = ["Return\nHead", "Conformer\nBackbone", "Directional\nHead", "Inception\nTokenizer"]
150
- mod_keys = ["return_regression_head", "norms_and_aux", "directional_class_head", "inception_tokenizer"]
151
 
152
- drift_ep1_ep2 = [audit["weight_drift_frobenius_audit"]["epoch1_to_epoch2"]["by_module"][k]["rel_frobenius_pct"] for k in mod_keys]
153
- drift_ep2_ep3 = [audit["weight_drift_frobenius_audit"]["epoch2_to_epoch3"]["by_module"][k]["rel_frobenius_pct"] for k in mod_keys]
154
- drift_wf24 = [audit["weight_drift_frobenius_audit"]["epoch3_to_wf2024"]["by_module"][k]["rel_frobenius_pct"] for k in mod_keys]
155
- drift_wf25 = [audit["weight_drift_frobenius_audit"]["epoch3_to_wf2025"]["by_module"][k]["rel_frobenius_pct"] for k in mod_keys]
 
156
 
157
  xm = np.arange(len(modules))
158
- wm = 0.2
159
- ax1.bar(xm - 1.5*wm, drift_ep1_ep2, wm, label='Pre-Train Ep1→Ep2 (10.00% Global)', color='#64748B', edgecolor='black', lw=0.5)
160
- ax1.bar(xm - 0.5*wm, drift_ep2_ep3, wm, label='Pre-Train Ep2→Ep3 (5.73% Global)', color='#94A3B8', edgecolor='black', lw=0.5)
161
- ax1.bar(xm + 0.5*wm, drift_wf24, wm, label='Walk-Forward Ep3→WF24 (0.54% Global)', color='#0EA5E9', edgecolor='black', lw=0.5)
162
- ax1.bar(xm + 1.5*wm, drift_wf25, wm, label='Walk-Forward Ep3→WF25 (0.79% Global)', color='#0F766E', edgecolor='black', lw=0.5)
163
- ax1.set_yscale('log')
164
  ax1.set_xticks(xm)
165
- ax1.set_xticklabels(modules)
166
- ax1.set_ylabel('Relative Frobenius Drift ||ΔW||_F / ||W||_F (%)')
167
- ax1.set_title('(a) Layer-Wise Parameter Drift Hierarchy (Log Scale)')
168
- ax1.legend(loc='upper left', frameon=True, fontsize=7.5)
169
- ax1.grid(True, which="both", alpha=0.3)
170
-
171
- # Panel (b): 2025 OOS ROC-AUC across Checkpoints (Epoch 1, Epoch 2, Epoch 3, WF-2024, WF-2025)
172
- ckpts = ["Epoch 1\n(Zero-Shot)", "Epoch 2\n(Zero-Shot)", "Epoch 3\n(Zero-Shot)", "WF-2024\n(Online)", "WF-2025\n(Online)"]
173
- ck_keys = ["epoch1", "epoch2", "epoch3", "wf2024", "wf2025"]
174
- aucs_2025 = [audit["multi_checkpoint_oos_audit"][k]["2025"]["overall_roc_auc"] for k in ck_keys]
175
- aucs_2024 = [audit["multi_checkpoint_oos_audit"][k]["2024"]["overall_roc_auc"] for k in ck_keys]
176
-
177
- xc = np.arange(len(ckpts))
178
- ax2.plot(xc, aucs_2024, marker='o', lw=2.0, color='#1D4ED8', label='2024 OOS Mean ROC-AUC')
179
- ax2.plot(xc, aucs_2025, marker='s', lw=2.0, color='#0D9488', linestyle='--', label='2025 OOS Mean ROC-AUC')
180
- ax2.axhline(0.5000, color='#E11D48', linestyle=':', lw=1.2, label='Random Classifier (0.5000)')
 
 
 
 
 
181
  ax2.set_xticks(xc)
182
- ax2.set_xticklabels(ckpts, fontsize=8)
183
- ax2.set_ylim(0.508, 0.520)
184
  ax2.set_ylabel('7-Horizon Mean ROC-AUC')
185
- ax2.set_title('(b) Out-of-Sample ROC-AUC Across Checkpoints')
186
- ax2.legend(loc='lower right', frameon=True)
187
- ax2.grid(True, alpha=0.3)
188
 
189
  plt.tight_layout()
190
  fig.savefig("papers/figures/fig3_walk_forward_comparison.png", dpi=300, bbox_inches='tight', pad_inches=0.1)
191
  plt.close()
192
 
193
  # =========================================================================
194
- # Figure 4: Mechanistic Inception Kernel Ablation (Continuous L2 & Accuracy)
195
  # =========================================================================
196
- print("Rendering Figure 4 from real 7-horizon mechanistic kernel ablation...")
197
  fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(11, 4.0), dpi=300)
198
 
199
- ab_branches = ["Mask_K3", "Mask_K7", "Mask_K15", "Mask_K31", "Mask_K63", "Mask_K127", "Mask_Micro_K3_K7", "Mask_Meso_K15_K31", "Mask_Macro_K63_K127"]
200
- ab_labels = ["K=3", "K=7", "K=15", "K=31", "K=63", "K=127", "Micro\n(3,7)", "Meso\n(15,31)", "Macro\n(63,127)"]
 
201
 
202
- logit_l2_1m = [audit["mechanistic_kernel_ablation_7h"]["ablations"][b]["per_horizon"]["1m"]["logit_l2_perturbation_pct"] for b in ab_branches]
203
- logit_l2_15m = [audit["mechanistic_kernel_ablation_7h"]["ablations"][b]["per_horizon"]["15m"]["logit_l2_perturbation_pct"] for b in ab_branches]
204
- logit_l2_1d = [audit["mechanistic_kernel_ablation_7h"]["ablations"][b]["per_horizon"]["1d"]["logit_l2_perturbation_pct"] for b in ab_branches]
205
 
206
- xa = np.arange(len(ab_labels))
207
- wa = 0.26
208
- ax1.bar(xa - wa, logit_l2_1m, wa, label='1m Horizon Logit L2 Shift (%)', color='#0284C7', edgecolor='black', lw=0.5)
209
- ax1.bar(xa, logit_l2_15m, wa, label='15m Horizon Logit L2 Shift (%)', color='#F59E0B', edgecolor='black', lw=0.5)
210
- ax1.bar(xa + wa, logit_l2_1d, wa, label='1d Horizon Logit L2 Shift (%)', color='#10B981', edgecolor='black', lw=0.5)
211
  ax1.set_xticks(xa)
212
- ax1.set_xticklabels(ab_labels, fontsize=7.5)
213
- ax1.set_ylabel('Relative Logit Perturbation ||Δz||_2 / ||z||_2 (%)')
214
- ax1.set_title('(a) Continuous Logit Sensitivity by Receptive Field')
215
- ax1.legend(loc='upper left', frameon=True)
216
  ax1.grid(axis='y', alpha=0.3)
217
 
218
- # Panel (b): Return Prediction L2 Shift (%) vs Mean Logit L2 Shift (%)
219
- mean_l2_z = [audit["mechanistic_kernel_ablation_7h"]["ablations"][b]["mean_logit_l2_perturbation_pct"] for b in ab_branches]
220
- mean_l2_r = [audit["mechanistic_kernel_ablation_7h"]["ablations"][b]["mean_return_l2_perturbation_pct"] for b in ab_branches]
221
-
222
- ax2.bar(xa - 0.18, mean_l2_z, 0.35, label='Mean Logit L2 Shift (%)', color='#4F46E5', edgecolor='black', lw=0.5)
223
- ax2.bar(xa + 0.18, mean_l2_r, 0.35, label='Mean Return Forecast L2 Shift (%)', color='#E11D48', edgecolor='black', lw=0.5)
224
- ax2.set_xticks(xa)
225
- ax2.set_xticklabels(ab_labels, fontsize=7.5)
226
- ax2.set_ylabel('7-Horizon Mean Relative L2 Perturbation (%)')
227
- ax2.set_title('(b) Dual-Head Perturbation Magnitude Under Masking')
228
- ax2.legend(loc='upper left', frameon=True)
229
- ax2.grid(axis='y', alpha=0.3)
 
 
 
 
 
 
 
230
 
231
  plt.tight_layout()
232
  fig.savefig("papers/figures/fig4_kernel_ablation.png", dpi=300, bbox_inches='tight', pad_inches=0.1)
233
  plt.close()
234
 
235
  # =========================================================================
236
- # Figure 5: Strictly Causal Chronological Execution Backtest & Hurdle Filtering
237
  # =========================================================================
238
- print("Rendering Figure 5 from real causal chronological backtest...")
239
  fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(11, 4.0), dpi=300)
240
 
241
- taus_lbl = ["0.0σ\n(100% Trd)", "0.5σ\n(~55% Trd)", "1.0σ\n(~20% Trd)", "1.5σ\n(~5% Trd)", "2.0σ\n(~1% Trd)"]
242
- tau_keys = ["tau_0.0sigma", "tau_0.5sigma", "tau_1.0sigma", "tau_1.5sigma", "tau_2.0sigma"]
243
-
244
- # Panel (a): 2025 60m & 2026 15m Breakeven Fee Capacitance (bps) vs Confidence Hurdle
245
- be_2025_60m = [audit["causal_chronological_backtest"]["2025"]["60m"][tk]["breakeven_fee_bps"] for tk in tau_keys]
246
- be_2026_15m = [audit["causal_chronological_backtest"]["2026"]["15m"][tk]["breakeven_fee_bps"] for tk in tau_keys]
247
- be_2024_5m = [audit["causal_chronological_backtest"]["2024"]["5m"][tk]["breakeven_fee_bps"] for tk in tau_keys]
248
-
249
- xt = np.arange(len(taus_lbl))
250
- ax1.plot(xt, be_2025_60m, marker='o', lw=2.0, color='#0D9488', label='2025 60m Horizon Breakeven Fee')
251
- ax1.plot(xt, be_2026_15m, marker='s', lw=2.0, color='#2563EB', label='2026 15m Horizon Breakeven Fee')
252
- ax1.plot(xt, be_2024_5m, marker='^', lw=2.0, color='#D97706', label='2024 5m Horizon Breakeven Fee')
253
- ax1.axhline(1.0, color='#E11D48', linestyle='--', lw=1.2, label='Institutional Prime Fee (1.0 bps)')
254
- ax1.set_xticks(xt)
255
- ax1.set_xticklabels(taus_lbl, fontsize=8)
256
- ax1.set_ylabel('Breakeven One-Way Fee Capacitance (bps)')
257
- ax1.set_title('(a) Causal Confidence Hurdle (τ) vs. Breakeven Fee')
258
- ax1.legend(loc='upper left', frameon=True)
259
- ax1.grid(True, alpha=0.3)
 
260
 
261
- # Panel (b): Net Post-Friction Sharpe Ratio across Slippage Grid (0, 1, 2, 5 bps)
262
- bps_grid = [0.0, 1.0, 2.0, 5.0]
263
- bps_keys = ["0.0bps", "1.0bps", "2.0bps", "5.0bps"]
264
-
265
- sh_2025_1d_t0 = [audit["causal_chronological_backtest"]["2025"]["1d"]["tau_0.0sigma"]["slippage_grid"][bk]["sharpe"] for bk in bps_keys]
266
- sh_2025_60m_t15 = [audit["causal_chronological_backtest"]["2025"]["60m"]["tau_1.5sigma"]["slippage_grid"][bk]["sharpe"] for bk in bps_keys]
267
- sh_2024_5m_t20 = [audit["causal_chronological_backtest"]["2024"]["5m"]["tau_2.0sigma"]["slippage_grid"][bk]["sharpe"] for bk in bps_keys]
268
- sh_2026_15m_t20 = [audit["causal_chronological_backtest"]["2026"]["15m"]["tau_2.0sigma"]["slippage_grid"][bk]["sharpe"] for bk in bps_keys]
269
-
270
- ax2.plot(bps_grid, sh_2024_5m_t20, marker='^', lw=2.0, color='#D97706', label='2024 5m (τ=2.0σ, 99.3% Turn. Saved)')
271
- ax2.plot(bps_grid, sh_2025_1d_t0, marker='o', lw=2.0, color='#1D4ED8', label='2025 1d (Unfiltered τ=0.0σ)')
272
- ax2.plot(bps_grid, sh_2025_60m_t15, marker='s', lw=2.0, color='#0D9488', label='2025 60m (τ=1.5σ, 94.4% Turn. Saved)')
273
- ax2.plot(bps_grid, sh_2026_15m_t20, marker='D', lw=2.0, color='#7C3AED', label='2026 15m (τ=2.0σ, 98.9% Turn. Saved)')
274
- ax2.axhline(0.0, color='black', linestyle='--', lw=1.1, label='Breakeven Sharpe (0.0)')
275
- ax2.set_xlabel('One-Way Execution Slippage / Fee (Basis Points)')
276
- ax2.set_ylabel('Annualized Net Sharpe Ratio (Causal Chronological)')
277
- ax2.set_title('(b) Post-Friction Net Sharpe Survival Under Hurdle')
278
- ax2.legend(loc='lower left', frameon=True, fontsize=7.5)
 
279
  ax2.grid(True, alpha=0.3)
280
 
281
  plt.tight_layout()
282
  fig.savefig("papers/figures/fig5_slippage_friction_curve.png", dpi=300, bbox_inches='tight', pad_inches=0.1)
283
  plt.close()
284
 
285
- print("✅ All 5 deterministic empirical figures rendered at 300 DPI!")
286
-
 
2
  ⚡ ULTRON Systems // 100% Deterministic Empirical Figure Generator (300 DPI)
3
  Zero synthetic data. Reads directly from:
4
  - logs/pretraining_telemetry_verified.json (855 real logged pre-training steps)
5
+ - logs/defensible_tier1_audit.json (Stratified 15-ticker contiguous OOS & Pre-2024 Stress audit,
6
+ exact global cosine similarities, 1m return-magnitude buckets, paired bootstrap CIs,
7
+ mean-ablation + random-channel controls, and non-overlapping state-turnover backtests)
8
  """
9
  import os
10
  import json
 
18
  mpl.rcParams['font.family'] = 'serif'
19
  mpl.rcParams['font.size'] = 9.5
20
  mpl.rcParams['axes.labelsize'] = 10
21
+ mpl.rcParams['axes.titlesize'] = 10.5
22
  mpl.rcParams['xtick.labelsize'] = 8.5
23
  mpl.rcParams['ytick.labelsize'] = 8.5
24
+ mpl.rcParams['legend.fontsize'] = 7.8
25
  mpl.rcParams['figure.titlesize'] = 12
26
 
27
  with open("logs/pretraining_telemetry_verified.json") as f:
28
  pre_data = json.load(f)
29
 
30
+ with open("logs/defensible_tier1_audit.json") as f:
 
 
 
31
  audit = json.load(f)
32
 
33
+ horizons = ["1m", "3m", "5m", "15m", "30m", "60m", "1d"]
34
+
35
  # =========================================================================
36
  # Figure 1: REAL Empirical Pre-Training Telemetry (855 Logged Steps)
37
  # =========================================================================
 
41
  t_loss = np.array([r["total_loss"] for r in records])
42
  d_acc = np.array([r["dir_acc_total"] for r in records])
43
 
 
44
  def causal_sma(arr, w=25):
45
  out = np.zeros_like(arr, dtype=np.float64)
46
  for i in range(len(arr)):
 
79
  plt.close()
80
 
81
  # =========================================================================
82
+ # Figure 2: 1m Base-Rate / Flat-Bar Decomposition, Return Buckets & Baselines
83
  # =========================================================================
84
+ print("Rendering Figure 2 from 1m return-magnitude buckets & multi-horizon ROC-AUC...")
 
 
 
 
 
85
  fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(11, 4.0), dpi=300)
86
 
87
+ # Panel (a): All-Bar ROC-AUC vs Strict Non-Zero ROC-AUC across Horizons (2024 OOS, N=8,044)
88
+ ep3_24 = audit["multi_checkpoint_oos_and_stress_audit"]["epoch3"]["2024"]["per_horizon"]
89
+ ep3_26 = audit["multi_checkpoint_oos_and_stress_audit"]["epoch3"]["2026"]["per_horizon"]
90
+ auc_all_24 = [ep3_24[h]["roc_auc"] for h in horizons]
91
+ auc_nz_24 = [ep3_24[h]["nonzero_roc_auc"] for h in horizons]
92
+ auc_nz_26 = [ep3_26[h]["nonzero_roc_auc"] for h in horizons]
93
+
94
  x = np.arange(len(horizons))
95
+ w = 0.26
96
+ ax1.bar(x - w, auc_all_24, w, label='2024 All-Bar ROC-AUC', color='#0284C7', edgecolor='black', lw=0.5)
97
+ ax1.bar(x, auc_nz_24, w, label='2024 Non-Zero (y≠0) ROC-AUC', color='#0D9488', edgecolor='black', lw=0.5)
98
+ ax1.bar(x + w, auc_nz_26, w, label='2026 Non-Zero (y≠0) ROC-AUC', color='#D97706', edgecolor='black', lw=0.5)
99
+ ax1.axhline(0.5000, color='#E11D48', linestyle='--', lw=1.2, label='Random Guess / Flat Heuristic (0.5000)')
100
  ax1.set_xticks(x)
101
  ax1.set_xticklabels(horizons)
102
+ ax1.set_ylim(0.480, 0.545)
103
+ ax1.set_ylabel('Threshold-Independent ROC-AUC')
104
+ ax1.set_title('(a) All-Bar vs. Strict Non-Zero (y≠0) ROC-AUC by Horizon')
105
  ax1.legend(loc='upper right', frameon=True)
106
  ax1.grid(axis='y', alpha=0.3)
107
 
108
+ # Panel (b): 1-Minute Accuracy & ROC-AUC by |y| Return Magnitude Quartile (Q1..Q4, y != 0)
109
+ b_keys = ["Q1_Smallest_Move", "Q2_Moderate_Move", "Q3_Medium_Move", "Q4_Largest_Move"]
110
+ b_lbls = ["Q1 Micro\n(~0.75 bps)", "Q2 Small\n(~2.1 bps)", "Q3 Medium\n(~4.4 bps)", "Q4 Large\n(~12.4 bps)"]
111
+ cal_acc_24 = [ep3_24["1m"]["return_magnitude_buckets"][bk]["calibrated_dir_acc"] for bk in b_keys]
112
+ cal_acc_26 = [ep3_26["1m"]["return_magnitude_buckets"][bk]["calibrated_dir_acc"] for bk in b_keys]
113
+ b_auc_24 = [ep3_24["1m"]["return_magnitude_buckets"][bk]["roc_auc"] * 100.0 for bk in b_keys]
114
+ b_auc_26 = [ep3_26["1m"]["return_magnitude_buckets"][bk]["roc_auc"] * 100.0 for bk in b_keys]
115
+
116
+ xb = np.arange(len(b_lbls))
117
+ wb = 0.20
118
+ ax2.bar(xb - 1.5*wb, cal_acc_24, wb, label='2024 Calibrated Acc (%)', color='#1E3A8A', edgecolor='black', lw=0.5)
119
+ ax2.bar(xb - 0.5*wb, b_auc_24, wb, label='2024 Bucket ROC-AUC (×100)', color='#38BDF8', edgecolor='black', lw=0.5)
120
+ ax2.bar(xb + 0.5*wb, cal_acc_26, wb, label='2026 Calibrated Acc (%)', color='#0F766E', edgecolor='black', lw=0.5)
121
+ ax2.bar(xb + 1.5*wb, b_auc_26, wb, label='2026 Bucket ROC-AUC (×100)', color='#F59E0B', edgecolor='black', lw=0.5)
122
+ ax2.axhline(50.0, color='#E11D48', linestyle='--', lw=1.2, label='50.0% Null Benchmark')
 
 
 
 
 
 
 
 
 
123
  ax2.set_xticks(xb)
124
+ ax2.set_xticklabels(b_lbls, fontsize=8)
125
+ ax2.set_ylim(49.0, 54.8)
126
+ ax2.set_ylabel('Non-Zero Bucket Accuracy (%) / AUC (×100)')
127
+ ax2.set_title('(b) 1-Minute Non-Zero Discrimination by |Return| Quartile')
128
+ ax2.legend(loc='upper right', frameon=True, fontsize=7.2)
129
  ax2.grid(axis='y', alpha=0.3)
130
 
131
  plt.tight_layout()
 
133
  plt.close()
134
 
135
  # =========================================================================
136
+ # Figure 3: Frobenius Drift vs RMS Update Arithmetic & Pre-2024 Stress Forgetting
137
  # =========================================================================
138
+ print("Rendering Figure 3 from Frobenius drift / Adam RMS arithmetic & Pre-2024 stress audit...")
139
  fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(11, 4.0), dpi=300)
140
 
141
+ modules = ["Return\nHead", "Depthwise\nConv", "SwiGLU\nFFN", "Conformer\nBackbone", "Dir.\nHead", "GQA\nAttn", "Inception\nTokenizer"]
142
+ mod_keys = ["return_regression_head", "sub_depthwise_conv", "sub_swiglu_ffn", "conformer_backbone_all", "directional_class_head", "sub_gqa_attention", "inception_tokenizer"]
143
 
144
+ wd = audit["weight_drift_and_cosine_audit"]
145
+ drift_wf24 = [wd["epoch3_to_wf2024"]["by_module"][k]["rel_frobenius_pct"] for k in mod_keys]
146
+ drift_wf25 = [wd["epoch3_to_wf2025"]["by_module"][k]["rel_frobenius_pct"] for k in mod_keys]
147
+ rms_dw_wf24 = [wd["epoch3_to_wf2024"]["by_module"][k]["rms_update_magnitude"] * 1e4 for k in mod_keys]
148
+ rms_w_base = [wd["epoch3_to_wf2024"]["by_module"][k]["rms_weight_norm"] * 50.0 for k in mod_keys]
149
 
150
  xm = np.arange(len(modules))
151
+ wm = 0.25
152
+ ax1.bar(xm - wm, drift_wf24, wm, label='Rel. Drift Ep3→WF24 (%)', color='#0284C7', edgecolor='black', lw=0.5)
153
+ ax1.bar(xm, drift_wf25, wm, label='Rel. Drift Ep3→WF25 (%)', color='#0D9488', edgecolor='black', lw=0.5)
154
+ ax1.bar(xm + wm, rms_dw_wf24, wm, label='Abs. RMS Update ||ΔW||_RMS (×10⁴)', color='#F59E0B', edgecolor='black', lw=0.5)
155
+ ax1.plot(xm, rms_w_base, marker='D', color='#E11D48', lw=1.5, linestyle='--', label='Base Weight Norm ||W||_RMS (×50)')
 
156
  ax1.set_xticks(xm)
157
+ ax1.set_xticklabels(modules, fontsize=7.5)
158
+ ax1.set_ylabel('Drift (%) / Scaled RMS Magnitude')
159
+ ax1.set_title('(a) Plasticity Hierarchy: Relative Drift vs. Absolute RMS Update')
160
+ ax1.legend(loc='upper left', frameon=True, fontsize=7.2)
161
+ ax1.grid(True, alpha=0.3)
162
+
163
+ # Panel (b): Pre-2024 Historical Stress Regimes & Forward OOS ROC-AUC (Epoch 3 vs WF-2024 vs WF-2025)
164
+ cohorts_lbl = ["2020-03\nCOVID Crash", "2022-06\nRate Shock", "2023-12\nPre-Anchor", "Pre-2024\nCombined", "2024\nOOS", "2025\nOOS", "2026\nForward"]
165
+ c_keys = ["stress_2020_03", "stress_2022_06", "stress_2023_12", "pre2024_stress", "2024", "2025", "2026"]
166
+
167
+ mc = audit["multi_checkpoint_oos_and_stress_audit"]
168
+ auc_ep3 = [mc["epoch3"][ck]["overall_roc_auc"] for ck in c_keys]
169
+ auc_wf24 = [mc["wf2024"][ck]["overall_roc_auc"] for ck in c_keys]
170
+ auc_wf25 = [mc["wf2025"][ck]["overall_roc_auc"] for ck in c_keys]
171
+
172
+ xc = np.arange(len(cohorts_lbl))
173
+ wc = 0.25
174
+ ax2.bar(xc - wc, auc_ep3, wc, label='Frozen Epoch 3 (2010–2023)', color='#1E3A8A', edgecolor='black', lw=0.5)
175
+ ax2.bar(xc, auc_wf24, wc, label='Online WF-2024 (+2024)', color='#0EA5E9', edgecolor='black', lw=0.5)
176
+ ax2.bar(xc + wc, auc_wf25, wc, label='Online WF-2025 (+2024–25)', color='#10B981', edgecolor='black', lw=0.5)
177
+ ax2.axhline(0.5000, color='#E11D48', linestyle='--', lw=1.1, label='Random Null (0.5000)')
178
  ax2.set_xticks(xc)
179
+ ax2.set_xticklabels(cohorts_lbl, fontsize=7.5)
180
+ ax2.set_ylim(0.500, 0.522)
181
  ax2.set_ylabel('7-Horizon Mean ROC-AUC')
182
+ ax2.set_title('(b) Backward Stress Forgetting & Forward Transfer Audit')
183
+ ax2.legend(loc='upper right', frameon=True, fontsize=7.2)
184
+ ax2.grid(axis='y', alpha=0.3)
185
 
186
  plt.tight_layout()
187
  fig.savefig("papers/figures/fig3_walk_forward_comparison.png", dpi=300, bbox_inches='tight', pad_inches=0.1)
188
  plt.close()
189
 
190
  # =========================================================================
191
+ # Figure 4: Controlled Mechanistic Kernel Ablation (Mean-Ablation, Controls & Denominator Effect)
192
  # =========================================================================
193
+ print("Rendering Figure 4 from controlled mean-ablation, random-channel controls & RMS logit shift...")
194
  fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(11, 4.0), dpi=300)
195
 
196
+ ab = audit["mechanistic_kernel_ablation_controlled"]
197
+ ab_keys = ["MeanAblate_K3", "MeanAblate_K7", "MeanAblate_K15", "MeanAblate_K31", "MeanAblate_K63", "MeanAblate_K127", "Random_341ch_Control", "MeanAblate_Micro_K3_K7", "MeanAblate_Meso_K15_K31", "MeanAblate_Macro_K63_K127", "Random_682ch_Control"]
198
+ ab_lbls = ["K=3", "K=7", "K=15", "K=31", "K=63", "K=127", "Rand\n341ch", "Micro\n(3,7)", "Meso\n(15,31)", "Macro\n(63,127)", "Rand\n682ch"]
199
 
200
+ cent_mean = [ab["mean_ablations"][k]["mean_centered_logit_l2_pct"] for k in ab_keys]
201
+ cent_zero = [ab["zero_ablations"][k.replace("MeanAblate_", "ZeroAblate_")]["mean_centered_logit_l2_pct"] for k in ab_keys]
 
202
 
203
+ xa = np.arange(len(ab_lbls))
204
+ wa = 0.36
205
+ ax1.bar(xa - wa/2, cent_mean, wa, label='In-Distribution Mean-Ablation (Centered L2 %)', color='#4F46E5', edgecolor='black', lw=0.5)
206
+ ax1.bar(xa + wa/2, cent_zero, wa, label='Zero-Clamping Ablation (Centered L2 %)', color='#0EA5E9', edgecolor='black', lw=0.5)
207
+ ax1.axhline(ab["mean_ablations"]["Random_341ch_Control"]["mean_centered_logit_l2_pct"], color='#E11D48', linestyle=':', lw=1.2, label='Random 341-Ch Mean-Ablate Null (20.31%)')
208
  ax1.set_xticks(xa)
209
+ ax1.set_xticklabels(ab_lbls, fontsize=7.2)
210
+ ax1.set_ylabel('Centered Logit Shift ||Δ(z - z̄)||_2 / ||z - z̄||_2 (%)')
211
+ ax1.set_title('(a) Centered Logit Sensitivity vs. Random-Channel Controls')
212
+ ax1.legend(loc='upper left', frameon=True, fontsize=7.2)
213
  ax1.grid(axis='y', alpha=0.3)
214
 
215
+ # Panel (b): Resolving the Denominator Effect across Horizons (Uncentered Raw L2 vs Centered L2 vs Abs RMS)
216
+ k7_ph = ab["mean_ablations"]["MeanAblate_K7"]["per_horizon"]
217
+ meso_ph = ab["mean_ablations"]["MeanAblate_Meso_K15_K31"]["per_horizon"]
218
+ raw_l2_k7 = [k7_ph[h]["raw_logit_l2_pct"] for h in horizons]
219
+ cent_l2_k7 = [k7_ph[h]["centered_logit_l2_pct"] for h in horizons]
220
+ rms_k7_scaled = [k7_ph[h]["abs_logit_rms_shift"] * 1000.0 for h in horizons]
221
+ base_rms_scaled = [ab["baseline"]["per_horizon"][h]["logit_rms"] * 200.0 for h in horizons]
222
+
223
+ xh = np.arange(len(horizons))
224
+ ax2.plot(xh, raw_l2_k7, marker='o', lw=2.0, color='#D97706', label='Uncentered ||Δz||_2 / ||z||_2 (%) [Peaks at 15m]')
225
+ ax2.plot(xh, cent_l2_k7, marker='s', lw=2.0, color='#4F46E5', label='Centered ||Δ(z-z̄)||_2 / ||z-z̄||_2 (%) [Variance-Norm]')
226
+ ax2.plot(xh, rms_k7_scaled, marker='^', lw=2.0, color='#0F766E', label='Denominator-Free RMS(Δz) (×1000) [Monotonic]')
227
+ ax2.plot(xh, base_rms_scaled, marker='x', lw=1.4, linestyle='--', color='#64748B', label='Baseline Denom. ||z||_RMS (×200) [Min at 15m]')
228
+ ax2.set_xticks(xh)
229
+ ax2.set_xticklabels(horizons)
230
+ ax2.set_ylabel('Perturbation (%) / Scaled RMS Units')
231
+ ax2.set_title('(b) Decomposition of the 15m Logit Denominator Effect (K=7)')
232
+ ax2.legend(loc='upper right', frameon=True, fontsize=7.0)
233
+ ax2.grid(True, alpha=0.3)
234
 
235
  plt.tight_layout()
236
  fig.savefig("papers/figures/fig4_kernel_ablation.png", dpi=300, bbox_inches='tight', pad_inches=0.1)
237
  plt.close()
238
 
239
  # =========================================================================
240
+ # Figure 5: Non-Overlapping Contiguous Backtest & Frozen 2024 Policy OOS
241
  # =========================================================================
242
+ print("Rendering Figure 5 from non-overlapping state-turnover backtest & frozen 2024 policy...")
243
  fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(11, 4.0), dpi=300)
244
 
245
+ # Panel (a): Fixed Hurdle (tau=1.0sigma) Walk-Forward Gross Return & State-Hold Breakeven Across 2024, 2025, 2026
246
+ wf_tau1 = audit["frozen_2024_policy_oos_evaluation"]["walk_forward_weights"]["fixed_tau_1sigma_all_horizons"]
247
+ h_plot = ["1m", "3m", "5m", "15m", "30m", "60m"]
248
+ be_24 = [wf_tau1[h]["2024"]["breakeven_one_way_bps_state_hold"] for h in h_plot]
249
+ be_25 = [wf_tau1[h]["2025"]["breakeven_one_way_bps_state_hold"] for h in h_plot]
250
+ be_26 = [wf_tau1[h]["2026"]["breakeven_one_way_bps_state_hold"] for h in h_plot]
251
+
252
+ xp = np.arange(len(h_plot))
253
+ wp = 0.25
254
+ ax1.bar(xp - wp, be_24, wp, label='2024 OOS State-Hold Breakeven (bps)', color='#0284C7', edgecolor='black', lw=0.5)
255
+ ax1.bar(xp, be_25, wp, label='2025 OOS State-Hold Breakeven (bps)', color='#0D9488', edgecolor='black', lw=0.5)
256
+ ax1.bar(xp + wp, be_26, wp, label='2026 OOS State-Hold Breakeven (bps)', color='#7C3AED', edgecolor='black', lw=0.5)
257
+ ax1.axhline(0.0, color='black', lw=0.9)
258
+ ax1.axhline(1.5, color='#E11D48', linestyle='--', lw=1.2, label='Maker / Midpoint Cost Hurdle (1.5 bps)')
259
+ ax1.set_xticks(xp)
260
+ ax1.set_xticklabels(h_plot)
261
+ ax1.set_ylabel('State-Hold Breakeven One-Way Cost (bps)')
262
+ ax1.set_title('(a) Non-Overlapping Breakeven Cost (Fixed τ=1.0σ, Walk-Forward)')
263
+ ax1.legend(loc='lower left', frameon=True, fontsize=7.2)
264
+ ax1.grid(axis='y', alpha=0.3)
265
 
266
+ # Panel (b): Frozen 2024 Selected Policy (60m, tau=0.0sigma) vs Fixed 3m (tau=1.0sigma) Across Cost Grid
267
+ cost_bps = [0.0, 1.5, 3.0, 5.0]
268
+ cost_keys = ["0.0bps_oneway", "1.5bps_oneway", "3.0bps_oneway", "5.0bps_oneway"]
269
+
270
+ fpol_wf = audit["frozen_2024_policy_oos_evaluation"]["walk_forward_weights"]["frozen_2024_optimal_policy"]["yearly_performance"]
271
+ sr_f24 = [fpol_wf["2024"]["cost_grid"][ck]["annualized_sharpe_state_hold"] for ck in cost_keys]
272
+ sr_f25 = [fpol_wf["2025"]["cost_grid"][ck]["annualized_sharpe_state_hold"] for ck in cost_keys]
273
+ sr_f26 = [fpol_wf["2026"]["cost_grid"][ck]["annualized_sharpe_state_hold"] for ck in cost_keys]
274
+ sr_3m_26 = [wf_tau1["3m"]["2026"]["cost_grid"][ck]["annualized_sharpe_state_hold"] for ck in cost_keys]
275
+
276
+ ax2.plot(cost_bps, sr_f24, marker='o', lw=2.0, color='#0284C7', label='Frozen Policy on 2024 (Selection: SR=+4.40 at 0bp, +2.04 at 1.5bp)')
277
+ ax2.plot(cost_bps, sr_f25, marker='s', lw=2.0, color='#0D9488', label='Frozen Policy Applied Untouched to 2025 (SR=+1.01 at 0bp)')
278
+ ax2.plot(cost_bps, sr_f26, marker='^', lw=2.0, color='#D97706', label='Frozen Policy Applied Untouched to 2026 (SR=-2.01 at 0bp)')
279
+ ax2.plot(cost_bps, sr_3m_26, marker='D', lw=1.8, linestyle='--', color='#7C3AED', label='2026 3m Demeaned (τ=1.0σ: SR=+3.56 at 0bp)')
280
+ ax2.axhline(0.0, color='black', linestyle='--', lw=1.1, label='Zero Net Sharpe Boundary')
281
+ ax2.set_xlabel('One-Way Execution Cost: Spread + Fee + Slippage (bps)')
282
+ ax2.set_ylabel('Annualized Net Sharpe Ratio (Non-Overlapping)')
283
+ ax2.set_title('(b) Frozen 2024 Policy Untouched OOS Transfer (2024–2026)')
284
+ ax2.legend(loc='lower left', frameon=True, fontsize=7.0)
285
  ax2.grid(True, alpha=0.3)
286
 
287
  plt.tight_layout()
288
  fig.savefig("papers/figures/fig5_slippage_friction_curve.png", dpi=300, bbox_inches='tight', pad_inches=0.1)
289
  plt.close()
290
 
291
+ print("✅ All 5 upgraded deterministic empirical figures rendered at 300 DPI!")