Files
PythagorasGoal/docs/diary/2026-06-23-skyhook.md
Adriano Dal Pastro 8d1fe173f7 feat(portfolio): wire SKH01-V2-DD sleeve @25% effective -> 4-sleeve book
Add Skyhook (SKH01_V2_DD) as a portfolio sleeve. Effective weight 25%: the three
existing sleeves scaled into the remaining 0.75 keeping their 55:25:20 ratio
(TP01 41.25% / XS01 18.75% / VRP01 15% / SKH01 25%).

_skyhook_returns(): 50/50 BTC+ETH daily series of the dual-TF regime+breakout engine
(causal, net 0.10% RT), same convention as the marginal lens.

Portfolio impact (run_portfolio.py), 3-sleeve -> 4-sleeve:
  FULL Sharpe 1.68 -> 2.13 (+0.45), FULL maxDD 14.3% -> 7.8% (halved)
  HOLD-OUT Sharpe 1.63 -> 2.30 (+0.67), HOLD-OUT maxDD ~3.5% (flat)
  Positive every year 2019-26 (annual DD <=7.8%) vs buy&hold 50/50 FULL Sh 0.93 / DD 76%.

Skyhook is quasi-orthogonal (corr ~0.09 to TP01) so it lifts Sharpe AND cuts DD.
Research portfolio (fixed weights, no real rebalancing cost at $600; Skyhook daily
Sharpe is the step-marked lens convention) -> forward-monitor, not deploy.
Tests: 25 pass (skyhook 8 + portfolio 7 + vrp 4 + trend 6). Diary + CLAUDE.md updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:22:15 +00:00

10 KiB
Raw Permalink Blame History

2026-06-23 — SKH01 "Skyhook": porting onesto del sistema ES dual-timeframe su BTC/ETH

Branch: strategy_skyhook. Engine: src/strategies/skyhook.py. Harness: scripts/research/skyhook/skyhooklib.py. Test: tests/test_skyhook.py (5 pass). Ricerca: scripts/research/skyhook/{sweep,grid,check_v1}.py + runs/.

Il brief

Sistema "Skyhook" (origine ES / E-mini S&P, genetico, a doppio timeframe), da portare su crypto:

  • data2 = 690 min (segnale), data1 = 230 min (esecuzione). NB 690 = 3 × 230.
  • NON trend-follower: entra solo quando coincidono (a) un regime di volatilità/volume e (b) un pattern di breakout.
  • Pipeline per barra: indicatori (BuzVola su ATR, BuzVolume su volume, tipo-Chande 0-100) → fasce regime → pattern (Donchian/breakout su data2) → composer (regime AND pattern) → ingresso (max 1/giorno, stop-and-reverse) → uscite (time-based asimmetrico uscitalong=24 / uscitashort=18 + stop/profit).
  • Ancore demo: trend lineare → BuzVola=50 (vol steady → neutro), BuzVolume=100 (volume in rampa).

Ricostruzione (fedele + onesta)

  • Resample dal feed 5m certificato con origin='epoch': 230 min = 46×5m, 690 min = 138×5m, e i confini 690 sono un sottoinsieme dei confini 230 → una barra HTF chiude esattamente su una chiusura LTF. Merge HTF→LTF causale: merge_asof backward sulla chiusura HTF (≤ chiusura LTF), così una barra HTF è usata solo quando è davvero chiusa. (~2287 barre/anno LTF, ~762 HTF.)
  • BuzVola / BuzVolume = chande01 (Chande Momentum Oscillator normalizzato 0-100): serie steady → 50, rampa-su → 100, rampa-giù → 0. Le ancore demo sono soddisfatte a livello di indicatore (è la lettura fedele: "vol steady → neutro"). NB: l'EMA-ATR su un linspace sintetico dà 100 per drift di warm-up/floating-point, non per comportamento reale — su BTC reale BuzVola oscilla intorno a 50 (EMA-ATR vs SMA-ATR corr 0.90).
  • Pattern = Donchian breakout leak-free (shift(1)) su HTF, ptn_n barre (default 13 da 13/13/1).
  • Regime = bande-soglia tunabili su BuzVola/BuzVolume (i magici interi 4/3/2 - 4/2/2 non sono nel brief; ricostruiti come [vola_lo,vola_hi] × [vol_lo,vol_hi]).
  • Composer = regime AND pattern. Ingressi ≤1/giorno (prima barra qualificante).
  • Uscite: time-based asimmetrico (uscitalong/uscitashort barre LTF) + hard stop/profit. Lo "stop 2000 / profit 5000" in $ del sistema ES → multipli di ATR LTF (scale-free): default sl_atr=2.0, tp_atr=5.0 (~ rapporto 40:100 pt ES), con modalità pct alternativa.
  • Engine espresso come entries {dir,tp,sl,max_bars} per backtest_signals (motore onesto del progetto: TP/SL intrabar, max_bars, non-overlap). Causalità verificata con prefix-recompute (0 mismatch).

