"""XM01 — Single-L Momentum Sweep MECHANISM: Score = past_return(close, L). Long top-k / short bottom-k cross-sectionally. Grid: L in {20, 30, 60, 90, 120}; universe in {all, majors}; test long-short and long-only. Known prior: plain momentum on full 49-universe (XS01 uses 19 majors with L blend 30+90). Goal: confirm negative on full universe, find whether single-L differs from XS01 blend. """ import sys sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/xsec") import xslib as xs import numpy as np print("XM01 — Single-L Momentum Sweep") print("=" * 60) # --- 5 targeted backtests --- # 1) Full 49-universe, medium lookback L=60, LS — expected to be negative (known prior) rep1 = xs.study_xs( "XM01_ALL_L60", lambda P: xs.past_return(P.close, 60), universe="all", H=10, k=5, long_short=True ) print(xs.fmt(rep1)) print("JSON:", xs.as_json(rep1)) print() # 2) Full universe, short lookback L=20 — does short-term momentum work? rep2 = xs.study_xs( "XM01_ALL_L20", lambda P: xs.past_return(P.close, 20), universe="all", H=10, k=5, long_short=True ) print(xs.fmt(rep2)) print("JSON:", xs.as_json(rep2)) print() # 3) Full universe, long lookback L=120, LS — intermediate/long momentum rep3 = xs.study_xs( "XM01_ALL_L120", lambda P: xs.past_return(P.close, 120), universe="all", H=10, k=5, long_short=True ) print(xs.fmt(rep3)) print("JSON:", xs.as_json(rep3)) print() # 4) Majors only (XS01 turf), single L=60 — compare single-L vs XS01 blend on same universe rep4 = xs.study_xs( "XM01_MAJORS_L60", lambda P: xs.past_return(P.close, 60), universe="majors", H=10, k=5, long_short=True ) print(xs.fmt(rep4)) print("JSON:", xs.as_json(rep4)) print() # 5) Full universe, L=90, long-only top-k — momentum as selection filter (long-only) rep5 = xs.study_xs( "XM01_ALL_L90_LO", lambda P: xs.past_return(P.close, 90), universe="all", H=10, k=5, long_short=False ) print(xs.fmt(rep5)) print("JSON:", xs.as_json(rep5)) print() # Pick best: prefer earns_slot, then hold-out sharpe, then distinctness from XS01 all_reps = [rep1, rep2, rep3, rep4, rep5] def score_rep(r): earns = int(r["earns_slot"]) hold_sh = r["holdout"].get("sharpe", -9) full_sh = r["full"]["sharpe"] corr_xs01 = r["corr_xs01"] or 1.0 distinctness = 1 - abs(corr_xs01) # higher = more distinct return (earns, hold_sh, full_sh, distinctness) best = max(all_reps, key=score_rep) print("=" * 60) print(f"BEST CONFIG: {best['name']}") print(xs.fmt(best)) print("JSON:", xs.as_json(best))