"""SKH_P_LOCAL2 — refine: combine the two winning axes (ptn_n DD-cut + sl/tp hold-lift)
and CHECK MARGINAL clean-year(2025) uplift on the top few, since that is the true gate
(robust_oos requires clean_year_uplift>0.02 AND multicut_persistent)."""
from __future__ import annotations
import sys
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/skyhook")
import skyhooklib as sk
from src.strategies.skyhook import SkyhookParams

V1 = dict(ptn_n=55, sl_atr=2.5, tp_atr=6.0, vola_lo=35.0, vola_hi=95.0, vol_lo=0.0)

def evalp(**over):
    p = SkyhookParams(**{**V1, **over})
    out = {a: sk.run_asset(a, p, fee_rt=sk.FEE_RT) for a in ("BTC","ETH")}
    return dict(p=p, over=over,
                min_full=min(out[a]["full"]["sharpe"] for a in out),
                min_hold=min(out[a]["holdout"]["sharpe"] for a in out),
                min_tr=min(out[a]["full"]["n_trades"] for a in out),
                max_dd=max(out[a]["full"]["maxdd"] for a in out),
                btc_dd=out["BTC"]["full"]["maxdd"], eth_dd=out["ETH"]["full"]["maxdd"])

def row(tag, r):
    elig = (r["min_full"]>=0.5 and r["min_tr"]>=20 and r["min_hold"]>=0.5)
    print(f"{tag:<26} minFull={r['min_full']:+.2f} minHold={r['min_hold']:+.2f} "
          f"maxDD={r['max_dd']*100:>3.0f}% (b{r['btc_dd']*100:.0f}/e{r['eth_dd']*100:.0f}) "
          f"minTr={r['min_tr']:>3} {'OK' if elig else 'x'}")
    return r

print("=== SKH_P_LOCAL2 combine ptn_n x sl/tp (fee 0.10%RT) ===")
cands=[]
for ptn in (40, 45, 48):
    for sl,tp in ((2.0,6.0),(2.0,7.0),(2.25,6.0),(2.25,7.0),(2.5,7.0)):
        over=dict(ptn_n=ptn, sl_atr=sl, tp_atr=tp)
        cands.append((f"ptn{ptn}_sl{sl}_tp{tp}", row(f"ptn{ptn}_sl{sl}_tp{tp}", evalp(**over))))
# also ptn45 with exit-bar asymmetry that lifted hold
for ul,us in ((30,18),(24,18)):
    over=dict(ptn_n=45, uscitalong=ul, uscitashort=us)
    cands.append((f"ptn45_ex{ul}/{us}", row(f"ptn45_ex{ul}/{us}", evalp(**over))))

elig=[(t,r) for (t,r) in cands if r["min_full"]>=0.5 and r["min_tr"]>=20 and r["min_hold"]>=0.5]
elig.sort(key=lambda tr:(tr[1]["max_dd"], -round(tr[1]["min_hold"],3)))
print(f"\nEligible: {len(elig)} (sorted by lowest DD)")
for t,r in elig:
    print(f"  {t:<24} maxDD={r['max_dd']*100:.0f}% minHold={r['min_hold']:+.2f} minFull={r['min_full']:+.2f} over={r['over']}")

# Check MARGINAL clean-year uplift on the lowest-DD eligible + the best-hold eligible.
def marg_check(tag, over):
    p = SkyhookParams(**{**V1, **over})
    mg = sk.marginal(p)
    print(f"\n--- MARGINAL {tag} over={over} ---")
    print(f"  verdict={mg.get('marginal_verdict')} corr_full={mg.get('corr_full')} "
          f"robust_oos={mg.get('robust_oos')} multicut_persistent={mg.get('multicut_persistent')}")
    print(f"  clean_year_uplift={mg.get('clean_year_uplift')} jackknife_min={mg.get('jackknife_min_uplift')} "
          f"has_insample_edge={mg.get('has_insample_edge')} is_hedge={mg.get('is_hedge')}")
    print(f"  blend w25 uplift_hold={mg.get('blends',{}).get('w25',{}).get('uplift_hold')} "
          f"uplift_full={mg.get('blends',{}).get('w25',{}).get('uplift_full')}")
    return mg

# pick up to 4 distinct configs to marginal-check
seen=set(); checked=0
for t,r in elig:
    key=tuple(sorted(r["over"].items()))
    if key in seen: continue
    seen.add(key); marg_check(t, r["over"]); checked+=1
    if checked>=5: break
