"""XM05 — Momentum Acceleration
MECHANISM: Score = past_return(close, L_short) - past_return(close, L_long)
           i.e. is momentum ACCELERATING? The idea: assets that are outperforming
           recently vs. their longer-run momentum are gaining momentum -> rank them
           high. Assets that were strong long-term but are slowing down -> rank low.
           L_short=20, L_long=60 (canonical config).

Grid: vary universe (all/majors), H (5/10), and L_short param
      to find the best config within <=5 backtests.

Distinctness target: if score is correlated to raw momentum (XS01), it's just XS01.
If acceleration captures something different (regime change, reversal of leaders), it
could be distinct and add to portfolio.
"""
import sys
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/xsec")
import xslib as xs
import numpy as np

print("XM05 — Momentum Acceleration (L_short - L_long)")
print("=" * 60)


def mom_accel(close, L_short, L_long):
    """Score = short-term return minus long-term return (causal). Higher = accelerating."""
    r_short = xs.past_return(close, L_short)
    r_long  = xs.past_return(close, L_long)
    return r_short - r_long


# --- 5 targeted backtests ---

# 1) Canonical config: all universe, L_short=20, L_long=60, H=10, LS
rep1 = xs.study_xs(
    "XM05_ALL_20_60",
    lambda P: mom_accel(P.close, 20, 60),
    universe="all", H=10, k=5, long_short=True
)
print(xs.fmt(rep1))
print("JSON:", xs.as_json(rep1))
print()

# 2) Majors universe (19 XS01 assets), same canonical L_short=20, L_long=60
rep2 = xs.study_xs(
    "XM05_MAJ_20_60",
    lambda P: mom_accel(P.close, 20, 60),
    universe="majors", H=10, k=5, long_short=True
)
print(xs.fmt(rep2))
print("JSON:", xs.as_json(rep2))
print()

# 3) All universe, shorter window: L_short=10, L_long=30 (faster acceleration signal)
rep3 = xs.study_xs(
    "XM05_ALL_10_30",
    lambda P: mom_accel(P.close, 10, 30),
    universe="all", H=10, k=5, long_short=True
)
print(xs.fmt(rep3))
print("JSON:", xs.as_json(rep3))
print()

# 4) All universe, L_short=20, L_long=60, longer holding period H=20
rep4 = xs.study_xs(
    "XM05_ALL_20_60_H20",
    lambda P: mom_accel(P.close, 20, 60),
    universe="all", H=20, k=5, long_short=True
)
print(xs.fmt(rep4))
print("JSON:", xs.as_json(rep4))
print()

# 5) All universe, longer windows: L_short=30, L_long=90 (medium-term acceleration)
rep5 = xs.study_xs(
    "XM05_ALL_30_90",
    lambda P: mom_accel(P.close, 30, 90),
    universe="all", H=10, k=5, long_short=True
)
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.get("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))