Baseline → V1 (lever scout + grid, inline, veloce)

  • Baseline (default 13/13, sl2/tp5, vola[35,95], vol_lo50): causale, fee-surviving, FULL Sharpe BTC +0.91 / ETH +0.64, ma HOLD-OUT debole (BTC 0.09 / ETH +0.17) → FAIL del gate onesto.
  • Lever scout (sweep.py): gli short servono (long_only → HOLD 0.52); il regime gate conta (togliere la banda vola → HOLD 0.80); il floor di volume a 50 frenava l'hold-out (vol_lo=40 o 0 → PASS); breakout più lento (ptn_n=55) e stop più larghi (sl2.5/tp6) alzano l'hold-out.
  • Grid combinato (grid.py): vincitrice SKH01-V1 SkyhookParams(ptn_n=55, sl_atr=2.5, tp_atr=6.0, vola_lo=35, vola_hi=95, vol_lo=0.0):
    • min-asset FULL +0.69, HOLD-OUT +0.64 (BTC 0.64 / ETH 0.64), PASS, fee-surviving a 0.30%RT.
    • BTC FULL +0.69/+275% DD49% ; ETH FULL +1.01/+871% DD31% ; entrambi HOLD-OUT positivi.
    • Marginal vs TP01 = ADDS e regge i gate induriti: corr 0.06 (ortogonale, NON trend-beta), has_insample_edge=True (Sharpe in-sample standalone 1.15), is_hedge=False, multi-cut persistente. Blend 0.75·TP01 + 0.25·SKH01: HOLD Sharpe 0.31 → 0.74 (+0.44), DD 11.9%; blend 50/50 HOLD 0.88, DD 17.8%.
    • Unico sub-gate fallito: clean_year_uplift +0.014 (sotto 0.02) → earns_slot=False per un pelo, nonostante tutto il resto sia forte. Debolezza principale: DD standalone alto (40-49%).

→ SKH01 è un diversificatore quasi-ortogonale reale (non un TP01 travestito): da solo è volatile, ma come sleeve al 25% migliora moltissimo l'hold-out del portafoglio a DD bassissimo.

Onda 1 (skyhook-improve, 30 agenti) — winner intermedio

Famiglie: param (RR, ptn_n, regime bands, exit bars, chande, local), regime-redef (percentile, realized-vol, vol-expansion, LTF), pattern (confirmation, ROC, Keltner, NR, dual), exit + overlay, ognuna verificata da 2 scettici. Risultato: winner intermedio SkyhookParams(ptn_n=45, sl_atr=2.5, tp_atr=7.0, uscitalong=24, uscitashort=16, vola_lo=35, vola_hi=95, vol_lo=0)minFull +0.83, minHold +0.81 (vs V1 +0.69/+0.64), causale, fee-surviving 0.30%RT, marginal ADDS (corr 0.05, has_insample_edge, robust_oos, multicut, clean_year_uplift +0.37), blend w25 uplift_hold +0.58. MA standalone maxDD ancora 34% (BTC) / 31% (ETH) → l'unico goal mancato era il DD<30%.

Onda 2 (skyhook-improve-v2, 14 famiglie DD-reduction) — SKH01-V2-DD vince

Obiettivo: tagliare il DD standalone <30% tenendo hold-out + earns_slot, e alzare l'uplift di portafoglio. 14 famiglie (ensemble param/struct, vol-target, DD kill-switch, RR/stop grid, regime tight, percentile, vol-expansion, breakout confirmation, dual-TF, asimmetria L/S, cadenza, chande, Keltner), ognuna verificata da 2 scettici avversariali (window-luck/multicut/jackknife + causalità/fee/plateau/overfit). Esito: il winner intermedio cade. Nuovo campione SKH01-V2-DD (famiglia ASYM_LS, src/strategies/skyhook.py:SKH01_V2_DD, run runs/SKH2_ASYM_LS.py):

  • Config: stesso SEGNALE del winner (ptn_n=45, vola_lo=35, vola_hi=95, vol_lo=0, exit-bars 24/16) ma EXIT commutati da ATR a percentuale fissa ASIMMETRICA — long sl=4% / tp=10%, short sl=2% (più stretto) / tp=8%. Motivazione meccanica: in crypto lo short si fa steamrollare da uno spike vola e lo stop-ATR si allarga lasciando correre la perdita → il %-SL stretto sullo short cappa la perdita per-trade che FORMA il maxDD. (Implementato come override per-direzione nel motore, backward-compatible: campi *_short=None → comportamento simmetrico invariato.)
  • Numeri veri (verificati indipendentemente via sk.study(SKH01_V2_DD)): standalone maxDD BTC 21.4% / ETH 27.4% (<30% ✓, vs 34.4/30.5 del winner) — goal RAGGIUNTO; minFull +0.99, minHold +1.26; causalità 0/400 entrambi gli asset; fee@0.30%RT BTC +1.05 / ETH +0.80 (positiva anche a 0.40%). Marginal vs TP01 ADDS (corr 0.09, has_insample_edge, is_hedge=False, robust_oos, multicut, clean_year_uplift +0.57). Blend 0.75·TP01 + 0.25·SKH: uplift_hold +0.87 (vs +0.58 del winner); blend 50/50: full 1.84 / hold 1.59 / DD 10.7%. earns_slot=True, beats_winner=True. Plateau reale (i vicini Spct_mb14/16 sl2% tengono DD 27-28%), non knife-edge. Entrambi gli scettici: holds_up=True, confidence high, killer_finding=null.

