"""XV01 — Low Realized-Volatility Anomaly
MECHANISM: Score = -roll_std(ret, W)  (long low-vol / short high-vol alts).
The low-vol anomaly: lower-volatility assets tend to outperform on a risk-adjusted basis.
Grid: W in {20, 30, 60}; universe in {all, majors}; long-short AND long-only.
Goal: find a DISTINCT signal from XS01 (plain momentum) that ADDS to the live portfolio.
"""
import sys
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/xsec")
import xslib as xs
import numpy as np

print("XV01 — Low Realized-Volatility Anomaly")
print("=" * 60)

# --- 5 targeted backtests ---

# 1) Full universe, W=20 (short-term vol), LS — baseline low-vol on all alts
rep1 = xs.study_xs(
    "XV01_ALL_W20_LS",
    lambda P: -xs.roll_std(P.ret, 20),
    universe="all", H=10, k=5, long_short=True
)
print(xs.fmt(rep1))
print("JSON:", xs.as_json(rep1))
print()

# 2) Full universe, W=30, LS — medium-window vol (the main hypothesis)
rep2 = xs.study_xs(
    "XV01_ALL_W30_LS",
    lambda P: -xs.roll_std(P.ret, 30),
    universe="all", H=10, k=5, long_short=True
)
print(xs.fmt(rep2))
print("JSON:", xs.as_json(rep2))
print()

# 3) Full universe, W=60, LS — longer-window vol
rep3 = xs.study_xs(
    "XV01_ALL_W60_LS",
    lambda P: -xs.roll_std(P.ret, 60),
    universe="all", H=10, k=5, long_short=True
)
print(xs.fmt(rep3))
print("JSON:", xs.as_json(rep3))
print()

# 4) Majors only (19), W=30, LS — smaller universe, less noise
rep4 = xs.study_xs(
    "XV01_MAJORS_W30_LS",
    lambda P: -xs.roll_std(P.ret, 30),
    universe="majors", H=10, k=5, long_short=True
)
print(xs.fmt(rep4))
print("JSON:", xs.as_json(rep4))
print()

# 5) Full universe, W=30, long-only top-k (lowest vol, long only)
#    The "defensive" alt selection: pick alts with lowest realized vol
rep5 = xs.study_xs(
    "XV01_ALL_W30_LO",
    lambda P: -xs.roll_std(P.ret, 30),
    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 full 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"] if r["corr_xs01"] is not None else 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))
