"""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))