Top-3 dell'onda 2 (criteri onesti):

# Famiglia maxDD (BTC/ETH) minHold w25 uplift_hold Verifica
1 ASYM_LS → SKH01-V2-DD 27.4% (21.4/27.4) +1.26 +0.87 2/2 high, killer=null
2 ENS_STRUCT (3-regime ensemble) 22.9% (21.2/22.8) +1.00 +0.67 2/2 high — ma 3 motori da eseguire
3 TPSL_DD (%-SL/TP hard) 28.0% (28/25.5) +1.11 +0.75 1/1 (rate-limit) — caveat hedge-like

Lezioni anti-DD:

  • Ha funzionato (STRUTTURA dell'exit, non i parametri): cambiare il MECCANISMO di uscita — %-SL hard, asimmetria L/S, o ensemble di exit/regime diversi (decorrelazione). Il DD del winner nasce dalla coda intra-trade negli spike ATR; il %-SL la cappa.
  • NON ha funzionato (la leva non raggiunge il DD vincolante): DD kill-switch entry-only (sopprime solo le NUOVE entry, non chiude il trade aperto che forma il maxDD → floor 33-36%); vol-target causale (DD<30 e uplift≥0.55 mutuamente esclusivi; cap>1 PEGGIORA il DD levereggiando nel pre-crash); cadenza/FREQ (accorciare gli hold short fa esplodere ETH a 50-66%); dual-TF (LTF è resample dello stesso prezzo → quasi-tautologico, DD invariato).
  • Bocciato dagli scettici come overfit: PATTERN_CONF (sub-30 solo a vola_lo=45, knife-edge: sl_atr ±0.5 → ETH 40-47%; la conferma "close_loc" da sola NON taglia il DD). Esempio canonico del perché serviva la doppia verifica.
  • Non promuovibili: PCTL_DD (numeri spettacolari ma 0 verifiche, le 2 sono morte per rate-limit → forward-monitor, non fidato); ENS_PARAM / TPSL_DD (battono i gate ma uplift recency/hedge-loaded, concentrato nei regimi TP01-down → forward-monitor).

Promozione (questa sessione): SKH01_V2_DD canonico nel motore + override exit-short asimmetrici (backward-compatible, V1/winner invariati) + 3 test nuovi (8/8 pass).

Sleeve cablato @0.25 effettivo (src/portfolio/sleeves.skyhook_sleeveactive_sleeves): i tre sleeve preesistenti scalati nel restante 0.75 mantenendo il rapporto 55:25:20 → TP01 41.25% / XS01 18.75% / VRP01 15% / SKH01 25%. Report del portafoglio (4 sleeve, run_portfolio.py):

FULL Sharpe FULL DD HOLD-OUT Sharpe HOLD-OUT DD
3 sleeve (TP01+XS01+VRP01) 1.68 14.3% 1.63 3.4%
+ SKH01 @25% 2.13 7.8% 2.30 3.5%
Δ +0.45 6.5pt +0.67 ~0

→ aggiungere Skyhook alza lo Sharpe full +0.45 e DIMEZZA il DD full (14.3→7.8%), e alza l'hold-out +0.67 a DD invariato. Portafoglio combinato: FULL Sh 2.13 / ret +365% / DD 7.8%, HOLD Sh 2.30 / DD 3.5%, positivo ogni anno (2019-26, DD annuo ≤7.8%) vs buy&hold 50/50 FULL Sh 0.93 / DD 76%.

Caveat onesti / NON deploy: è un portafoglio di ricerca (peso fisso, no costi di ribilanciamento reale a $600; lo Sharpe daily-step di Skyhook è la convenzione del lens). ETH DD standalone 27.4% ha margine sottile vs 30%. Prima di un eventuale deploy: ri-verificare la causalità sul codice di esecuzione reale (qui è l'harness di ricerca) e i costi del book a 230m (ribilanciamento più frequente del resto). XS01/VRP01 restano STAT-MODE/lead. Per ora: research win + sleeve cablato, forward-monitor.