"""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()