"""XD01 — Low-skew / anti-lottery cross-sectional strategy.

Score = -roll_skew(ret, 60):  short high-skew "lottery" alts, long low-skew alts.
Rationale: lottery-preference premium — investors overpay for positive-skew assets
(right-tail lottery tickets), so they should earn lower returns; negative-skew assets
are underpriced relative to their systematic risk.

Grid (<=5 calls):
  1. Baseline: "majors" (19 XS01 universe), H=10, k=5, L/S
  2. Wider universe: "all" (~49 alts), H=10, k=5, L/S
  3. Vary rebalance period: "all", H=5, k=5, L/S (more frequent)
  4. Vary top-k: "all", H=10, k=7, L/S (more diversified)
  5. Combined: -skew60 + -skew30 blend (multi-horizon), "all", H=10, k=5, L/S
"""
import sys
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/xsec")
import xslib as xs
import numpy as np

SKEW_WIN = 60   # lookback for rolling skew (days)
SKEW_WIN2 = 30  # shorter lookback for blend


def score_anti_lottery(P, win=SKEW_WIN):
    """Anti-lottery score: negate rolling skew so LOW-skew assets score HIGH (long)."""
    sk = xs.roll_skew(P.ret, win)   # (n_days x n_assets); higher skew = lottery
    return -sk                       # higher = lower skew = long


def score_anti_lottery_blend(P, w1=SKEW_WIN, w2=SKEW_WIN2):
    """Multi-horizon blend of negated skews (cross-sectionally z-scored before blend)."""
    sk1 = xs.xs_zscore(-xs.roll_skew(P.ret, w1))
    sk2 = xs.xs_zscore(-xs.roll_skew(P.ret, w2))
    return 0.5 * sk1 + 0.5 * sk2


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

    # --- Run 1: majors universe, H=10, k=5, L/S ---
    print("Running XD01-v1: majors, H=10, k=5, L/S ...")
    rep1 = xs.study_xs(
        "XD01-v1-majors",
        lambda P: score_anti_lottery(P, 60),
        universe="majors",
        H=10, k=5, long_short=True,
    )
    print(xs.fmt(rep1))
    results.append(rep1)

    # --- Run 2: all universe, H=10, k=5, L/S ---
    print("\nRunning XD01-v2: all, H=10, k=5, L/S ...")
    rep2 = xs.study_xs(
        "XD01-v2-all",
        lambda P: score_anti_lottery(P, 60),
        universe="all",
        H=10, k=5, long_short=True,
    )
    print(xs.fmt(rep2))
    results.append(rep2)

    # --- Run 3: all, H=5 (more frequent rebalance), k=5, L/S ---
    print("\nRunning XD01-v3: all, H=5, k=5, L/S ...")
    rep3 = xs.study_xs(
        "XD01-v3-H5",
        lambda P: score_anti_lottery(P, 60),
        universe="all",
        H=5, k=5, long_short=True,
    )
    print(xs.fmt(rep3))
    results.append(rep3)

    # --- Run 4: all, H=10, k=7, L/S (more diversified) ---
    print("\nRunning XD01-v4: all, H=10, k=7, L/S ...")
    rep4 = xs.study_xs(
        "XD01-v4-k7",
        lambda P: score_anti_lottery(P, 60),
        universe="all",
        H=10, k=7, long_short=True,
    )
    print(xs.fmt(rep4))
    results.append(rep4)

    # --- Run 5: blend multi-horizon skew, all, H=10, k=5, L/S ---
    print("\nRunning XD01-v5: blend skew30+60, all, H=10, k=5, L/S ...")
    rep5 = xs.study_xs(
        "XD01-v5-blend",
        lambda P: score_anti_lottery_blend(P, 60, 30),
        universe="all",
        H=10, k=5, long_short=True,
    )
    print(xs.fmt(rep5))
    results.append(rep5)

    # --- Pick best config by: earns_slot > holdout sharpe > full sharpe > distinctness ---
    def rank_key(r):
        earns = int(r["earns_slot"])
        h_sh = r["holdout"].get("sharpe", -99)
        f_sh = r["full"]["sharpe"]
        distinct = 1.0 - abs(r["corr_xs01"] or 1.0)  # higher = more distinct
        verdict_score = {"ADDS": 3, "NEUTRAL": 2, "DILUTES": 1, "REDUNDANT": 0, "N/A": 0}.get(
            r["marginal"].get("verdict", "N/A"), 0)
        return (earns, verdict_score, h_sh, f_sh, distinct)

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