"""XVa2 — Cross-sectional RSI reversal.

Idea: compute RSI(14) per asset; score = -RSI so oversold assets go long (low RSI = long).
This is a mean-reversion signal: buy the most oversold, short the most overbought.

Grid (<=5 calls):
  1. RSI(14) reversal, majors, H=10, k=5, LS
  2. RSI(14) reversal, all, H=10, k=5, LS
  3. RSI(14) reversal, all, H=5, k=5, LS  (faster rebalance)
  4. RSI(7) reversal, all, H=5, k=5, LS   (shorter RSI period)
  5. RSI(14) reversal, all, H=10, k=7, LS  (wider basket)
"""
import sys
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/xsec")
import xslib as xs
import numpy as np
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/alt")
import altlib as al


def rsi_score(close: np.ndarray, win: int = 14) -> np.ndarray:
    """Compute -RSI(win) per asset column causally. Returns (n_days, n_assets) score matrix."""
    n, A = close.shape
    out = np.full((n, A), np.nan)
    for a in range(A):
        out[:, a] = -al.rsi(close[:, a], win)
    return out


results = []

# 1. RSI(14) on majors, H=10, k=5, LS
rep1 = xs.study_xs(
    "XVa2-RSI14-majors-H10-k5",
    lambda P: rsi_score(P.close, 14),
    universe="majors", H=10, k=5, long_short=True
)
print(xs.fmt(rep1))
results.append(rep1)

# 2. RSI(14) on all, H=10, k=5, LS
rep2 = xs.study_xs(
    "XVa2-RSI14-all-H10-k5",
    lambda P: rsi_score(P.close, 14),
    universe="all", H=10, k=5, long_short=True
)
print(xs.fmt(rep2))
results.append(rep2)

# 3. RSI(14) on all, H=5, k=5, LS (faster rebalance)
rep3 = xs.study_xs(
    "XVa2-RSI14-all-H5-k5",
    lambda P: rsi_score(P.close, 14),
    universe="all", H=5, k=5, long_short=True
)
print(xs.fmt(rep3))
results.append(rep3)

# 4. RSI(7) on all, H=5, k=5, LS (shorter RSI)
rep4 = xs.study_xs(
    "XVa2-RSI7-all-H5-k5",
    lambda P: rsi_score(P.close, 7),
    universe="all", H=5, k=5, long_short=True
)
print(xs.fmt(rep4))
results.append(rep4)

# 5. RSI(14) on all, H=10, k=7, LS (wider basket)
rep5 = xs.study_xs(
    "XVa2-RSI14-all-H10-k7",
    lambda P: rsi_score(P.close, 14),
    universe="all", H=10, k=7, long_short=True
)
print(xs.fmt(rep5))
results.append(rep5)

# Pick best by: earns_slot first, then hold-out Sharpe, then distinctness from XS01
def score_rep(r):
    earns = 1 if r["earns_slot"] else 0
    hold_sh = r["holdout"].get("sharpe", -999) or -999
    xs01_corr = abs(r["corr_xs01"] or 1.0)
    full_sh = r["full"].get("sharpe", -999) or -999
    return (earns, hold_sh, full_sh, -xs01_corr)

best = max(results, key=score_rep)

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