"""XS02b — Long-mom + short-rev multi-horizon
Score = xs_zscore(past_return(close, 90)) + xs_zscore(-past_return(close, 5))

Long-term winners (90d) that have recently dipped (5d reversal).
This is structurally distinct from plain XS01 momentum because it FADES the very-recent move
while keeping the intermediate-term trend, blending momentum with mean-reversion.

Grid: universe x H x k (<=5 study_xs calls).
"""

import sys
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/xsec")
import xslib as xs
import numpy as np


def score_xs02b(P):
    """Score = xs_zscore(90d mom) + xs_zscore(-5d return).
    Higher = long: intermediate-term winner AND short-term dipper.
    Fully causal: past_return(close, L) at row i uses close[i-L..i].
    """
    mom_long  = xs.xs_zscore(xs.past_return(P.close, 90))   # 90d momentum
    rev_short = xs.xs_zscore(-xs.past_return(P.close, 5))    # 5d reversal (negate: dip = good)
    return mom_long + rev_short


if __name__ == "__main__":
    results = []

    # Run 1: majors, H=10, k=5, L/S — canonical XS01-like setup but new signal
    r1 = xs.study_xs("XS02b_maj_H10_k5_LS", score_xs02b,
                     universe="majors", H=10, k=5, long_short=True, target_vol=0.20)
    print(xs.fmt(r1))
    print("JSON:", xs.as_json(r1))
    results.append(r1)

    # Run 2: all (49 alts), H=10, k=5, L/S — broader universe
    r2 = xs.study_xs("XS02b_all_H10_k5_LS", score_xs02b,
                     universe="all", H=10, k=5, long_short=True, target_vol=0.20)
    print(xs.fmt(r2))
    print("JSON:", xs.as_json(r2))
    results.append(r2)

    # Run 3: majors, H=5, k=5, L/S — faster rebalance
    r3 = xs.study_xs("XS02b_maj_H5_k5_LS", score_xs02b,
                     universe="majors", H=5, k=5, long_short=True, target_vol=0.20)
    print(xs.fmt(r3))
    print("JSON:", xs.as_json(r3))
    results.append(r3)

    # Run 4: all, H=5, k=7, L/S — broader universe, faster, wider basket
    r4 = xs.study_xs("XS02b_all_H5_k7_LS", score_xs02b,
                     universe="all", H=5, k=7, long_short=True, target_vol=0.20)
    print(xs.fmt(r4))
    print("JSON:", xs.as_json(r4))
    results.append(r4)

    # Run 5: majors, H=10, k=5, long-only — for comparison
    r5 = xs.study_xs("XS02b_maj_H10_k5_LO", score_xs02b,
                     universe="majors", H=10, k=5, long_short=False, target_vol=0.20)
    print(xs.fmt(r5))
    print("JSON:", xs.as_json(r5))
    results.append(r5)

    # ---- Summary ----
    print("\n\n=== XS02b GRID SUMMARY ===")
    for r in results:
        f = r["full"]
        h = r["holdout"]
        m = r.get("marginal", {})
        print(f"  {r['name']:35s}  FULL Sh={f['sharpe']:+.2f} DD={f['maxdd']:.1%}"
              f"  HOLD Sh={h['sharpe']:+.2f}"
              f"  corr_xs01={r.get('corr_xs01',float('nan')):+.2f}"
              f"  verdict={m.get('verdict','?')}"
              f"  earns_slot={r.get('earns_slot','?')}")

    # Pick best by: earns_slot > hold-out > corr distinctness
    def sort_key(r):
        es = 1 if r.get("earns_slot") else 0
        mv = 1 if r.get("marginal", {}).get("verdict") == "ADDS" else 0
        ho = r["holdout"]["sharpe"]
        cxs = abs(r.get("corr_xs01", 1.0))
        return (es, mv, ho, -cxs)

    best = max(results, key=sort_key)
    print(f"\nBEST CONFIG: {best['name']}")
    print(xs.fmt(best))
    print("JSON:", xs.as_json(best))
