"""SKH_P_REGIME — regime-band sweep on the V1 base.

Search bands: vola_lo in {20,30,35,45}, vola_hi in {88,95,100},
              vol_lo in {0,30,45,55},  vol_hi in {80,100}.
Find the combo that lifts min HOLD-OUT and is a PLATEAU (neighbors also good).
Compare to V1: SkyhookParams(ptn_n=55, sl_atr=2.5, tp_atr=6.0, vola_lo=35, vola_hi=95, vol_lo=0.0)
  -> minFull +0.69, minHold +0.64.
"""
from __future__ import annotations
import sys, itertools
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/skyhook")
import skyhooklib as sk
from src.strategies.skyhook import SkyhookParams

ASSETS = ("BTC", "ETH")

# V1 base (everything except the regime bands stays fixed)
BASE = dict(ptn_n=55, sl_atr=2.5, tp_atr=6.0)

VOLA_LO = [20, 30, 35, 45]
VOLA_HI = [88, 95, 100]
VOL_LO  = [0, 30, 45, 55]
VOL_HI  = [80, 100]


def mk(vlo, vhi, vol_lo, vol_hi):
    return SkyhookParams(vola_lo=vlo, vola_hi=vhi, vol_lo=vol_lo, vol_hi=vol_hi, **BASE)


def eval_combo(vlo, vhi, vol_lo, vol_hi):
    p = mk(vlo, vhi, vol_lo, vol_hi)
    res = {}
    for a in ASSETS:
        r = sk.run_asset(a, p, sk.FEE_RT)
        res[a] = r
    min_full = min(res[a]["full"]["sharpe"] for a in ASSETS)
    min_hold = min(res[a]["holdout"]["sharpe"] for a in ASSETS)
    min_tr   = min(res[a]["full"]["n_trades"] for a in ASSETS)
    max_dd   = max(res[a]["full"]["maxdd"] for a in ASSETS)
    return dict(vlo=vlo, vhi=vhi, vol_lo=vol_lo, vol_hi=vol_hi,
                min_full=min_full, min_hold=min_hold, min_tr=min_tr, max_dd=max_dd,
                btc_hold=res["BTC"]["holdout"]["sharpe"], eth_hold=res["ETH"]["holdout"]["sharpe"],
                btc_full=res["BTC"]["full"]["sharpe"], eth_full=res["ETH"]["full"]["sharpe"])


def main():
    rows = []
    combos = list(itertools.product(VOLA_LO, VOLA_HI, VOL_LO, VOL_HI))
    print(f"Sweeping {len(combos)} band combos x 2 assets = {len(combos)*2} run_asset calls")
    for vlo, vhi, vol_lo, vol_hi in combos:
        rows.append(eval_combo(vlo, vhi, vol_lo, vol_hi))

    # rank by min HOLD-OUT (subject to minFull>=0.5 and >=20 trades both assets)
    valid = [r for r in rows if r["min_full"] >= 0.5 and r["min_tr"] >= 20]
    valid.sort(key=lambda r: r["min_hold"], reverse=True)

    print("\n=== TOP 15 by min HOLD-OUT (minFull>=0.5, minTrades>=20) ===")
    print(f"{'vlo':>4}{'vhi':>5}{'vol_lo':>7}{'vol_hi':>7}  {'minF':>6}{'minH':>6}{'minTr':>6}{'maxDD':>7}  {'btcH':>6}{'ethH':>6}")
    for r in valid[:15]:
        print(f"{r['vlo']:>4}{r['vhi']:>5}{r['vol_lo']:>7}{r['vol_hi']:>7}  "
              f"{r['min_full']:>6.2f}{r['min_hold']:>6.2f}{r['min_tr']:>6}{r['max_dd']*100:>6.0f}%  "
              f"{r['btc_hold']:>6.2f}{r['eth_hold']:>6.2f}")

    # full table sorted for plateau inspection (group by lo/hi neighbors)
    rows_sorted = sorted(rows, key=lambda r: r["min_hold"], reverse=True)
    print("\n=== ALL combos by min HOLD-OUT ===")
    for r in rows_sorted:
        flag = "" if (r["min_full"] >= 0.5 and r["min_tr"] >= 20) else "  (low-full/trades)"
        print(f"  vlo={r['vlo']:>3} vhi={r['vhi']:>3} vol_lo={r['vol_lo']:>3} vol_hi={r['vol_hi']:>3} | "
              f"minF={r['min_full']:+.2f} minH={r['min_hold']:+.2f} tr={r['min_tr']:>3} DD={r['max_dd']*100:.0f}%{flag}")

    if not valid:
        print("\nNo valid combo (minFull>=0.5 & >=20 trades). Best raw:")
        print(rows_sorted[0])
        return

    # plateau check: for the top combo, look at neighbors in the grid
    top = valid[0]
    print(f"\n=== WINNER: vlo={top['vlo']} vhi={top['vhi']} vol_lo={top['vol_lo']} vol_hi={top['vol_hi']} ===")
    print(f"  minFull={top['min_full']:+.2f} minHold={top['min_hold']:+.2f} minTr={top['min_tr']} maxDD={top['max_dd']*100:.0f}%")

    # neighbor plateau: same vol_lo/vol_hi, vary vola_lo/vola_hi to adjacent grid values
    def find(vlo, vhi, vol_lo, vol_hi):
        for r in rows:
            if r["vlo"]==vlo and r["vhi"]==vhi and r["vol_lo"]==vol_lo and r["vol_hi"]==vol_hi:
                return r
        return None
    print("\n  Plateau neighbors (min HOLD-OUT):")
    for vlo in VOLA_LO:
        for vhi in VOLA_HI:
            r = find(vlo, vhi, top['vol_lo'], top['vol_hi'])
            if r:
                mark = " <-- WIN" if (vlo==top['vlo'] and vhi==top['vhi']) else ""
                print(f"    vola_lo={vlo:>3} vola_hi={vhi:>3}: minH={r['min_hold']:+.2f} minF={r['min_full']:+.2f}{mark}")

    # final study + causality + marginal on the winner
    p = mk(top['vlo'], top['vhi'], top['vol_lo'], top['vol_hi'])
    print("\n=== STUDY (winner) ===")
    rep = sk.study(f"SKH_P_REGIME_vlo{top['vlo']}_vhi{top['vhi']}_vollo{top['vol_lo']}_volhi{top['vol_hi']}", p)
    print(sk.fmt(rep))
    print("\ncausality:", sk.causality(p))
    print("\nmarginal:", sk.marginal(p))
    print("\nas_json:", sk.as_json(rep))


if __name__ == "__main__":
    main()
