"""XR05 — Overreaction Reversal (mid-horizon)
IDEA: Score = -past_return(close, L) for L in {20, 30}.
Assets that ran up the most over the past 20-30 days are SHORTED (expected to mean-revert);
assets that dropped the most are LONGED. Pure cross-sectional contrarian on multi-week moves.

Grid (<= 5 calls):
  1. L=20, H=10, k=5, LS, universe=majors
  2. L=30, H=10, k=5, LS, universe=majors
  3. L=20, H=5,  k=5, LS, universe=majors  (faster rebal)
  4. blend -PR20 and -PR30 (mean z-score), H=10, k=5, LS, universe=majors
  5. blend -PR20 and -PR30, H=10, k=5, LS, universe=all  (broader universe)
"""
import sys
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/xsec")
import xslib as xs
import numpy as np

# ------------------------------------------------------------------
# Score helpers (causal: close[i] only uses data up to bar i)
# ------------------------------------------------------------------
def score_rev20(P):
    return -xs.past_return(P.close, 20)

def score_rev30(P):
    return -xs.past_return(P.close, 30)

def score_rev20_fast(P):
    return -xs.past_return(P.close, 20)

def score_blend_majors(P):
    z20 = xs.xs_zscore(-xs.past_return(P.close, 20))
    z30 = xs.xs_zscore(-xs.past_return(P.close, 30))
    return (z20 + z30) / 2.0

def score_blend_all(P):
    z20 = xs.xs_zscore(-xs.past_return(P.close, 20))
    z30 = xs.xs_zscore(-xs.past_return(P.close, 30))
    return (z20 + z30) / 2.0

# ------------------------------------------------------------------
# Grid
# ------------------------------------------------------------------
configs = [
    dict(name="XR05-REV20-H10-k5-majors",  fn=score_rev20,      universe="majors", H=10, k=5, long_short=True),
    dict(name="XR05-REV30-H10-k5-majors",  fn=score_rev30,      universe="majors", H=10, k=5, long_short=True),
    dict(name="XR05-REV20-H5-k5-majors",   fn=score_rev20_fast, universe="majors", H=5,  k=5, long_short=True),
    dict(name="XR05-BLENDz-H10-k5-majors", fn=score_blend_majors, universe="majors", H=10, k=5, long_short=True),
    dict(name="XR05-BLENDz-H10-k5-all",    fn=score_blend_all,  universe="all",    H=10, k=5, long_short=True),
]

results = []
for c in configs:
    print(f"\nRunning {c['name']} ...")
    rep = xs.study_xs(
        c["name"],
        c["fn"],
        universe=c["universe"],
        H=c["H"],
        k=c["k"],
        long_short=c["long_short"],
    )
    print(xs.fmt(rep))
    results.append(rep)

# ------------------------------------------------------------------
# Pick best config: earns_slot first, then hold-out sharpe, then distinctness
# ------------------------------------------------------------------
def _sort_key(r):
    earns = int(r["earns_slot"])
    hold_sh = r["holdout"].get("sharpe", -99)
    corr_xs01 = abs(r["corr_xs01"] or 1.0)
    return (earns, hold_sh, -corr_xs01)

best = max(results, key=_sort_key)
print("\n" + "="*60)
print("BEST CONFIG:")
print(xs.fmt(best))
print("JSON:", xs.as_json(best))
