"""SKH_R_EXPAND_study — final study() on the two best volatility-expansion configs. We use the project's HONEST study() harness. Because the expansion regime is a STRUCTURAL change (not expressible via SkyhookParams bands), we monkeypatch htf_features INSIDE skyhooklib's namespace to our expansion-features for the duration of each study, so study() runs the exact same leak-free FULL+HOLDOUT+fee-sweep+per-year machinery on our entries. This is safe: we only swap the feature builder (regime def); pattern/composer/entry/exit and all the eval code are unchanged. We restore the original after each study. """ from __future__ import annotations import sys sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/skyhook") import numpy as np import pandas as pd import skyhooklib as sk from src.strategies import skyhook as S from src.strategies.skyhook import SkyhookParams # import our feature builder from SKH_R_EXPAND import expand_htf_features ORIG_FEAT = S.htf_features def make_patched_features(cfg): def _feat(htf, p): return expand_htf_features(htf, p, **cfg) return _feat def study_expand(name, p, cfg): """Run sk.study with htf_features patched to the expansion regime defined by cfg.""" patched = make_patched_features(cfg) # skyhook_entries calls skyhook.htf_features via the module-level name S.htf_features. S.htf_features = patched try: rep = sk.study(name, p) caus = sk.causality(p, "BTC") caus_eth = sk.causality(p, "ETH") marg = sk.marginal(p) finally: S.htf_features = ORIG_FEAT return rep, (caus, caus_eth), marg if __name__ == "__main__": p = SkyhookParams(ptn_n=55, sl_atr=2.5, tp_atr=6.0) configs = { # best DD-cut + above-V1 full, balanced volume gate (maxDD 34%) "EXP_atr20vol20": dict(w_atr=20, k_atr=1.0, w_vol=20, k_vol=1.0), # best hold-out / no volume gate (minFull 0.81, DD 40%) "EXP_atr20volOFF": dict(w_atr=20, k_atr=1.0, w_vol=20, k_vol=0.0), } for name, cfg in configs.items(): print(f"\n########## {name} cfg={cfg} ##########") rep, (caus, caus_eth), marg = study_expand(name, p, cfg) print(sk.fmt(rep)) print(f"causality BTC={caus} ETH={caus_eth}") print(f"marginal: verdict={marg.get('marginal_verdict')} corr_full={marg.get('corr_full')}" f" blend_w25_uplift_hold={marg.get('blends',{}).get('w25',{}).get('uplift_hold')}") print(f" has_insample_edge={marg.get('has_insample_edge')} is_hedge={marg.get('is_hedge')}" f" robust_oos={marg.get('robust_oos')} clean_year_uplift={marg.get('clean_year_uplift')}" f" multicut_persistent={marg.get('multicut_persistent')}") v = rep["verdict"] print(f"VERDICT[{name}]: grade={v['grade']} minFull={v['min_asset_full_sharpe']}" f" minHold={v['min_asset_holdout_sharpe']} minTrades={v['min_trades']} feeOK={v['fee_survives']}")