"""OOS slice metrics for v15/v18/v19 candidate variants.

Splits the 119d window into:
  TRAIN: 2025-11-11 .. 2025-12-31 (~36 td)
  TEST:  2026-01-01 .. 2026-05-04 (~83 td)

Computes return, MaxDD, Sharpe, WR, PF on each slice.
A variant that holds up in TEST as well as in TRAIN is the most likely to be real.
"""
from __future__ import annotations

import json
import math
import sys
from pathlib import Path


def _load(path: str) -> list[dict]:
    with open(path) as f:
        return json.load(f)["daily_results"]


def _max_dd(equity: list[float]) -> float:
    peak = equity[0]
    worst = 0.0
    for eq in equity:
        if eq > peak:
            peak = eq
        if peak > 0:
            dd = (eq - peak) / peak
            if dd < worst:
                worst = dd
    return worst


def _slice_metrics(label: str, daily: list[dict], date_pred) -> dict:
    sliced = [d for d in daily if date_pred(d["date"])]
    if not sliced:
        return {"label": label, "n_days": 0}

    initial = 10_000.0
    eq = [initial]
    for d in sliced:
        eq.append(eq[-1] + d["day_pnl"])
    final = eq[-1]
    ret = (final - initial) / initial
    dd = _max_dd(eq)

    daily_ret = [d["day_pnl"] / initial for d in sliced]
    n = len(daily_ret)
    mean = sum(daily_ret) / n
    var = sum((r - mean) ** 2 for r in daily_ret) / n if n > 1 else 0
    sd = math.sqrt(var)
    sharpe = (mean / sd) * math.sqrt(252) if sd > 0 else 0

    all_trades = [t for d in sliced for t in d["trades"]]
    wins = [t for t in all_trades if t["pnl"] > 0]
    losses = [t for t in all_trades if t["pnl"] <= 0]
    wr = len(wins) / len(all_trades) if all_trades else 0
    gross_w = sum(t["pnl"] for t in wins)
    gross_l = -sum(t["pnl"] for t in losses)
    pf = gross_w / gross_l if gross_l > 0 else float("inf") if gross_w > 0 else 0

    return {
        "label": label,
        "n_days": n,
        "return": ret,
        "max_dd": dd,
        "sharpe": sharpe,
        "wr": wr,
        "pf": pf,
        "n_trades": len(all_trades),
    }


def main() -> int:
    runs_dir = Path("runs/intraday/topgainer_holdtoclose_v1")
    candidates = [
        ("v1_recheck", "v1 baseline"),
        ("v7_strict_entry", "v7 strict (top5/3%/$10M)"),
        ("v15_strict_top10", "v15 strict+top10"),
        ("v18_top10_pmtight", "v18 v15+PM tighten"),
        ("v19_top15", "v19 strict+top15"),
    ]
    train_pred = lambda d: d <= "2025-12-31"
    test_pred = lambda d: d >= "2026-01-01"

    print(f"\n{'variant':<28} {'slice':<8} {'days':>5} {'return':>8} {'DD':>8} {'Sharpe':>7} {'WR':>6} {'PF':>5} {'trades':>6}")
    print("-" * 90)
    for fname, label in candidates:
        path = runs_dir / f"{fname}.json"
        if not path.exists():
            continue
        daily = _load(str(path))
        for slice_label, pred in [("FULL", lambda d: True), ("TRAIN", train_pred), ("TEST", test_pred)]:
            m = _slice_metrics(slice_label, daily, pred)
            if m.get("n_days", 0) == 0:
                continue
            print(f"{label:<28} {slice_label:<8} {m['n_days']:>5} {m['return']:>+8.4f} {m['max_dd']:>+8.4f} {m['sharpe']:>7.2f} {m['wr']:>6.3f} {m['pf']:>5.2f} {m['n_trades']:>6}")
        print()

    return 0


if __name__ == "__main__":
    raise SystemExit(main())
