Includes core prod + GREEN/BLUE subsystems: - prod/ (BLUE harness, configs, scripts, docs) - nautilus_dolphin/ (GREEN Nautilus-native impl + dvae/ preserved) - adaptive_exit/ (AEM engine + models/bucket_assignments.pkl) - Observability/ (EsoF advisor, TUI, dashboards) - external_factors/ (EsoF producer) - mc_forewarning_qlabs_fork/ (MC regime/envelope) Excludes runtime caches, logs, backups, and reproducible artifacts per .gitignore.
409 lines
20 KiB
Python
Executable File
409 lines
20 KiB
Python
Executable File
"""
|
||
Exp 9 — Extended Leverage Ceiling Test
|
||
|
||
Motivation:
|
||
GOLD (adaptive_beta) achieved DD=14.32% (−0.72pp vs Silver=15.05%). The question is whether
|
||
this headroom permits raising the leverage ceiling above the current 5x soft / 6x hard cap
|
||
without exceeding Silver's DD budget — or ideally staying below GOLD's DD while gaining ROI.
|
||
|
||
Architecture recap (DO NOT MODIFY any of the below):
|
||
bet_sizer.max_leverage (5.0) → convex curve soft cap — strength_score^3 tops out here
|
||
base_max_leverage (5.0) → base for ACB regime excursions
|
||
abs_max_leverage (6.0) → hard ceiling: min(base*regime_mult, abs_max)
|
||
ACB regime_size_mult (1.0–1.6) → can push raw_leverage above bet_sizer.max_leverage
|
||
→ Current actual range: 0.5x – 6.0x (6x hard cap is binding on extreme signals)
|
||
|
||
Fork strategy:
|
||
ExtendedLeverageEngine(AdaptiveBoostEngine) — subclass only, zero parent modification.
|
||
Sets all three caps consistently: bet_sizer.max_leverage = base_max_leverage = extended_soft_cap,
|
||
abs_max_leverage = extended_abs_cap.
|
||
Example at 7.0/8.0: extreme signal gets bet_sizer→7.0 × regime_mult≈1.2 = 8.4, clamped at 8.0.
|
||
|
||
MC-Forewarner interaction (CRITICAL):
|
||
begin_day() feeds MC: mc_cfg['max_leverage'] = base_max_leverage * day_base_boost
|
||
MC was trained at max_leverage 5.0–6.0 (champion region). At 8x+ it's outside training
|
||
distribution → One-Class SVM envelope_score likely < -1.0 → RED → regime_dd_halt=True
|
||
→ ZERO trades that day.
|
||
|
||
Two modes tested:
|
||
mc_ref=5.0 ("decoupled"): MC sees original 5.0x reference → same verdicts as GOLD
|
||
Pure effect of higher ceiling with MC behavior unchanged
|
||
mc_ref=soft_cap ("coupled"): MC sees actual new cap → may flag RED/ORANGE on more days
|
||
Tests "what would MC do if it knew about the new leverage"
|
||
|
||
ExtendedLeverageEngine.begin_day() temporarily swaps base_max_leverage to mc_leverage_ref
|
||
before calling super().begin_day(), then restores extended caps for actual trading.
|
||
This is the ONLY divergence from parent logic.
|
||
|
||
Test configs:
|
||
A: 5.0/6.0 mc_ref=5.0 — GOLD reference (must reproduce 96.55% / 14.32%)
|
||
B: 6.0/7.0 mc_ref=5.0 — +1x soft, MC decoupled
|
||
C: 7.0/8.0 mc_ref=5.0 — +2x soft, MC decoupled
|
||
D: 8.0/9.0 mc_ref=5.0 — +3x soft, MC decoupled
|
||
E: 9.0/10.0 mc_ref=5.0 — +4x soft, MC decoupled
|
||
F: 6.0/7.0 mc_ref=6.0 — +1x soft, MC coupled
|
||
G: 7.0/8.0 mc_ref=7.0 — +2x soft, MC coupled
|
||
H: 8.0/9.0 mc_ref=8.0 — +3x soft, MC coupled
|
||
Total: 8 runs × ~250s ≈ 35 min
|
||
|
||
Key metrics:
|
||
ROI%, DD%, PF, Trades, avg_leverage (mean realized leverage per trade)
|
||
MC status breakdown: RED days / ORANGE days / OK days / halted days
|
||
Δ vs GOLD: ΔROI, ΔDD
|
||
|
||
Results → exp9_leverage_ceiling_results.json
|
||
"""
|
||
|
||
import sys, time, json, math
|
||
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
||
from pathlib import Path
|
||
import numpy as np
|
||
|
||
_HERE = Path(__file__).resolve().parent
|
||
sys.path.insert(0, str(_HERE.parent))
|
||
|
||
from exp_shared import (
|
||
ensure_jit, ENGINE_KWARGS, GOLD, MC_BASE_CFG,
|
||
load_data, load_forewarner, log_results,
|
||
)
|
||
from nautilus_dolphin.nautilus.proxy_boost_engine import AdaptiveBoostEngine, DEFAULT_THRESHOLD, DEFAULT_ALPHA
|
||
from nautilus_dolphin.nautilus.adaptive_circuit_breaker import AdaptiveCircuitBreaker
|
||
|
||
# ── GOLD reference for this experiment (adaptive_beta, not the old silver) ───
|
||
_GOLD_EXP9 = dict(roi=96.55, dd=14.32, trades=2155) # adaptive_beta GOLD
|
||
_SILVER = dict(roi=88.55, dd=15.05, trades=2155) # former gold = regression floor
|
||
|
||
|
||
# ── ExtendedLeverageEngine — subclass only, ZERO parent modification ──────────
|
||
|
||
class ExtendedLeverageEngine(AdaptiveBoostEngine):
|
||
"""
|
||
Extended leverage ceiling fork of AdaptiveBoostEngine (adaptive_beta GOLD).
|
||
|
||
Three new constructor params vs parent:
|
||
extended_soft_cap : replaces max_leverage (5.0) and base_max_leverage
|
||
extended_abs_cap : replaces abs_max_leverage (6.0) — hard ceiling
|
||
mc_leverage_ref : what to feed the MC-Forewarner (independent of actual caps)
|
||
If None → MC sees extended_soft_cap (fully coupled)
|
||
Set to 5.0 → MC always sees original 5x reference (decoupled)
|
||
|
||
ALL existing leverage logic (convex curve, ACB regime_size_mult, STALKER 2x cap,
|
||
proxy_B scale_boost, etc.) is completely untouched. Only the three cap values change.
|
||
"""
|
||
|
||
def __init__(
|
||
self,
|
||
*args,
|
||
extended_soft_cap: float = 5.0,
|
||
extended_abs_cap: float = 6.0,
|
||
mc_leverage_ref: float = None,
|
||
**kwargs,
|
||
):
|
||
# Inject extended caps as max_leverage / abs_max_leverage so parent stores them
|
||
kwargs['max_leverage'] = extended_soft_cap
|
||
kwargs['abs_max_leverage'] = extended_abs_cap
|
||
super().__init__(*args, **kwargs)
|
||
|
||
# Explicitly ensure all three cap locations are consistent
|
||
# (parent __init__ sets base_max_leverage = max_leverage and bet_sizer.max_leverage
|
||
# from the kwargs, but we set explicitly for clarity)
|
||
self.bet_sizer.max_leverage = extended_soft_cap
|
||
self.base_max_leverage = extended_soft_cap
|
||
self.abs_max_leverage = extended_abs_cap
|
||
|
||
self._extended_soft_cap = extended_soft_cap
|
||
self._extended_abs_cap = extended_abs_cap
|
||
# MC reference: 5.0 = decoupled (MC sees original gold reference)
|
||
# extended_soft_cap = coupled (MC sees actual new cap)
|
||
self._mc_leverage_ref = mc_leverage_ref if mc_leverage_ref is not None else extended_soft_cap
|
||
|
||
# Per-day MC verdict monitoring
|
||
self.mc_monitor = dict(red=0, orange=0, ok=0, halted=0, total=0)
|
||
|
||
def begin_day(self, date_str: str, posture: str = 'APEX', direction=None) -> None:
|
||
"""
|
||
Temporarily expose mc_leverage_ref to the MC-Forewarner assessment,
|
||
then restore the true extended caps for actual trading.
|
||
|
||
The parent begin_day() computes:
|
||
mc_cfg['max_leverage'] = self.base_max_leverage * self._day_base_boost
|
||
By setting base_max_leverage = mc_leverage_ref before the call, MC sees the
|
||
reference leverage. After super().begin_day() returns, regime_dd_halt and
|
||
_day_mc_scale are already set correctly for that reference. We then restore
|
||
the true extended caps so _try_entry uses the full new ceiling.
|
||
"""
|
||
# Save true extended caps
|
||
_true_base = self.base_max_leverage
|
||
_true_abs = self.abs_max_leverage
|
||
_true_sizer = self.bet_sizer.max_leverage
|
||
|
||
# Temporarily expose mc_leverage_ref to parent's MC assessment
|
||
self.base_max_leverage = self._mc_leverage_ref
|
||
self.bet_sizer.max_leverage = self._mc_leverage_ref
|
||
self.abs_max_leverage = self._mc_leverage_ref # only affects _try_entry, safe to temp-set
|
||
|
||
super().begin_day(date_str, posture=posture, direction=direction)
|
||
|
||
# Restore true extended caps — all trading this day uses extended ceiling
|
||
self.base_max_leverage = _true_base
|
||
self.bet_sizer.max_leverage = _true_sizer
|
||
self.abs_max_leverage = _true_abs
|
||
|
||
# Record MC verdict for monitoring
|
||
self.mc_monitor['total'] += 1
|
||
status = self._day_mc_status
|
||
if status == 'RED':
|
||
self.mc_monitor['red'] += 1
|
||
elif status == 'ORANGE':
|
||
self.mc_monitor['orange'] += 1
|
||
else:
|
||
self.mc_monitor['ok'] += 1
|
||
if self.regime_dd_halt:
|
||
self.mc_monitor['halted'] += 1
|
||
|
||
def reset(self):
|
||
super().reset()
|
||
# NDAlphaEngine.reset() rebuilds bet_sizer from self.bet_sizer.max_leverage
|
||
# (which at reset time = _extended_soft_cap, so it rebuilds correctly).
|
||
# But we re-apply explicitly to be safe.
|
||
self.bet_sizer.max_leverage = self._extended_soft_cap
|
||
self.base_max_leverage = self._extended_soft_cap
|
||
self.abs_max_leverage = self._extended_abs_cap
|
||
# Reset monitoring
|
||
self.mc_monitor = dict(red=0, orange=0, ok=0, halted=0, total=0)
|
||
|
||
|
||
# ── Run harness ───────────────────────────────────────────────────────────────
|
||
|
||
def _run(engine_factory, name, d, fw):
|
||
"""Full 55-day run + MC monitoring + avg_leverage tracking."""
|
||
kw = ENGINE_KWARGS.copy()
|
||
acb = AdaptiveCircuitBreaker()
|
||
acb.preload_w750(d['date_strings'])
|
||
|
||
eng = engine_factory(kw)
|
||
eng.set_ob_engine(d['ob_eng'])
|
||
eng.set_acb(acb)
|
||
if fw is not None:
|
||
eng.set_mc_forewarner(fw, MC_BASE_CFG)
|
||
eng.set_esoteric_hazard_multiplier(0.0)
|
||
|
||
daily_caps, daily_pnls = [], []
|
||
|
||
for pf in d['parquet_files']:
|
||
ds = pf.stem
|
||
df, acols, dvol = d['pq_data'][ds]
|
||
cap_before = eng.capital
|
||
vol_ok = np.where(np.isfinite(dvol), dvol > d['vol_p60'], False)
|
||
eng.process_day(ds, df, acols, vol_regime_ok=vol_ok)
|
||
daily_caps.append(eng.capital)
|
||
daily_pnls.append(eng.capital - cap_before)
|
||
|
||
tr = eng.trade_history
|
||
n = len(tr)
|
||
roi = (eng.capital - 25000.0) / 25000.0 * 100.0
|
||
|
||
if n == 0:
|
||
mc_mon = getattr(eng, 'mc_monitor', {})
|
||
return dict(name=name, roi=roi, pf=0.0, dd=0.0, wr=0.0, sharpe=0.0,
|
||
trades=0, avg_leverage=0.0, sizing_scale_mean=1.0,
|
||
mc_monitor=mc_mon)
|
||
|
||
def _abs(t): return t.pnl_absolute if hasattr(t, 'pnl_absolute') else t.pnl_pct * 250.0
|
||
wins = [t for t in tr if _abs(t) > 0]
|
||
losses = [t for t in tr if _abs(t) <= 0]
|
||
wr = len(wins) / n * 100.0
|
||
pf_val = sum(_abs(t) for t in wins) / max(abs(sum(_abs(t) for t in losses)), 1e-9)
|
||
|
||
peak_cap, max_dd = 25000.0, 0.0
|
||
for cap in daily_caps:
|
||
peak_cap = max(peak_cap, cap)
|
||
max_dd = max(max_dd, (peak_cap - cap) / peak_cap * 100.0)
|
||
|
||
dr = np.array([p / 25000.0 * 100.0 for p in daily_pnls])
|
||
sharpe = float(dr.mean() / (dr.std() + 1e-9) * math.sqrt(365)) if len(dr) > 1 else 0.0
|
||
|
||
# Realized leverage stats
|
||
lev_vals = [t.leverage for t in tr if hasattr(t, 'leverage') and t.leverage > 0]
|
||
avg_lev = float(np.mean(lev_vals)) if lev_vals else 0.0
|
||
max_lev = float(np.max(lev_vals)) if lev_vals else 0.0
|
||
lev_p90 = float(np.percentile(lev_vals, 90)) if lev_vals else 0.0
|
||
lev_at_cap = sum(1 for v in lev_vals if v >= (eng.abs_max_leverage - 0.05))
|
||
pct_at_cap = lev_at_cap / len(lev_vals) * 100.0 if lev_vals else 0.0
|
||
|
||
# proxy_B scale stats
|
||
scale_mean = getattr(eng, 'sizing_scale_mean', 1.0)
|
||
|
||
# MC monitoring
|
||
mc_mon = getattr(eng, 'mc_monitor', {})
|
||
|
||
return dict(
|
||
name=name,
|
||
roi=roi, pf=pf_val, dd=max_dd, wr=wr, sharpe=sharpe, trades=n,
|
||
avg_leverage=avg_lev, max_leverage_realized=max_lev,
|
||
lev_p90=lev_p90,
|
||
pct_at_hard_cap=pct_at_cap,
|
||
sizing_scale_mean=scale_mean,
|
||
mc_monitor=mc_mon,
|
||
)
|
||
|
||
|
||
# ── Main ─────────────────────────────────────────────────────────────────────
|
||
|
||
def main():
|
||
t_start = time.time()
|
||
print("=" * 76)
|
||
print("Exp 9 — Extended Leverage Ceiling Test (fork of GOLD adaptive_beta)")
|
||
print("=" * 76)
|
||
print(f" GOLD ref : ROI={_GOLD_EXP9['roi']:.2f}% DD={_GOLD_EXP9['dd']:.2f}% (adaptive_beta)")
|
||
print(f" SILVER ref: ROI={_SILVER['roi']:.2f}% DD={_SILVER['dd']:.2f}% (former gold, regression floor)")
|
||
|
||
ensure_jit()
|
||
d = load_data()
|
||
fw = load_forewarner()
|
||
|
||
# Config: (label, extended_soft_cap, extended_abs_cap, mc_leverage_ref)
|
||
configs = [
|
||
# ── Decoupled (MC sees original 5.0x reference across all runs) ──────────
|
||
("A_5.0/6.0_mc5.0_GOLD-ref", 5.0, 6.0, 5.0), # must reproduce GOLD 96.55%
|
||
("B_6.0/7.0_mc5.0_decoupled", 6.0, 7.0, 5.0),
|
||
("C_7.0/8.0_mc5.0_decoupled", 7.0, 8.0, 5.0),
|
||
("D_8.0/9.0_mc5.0_decoupled", 8.0, 9.0, 5.0),
|
||
("E_9.0/10.0_mc5.0_decoupled", 9.0, 10.0, 5.0),
|
||
# ── Coupled (MC sees actual new cap → tests MC's response) ───────────────
|
||
("F_6.0/7.0_mc6.0_coupled", 6.0, 7.0, 6.0),
|
||
("G_7.0/8.0_mc7.0_coupled", 7.0, 8.0, 7.0),
|
||
("H_8.0/9.0_mc8.0_coupled", 8.0, 9.0, 8.0),
|
||
]
|
||
|
||
# adaptive_beta proxy_B params (match GOLD exactly)
|
||
_PROXY_KWARGS = dict(threshold=DEFAULT_THRESHOLD, alpha=DEFAULT_ALPHA,
|
||
adaptive_beta=True, adaptive_alpha=False, adaptive_thr=False)
|
||
|
||
results = []
|
||
for i, (label, soft, hard, mc_ref) in enumerate(configs):
|
||
t0 = time.time()
|
||
print(f"\n[{i+1}/{len(configs)}] {label} ...")
|
||
|
||
def _factory(kw, s=soft, h=hard, r=mc_ref):
|
||
return ExtendedLeverageEngine(
|
||
extended_soft_cap=s,
|
||
extended_abs_cap=h,
|
||
mc_leverage_ref=r,
|
||
**_PROXY_KWARGS,
|
||
**kw,
|
||
)
|
||
|
||
res = _run(_factory, label, d, fw)
|
||
elapsed = time.time() - t0
|
||
|
||
mc = res['mc_monitor']
|
||
mc_str = (f" MC: ok={mc.get('ok',0)} orange={mc.get('orange',0)} "
|
||
f"red={mc.get('red',0)} halted={mc.get('halted',0)}/{mc.get('total',0)}")
|
||
dROI = res['roi'] - _GOLD_EXP9['roi']
|
||
dDD = res['dd'] - _GOLD_EXP9['dd']
|
||
print(f" ROI={res['roi']:>7.2f}% (Δ{dROI:+.2f}pp) DD={res['dd']:>6.2f}% (Δ{dDD:+.2f}pp) "
|
||
f"PF={res['pf']:.4f} Trades={res['trades']}")
|
||
print(f" avg_lev={res['avg_leverage']:.2f}x p90={res['lev_p90']:.2f}x "
|
||
f"max={res['max_leverage_realized']:.2f}x at_hard_cap={res['pct_at_hard_cap']:.1f}% "
|
||
f"scale_mean={res['sizing_scale_mean']:.4f}")
|
||
print(f"{mc_str} ({elapsed:.0f}s)")
|
||
|
||
results.append(res)
|
||
|
||
# ── Verification ─────────────────────────────────────────────────────────
|
||
gold_ref = results[0]
|
||
gold_ok = (abs(gold_ref['roi'] - _GOLD_EXP9['roi']) < 0.5 and
|
||
abs(gold_ref['dd'] - _GOLD_EXP9['dd']) < 0.5 and
|
||
abs(gold_ref['trades'] - _GOLD_EXP9['trades']) < 10)
|
||
print(f"\n{'='*76}")
|
||
print(f"GOLD REFERENCE VERIFICATION: {'PASS ✓' if gold_ok else 'FAIL ✗'}")
|
||
print(f" Expected: ROI={_GOLD_EXP9['roi']:.2f}% DD={_GOLD_EXP9['dd']:.2f}% "
|
||
f"Got: ROI={gold_ref['roi']:.2f}% DD={gold_ref['dd']:.2f}%")
|
||
|
||
# ── Results table ─────────────────────────────────────────────────────────
|
||
print(f"\n{'='*76}")
|
||
print("FULL RESULTS (vs GOLD = adaptive_beta 96.55% / 14.32%)")
|
||
print(f"{'Config':<38} {'ROI%':>7} {'ΔROI':>6} {'DD%':>6} {'ΔDD':>6} "
|
||
f"{'Trades':>7} {'avgLev':>7} {'p90Lev':>7} {'@cap%':>6} {'OK?':>4}")
|
||
print('-' * 100)
|
||
for r in results:
|
||
dROI = r['roi'] - _GOLD_EXP9['roi']
|
||
dDD = r['dd'] - _GOLD_EXP9['dd']
|
||
# Pass: better than GOLD on DD, not worse than SILVER on ROI
|
||
ok = ('Y' if r['dd'] < _GOLD_EXP9['dd'] and r['roi'] >= _SILVER['roi'] else
|
||
'G' if r['dd'] < _SILVER['dd'] and r['roi'] >= _SILVER['roi'] else
|
||
'N')
|
||
print(f"{r['name']:<38} {r['roi']:>7.2f} {dROI:>+6.2f} {r['dd']:>6.2f} {dDD:>+6.2f} "
|
||
f"{r['trades']:>7} {r['avg_leverage']:>7.2f} {r['lev_p90']:>7.2f} "
|
||
f"{r['pct_at_hard_cap']:>6.1f} {ok:>4}")
|
||
print(" OK=Y: beats GOLD on DD + above SILVER ROI | OK=G: beats SILVER on both | OK=N: fail")
|
||
|
||
# ── MC interaction table ──────────────────────────────────────────────────
|
||
print(f"\n{'='*76}")
|
||
print("MC-FOREWARNER INTERACTION (per-day breakdown)")
|
||
print(f"{'Config':<38} {'OK':>5} {'ORG':>5} {'RED':>5} {'HALT':>5} {'TOTAL':>6} {'halt%':>7}")
|
||
print('-' * 75)
|
||
for r in results:
|
||
mc = r['mc_monitor']
|
||
total = mc.get('total', 0)
|
||
halt = mc.get('halted', 0)
|
||
halt_pct = halt / total * 100.0 if total else 0.0
|
||
print(f"{r['name']:<38} {mc.get('ok',0):>5} {mc.get('orange',0):>5} "
|
||
f"{mc.get('red',0):>5} {halt:>5} {total:>6} {halt_pct:>7.1f}%")
|
||
|
||
# ── Decoupled vs Coupled delta at each leverage level ────────────────────
|
||
print(f"\n{'='*76}")
|
||
print("MC COUPLING EFFECT (decoupled vs coupled at same leverage level)")
|
||
pairs = [
|
||
("B_6.0/7.0", "F_6.0/7.0"),
|
||
("C_7.0/8.0", "G_7.0/8.0"),
|
||
("D_8.0/9.0", "H_8.0/9.0"),
|
||
]
|
||
rmap = {r['name'][:10]: r for r in results}
|
||
for dec_label, coup_label in pairs:
|
||
dec = next((r for r in results if dec_label in r['name']), None)
|
||
cop = next((r for r in results if coup_label in r['name']), None)
|
||
if dec and cop:
|
||
halt_dec = dec['mc_monitor'].get('halted', 0)
|
||
halt_cop = cop['mc_monitor'].get('halted', 0)
|
||
print(f" {dec_label}: decoupled ROI={dec['roi']:.2f}% DD={dec['dd']:.2f}% halted={halt_dec}d")
|
||
print(f" {coup_label}: coupled ROI={cop['roi']:.2f}% DD={cop['dd']:.2f}% halted={halt_cop}d")
|
||
print(f" MC coupling cost: ΔROI={cop['roi']-dec['roi']:+.2f}pp ΔDD={cop['dd']-dec['dd']:+.2f}pp "
|
||
f"Δhalted={halt_cop-halt_dec:+d}d")
|
||
print()
|
||
|
||
# ── Best config summary ───────────────────────────────────────────────────
|
||
print(f"{'='*76}")
|
||
decoupled = [r for r in results if 'decoupled' in r['name'] or 'GOLD' in r['name']]
|
||
best_roi = max(decoupled, key=lambda r: r['roi'])
|
||
best_dd = min(decoupled, key=lambda r: r['dd'])
|
||
best_combined = max(decoupled, key=lambda r: r['roi'] - r['dd']) # ROI−DD as proxy
|
||
|
||
print(f"BEST (decoupled only — pure leverage effect):")
|
||
print(f" Best ROI: {best_roi['name']} ROI={best_roi['roi']:.2f}% DD={best_roi['dd']:.2f}%")
|
||
print(f" Best DD: {best_dd['name']} ROI={best_dd['roi']:.2f}% DD={best_dd['dd']:.2f}%")
|
||
print(f" Best R−D: {best_combined['name']} ROI={best_combined['roi']:.2f}% DD={best_combined['dd']:.2f}%")
|
||
|
||
# ── Log ──────────────────────────────────────────────────────────────────
|
||
outfile = _HERE / "exp9_leverage_ceiling_results.json"
|
||
log_results(results, outfile, gold=_GOLD_EXP9, meta={
|
||
"exp": "exp9",
|
||
"question": "Does adaptive_beta DD headroom permit higher leverage ceiling?",
|
||
"silver": _SILVER,
|
||
"total_elapsed_s": round(time.time() - t_start, 1),
|
||
"gold_ref_ok": gold_ok,
|
||
"note_mc": (
|
||
"Decoupled runs (mc_ref=5.0): MC assesses at original 5x reference — "
|
||
"pure leverage cap test. Coupled runs: MC sees actual new cap — tests MC response."
|
||
),
|
||
})
|
||
|
||
total = time.time() - t_start
|
||
print(f"\nTotal elapsed: {total / 60:.1f} min")
|
||
print("Done.")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|