From ba5ec7bd6be086f4b007bd47f31d01e4d89e198c Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Thu, 11 Jun 2026 10:00:48 +0000 Subject: [PATCH] docs: aggiorna strategie_attive.html + CLAUDE/TODO a v1.1.20 (XS01, real-truth, 19 sleeve) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - make_strategy_doc: nuova famiglia XSEC — card XS01 (meccanismo, dispersion-gate disp_min=0.0313, gate PORT06 OOS 10.07->10.37) con grafico book+gate e tabella per anno (engine canonico ungated); pesi aggiornati a 19 sleeve (5.69/5.26/2.94%); header con real-truth ledger e 4 book paper; bullet metodologia real-truth; ripuliti i riferimenti 'oggi' (EXIT-16 su DIP01, fix punto-10 SH01) - strategie_attive.html rigenerato: v1.1.20, backtest canonico FULL Sharpe 7.34 / DD 3.46% — OOS Sharpe 10.07 / DD 1.48% (19 sleeve, XS01 incluso) - CLAUDE.md: sezione XS01 (famiglia XSEC, gate, dispersion-gate live-only, FC01 scartata), copertura reale 15/19, varianti gioco options/session/grid in struttura - TODO.md: stato esecuzione aggiornato (6 pairs, XS01 paper, real-truth) Co-Authored-By: Claude Fable 5 --- CLAUDE.md | 31 ++++++-- docs/TODO.md | 18 +++-- docs/report/strategie_attive.html | 51 ++++++++----- scripts/analysis/make_strategy_doc.py | 101 ++++++++++++++++++++++---- 4 files changed, 155 insertions(+), 46 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index a47f623..9b86e93 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -61,7 +61,11 @@ scripts/analysis/ → ricerca/validazione OOS fee-aware (strategy_research, option_overlay_lab.py (overlay opzioni prezzato; mr02eth_port06_gate.py = gate swap-sleeve); pairs15m_*.py (gate/flatcheck/smoke ETH/BTC 15m -> sleeve PR_ETHBTC_15M) scripts/games/ → gioco "Blind Traders": 100 agenti ciechi su BTC/ETH anonimi (engine.py, - arena.py epoche+cull, agent_brief.py digest, run_game.py). Origine del BLEND 15m + arena.py epoche+cull, agent_brief.py digest, run_game.py). Origine del BLEND 15m. + Varianti: options_* (strutture in opzioni, BS+skew+DVOL; opt_calibrate da + cerbero-bite), session_* (pattern orari), grid_* (griglie da STRATEGIA_GRIGLIA.md; + gate scripts/analysis/grid_game_gate.py). arena: GAME_NO_LIVE=1 vieta le + strategie gia' deployate (pairs, fade zscore/breakout/momentum) scripts/bump_version.py, scripts/deploy.sh → versionamento e deploy (bump+commit+rebuild) VERSION → versione semver (cotta nell'immagine, +1 ad ogni deploy) strategies.yml → config multi-strategy paper trader @@ -386,8 +390,23 @@ queste fade, ma va confermato col paper trader live prima di rischiare capitale ## Portafogli - Un `Portfolio` è un oggetto di prima classe (`src/portfolio/`) con definizione (sleeve + schema pesi) e due facce sulla **STESSA** definizione: `.backtest()` (riusa il builder unico di `sleeves.py` → parità esatta con `report_families`) e live (`PortfolioRunner`: capitale pool condiviso, sizing per peso, ribilancio giornaliero, ledger aggregato in `data/portfolios/{code}/`). -- **Schemi peso:** `equal` (default), `cap` (tetto per famiglia, es. pairs 33% — config raccomandata), `inverse_vol`, `cluster_rp` (equal fra cluster naturali poi inverse-vol intra-cluster), `manual`. Definiti in `weighting.py`; la chiave cap è la famiglia (PAIRS/FADE/HONEST/SHAPE/TSM). -- **Default `portfolios.yml`:** PORT06 (master+shape), `weighting=cap pairs 0.33 + shape 0.0588`, leva 2x, ribilancio 1D. Backtest PORT06 canonico (dati al 2026-05-28, pre-cap-shape): FULL Sharpe 6.47 DD 4.10% / OOS Sharpe 8.82 DD 1.30%; **con EXIT-16 close-confirm (config live attuale): FULL 7.84 / 2.60%, OOS 10.06 / 1.15%** (i vecchi 6.07/8.19 erano pre-loss-guard/pre-refresh dati). Col cap SHAPE (2026-06-05): FULL 6.43 / 3.96%, OOS 8.58 / 1.36% — assicurazione sulla coda SH01, vedi sotto. **Col BLEND ETH/BTC 15m (2026-06-09, v1.1.16, vedi sotto): FULL 7.20 / 3.68%, OOS 9.66 / 1.31% — 18 sleeve.** +- **Schemi peso:** `equal` (default), `cap` (tetto per famiglia, es. pairs 33% — config raccomandata), `inverse_vol`, `cluster_rp` (equal fra cluster naturali poi inverse-vol intra-cluster), `manual`. Definiti in `weighting.py`; la chiave cap è la famiglia (PAIRS/FADE/HONEST/SHAPE/TSM/XSEC). +- **Default `portfolios.yml`:** PORT06 (master+shape), `weighting=cap pairs 0.33 + shape 0.0588`, leva 2x, ribilancio 1D. Backtest PORT06 canonico (dati al 2026-05-28, pre-cap-shape): FULL Sharpe 6.47 DD 4.10% / OOS Sharpe 8.82 DD 1.30%; **con EXIT-16 close-confirm (config live attuale): FULL 7.84 / 2.60%, OOS 10.06 / 1.15%** (i vecchi 6.07/8.19 erano pre-loss-guard/pre-refresh dati). Col cap SHAPE (2026-06-05): FULL 6.43 / 3.96%, OOS 8.58 / 1.36% — assicurazione sulla coda SH01, vedi sotto. Col BLEND ETH/BTC 15m (2026-06-09, v1.1.16, vedi sotto): FULL 7.20 / 3.68%, OOS 9.66 / 1.31% — 18 sleeve. **Con XS01 (2026-06-09, vedi sotto): OOS Sharpe 10.07, FULL DD 3.46 — 19 sleeve** (pool live real-only 15; i 4 book multi-asset TR01/ROT02/TSM01/XS01 girano in statistica). +- **XS01 — Cross-Sectional Reversion (ATTIVO LIVE 2026-06-09; dispersion-gate v1.1.20, 2026-06-10).** + Famiglia nuova XSEC, distinta da pairs (pairwise) e fade (single-asset): ogni `hold=12` ore + classifica 8 crypto (UNIVERSE8) per rendimento a `lb=48` ore e va long i perdenti relativi / + short i vincenti (peso ∝ −(ret − media cross-section)), market-neutral gross 1, fee 0.20% + RT/book (turnover 2). Scorrelato ~0 da pairs e fade. FULL Sharpe ~3.3, plateau lb 12-72 × + hold 6-24; cost-sensitive (muore a ~0.35% RT/book). Gate PORT06: OOS Sharpe 9.66→10.07, + FULL DD 3.68→3.46. **Dispersion-gate** (`disp_min=0.0313` = p50 TRAIN): entra solo se la + std cross-section del momentum ≥ soglia — diagnostica monotona TRAIN+OOS, plateau p30-p70, + standalone Sharpe 2.50→3.46 (regge fee 2x), PORT06 OOS 10.07→10.37 a DD pari. Come + trend/hurst sulle fade, il gate agisce SOLO sul path live (backtest canonico non filtrato + → il live farà meglio del backtest). 8 gambe → PAPER (niente esecuzione reale a €2k). + Worker `XsecWorker` validato (`validate_xsec_worker`: replay == backtest esatto). Strategia + `scripts/strategies/XS01_cross_sectional.py`, gate `scripts/analysis/xsec_port06_gate.py` / + `xs01_dispersion_gate.py`. NB scartata nella stessa tornata: FC01 funding-carry (nessun + edge su 6.5 anni). Diari `docs/diary/2026-06-09/10-*`. - **BLEND ETH/BTC 15m flat-skip (ATTIVO LIVE v1.1.16, 2026-06-09).** Sleeve `PR_ETHBTC_15M` accanto al 1h: pairs ETH/BTC a **15m** (n=66, z_in=1.674, z_exit=1.0, max_bars=35) a **mezza size** (`params.position_size=0.10`). **Origine: gioco "Blind Traders"** (100 agenti ciechi su BTC/ETH anonimizzati → riscoprono la mean-reversion, vincitore = spread ETH/BTC 15m; `scripts/games/`). Gate PORT06 sul serio: **non duplicato (corr 1h↔15m = 0.37)**, robusto (16/16 celle Sharpe>1), e l'edge **NON è artefatto delle candele flat ETH 15m** (16% storico; filtrandole resta l'83% dello Sharpe). Engine `pairs_research.pairs_sim_flat` con uscita **LIVE-REALIZABLE** (`flat_skip`: niente entry/exit su barre O=H=L=C, esce alla 1a barra pulita), **regression-lock** a `pairs_sim` con flat_skip=False. **Worker validato** (`validate_worker_pairs` a 15m: replay == backtest, 8452 vs 8453 trade; 1h byte-exact). Runner: fetch sub-orario diretto da Cerbero + `pos_for_spec` override **per-sleeve** (params.position_size > famiglia > globale). Mezza size perché a peso pieno il 15m pesava il 25.8% del rischio PORT06 (→ 11.5%, bilanciato col 1h) — blend-tilt prudente sul **caveat slippage** (a slippage realistico il vantaggio di Sharpe regge, quello di DD si assottiglia: il vero banco di prova è il ledger reale shadow). Diari `docs/diary/2026-06-09-pairs15m-*.md`, gate `scripts/analysis/pairs15m_port06_gate.py` / `pairs15m_gate_final.py` / `pairs15m_flatcheck.py`, smoke `pairs15m_live_smoke.py`. - **SH01 SENZA STOP-LOSS — by design, CONFERMATO da ricerca (2026-06-05).** Dopo il crash ETH (−15.6% su un trade SH01 live), ricerca multi-agente con harness dedicato `scripts/analysis/sh01_exit_lab.py` (cache segnali walk-forward, engine con **fill gap-aware** `worse(livello, open)`, parity esatta con explore_lab, protocollo train≤2023-11-01/OOS): **11 famiglie di stop testate (ATR intrabar/close-confirm, %, chandelier, breakeven, giveback, loser-timestop, disaster-cap close+intrabar, swing, vol-regime), 0 sopravvissute** al gate (ETH migliorato senza degradare BTC, train E oos, plateau). Pattern: ogni stop stretto abbastanza da toccare la coda ETH rompe BTC; ogni stop largo non arriva alla coda; nei crash il fill è al gap, non al livello (lo stop "protettivo" PEGGIORA la coda OOS). Mitigazione adottata: **cap famiglia SHAPE a 0.0588 in PORT06** (≈ dimezzata; costo OOS Sharpe −0.24, FULL DD −0.14pp) — la prossima coda impatta il conto per metà. NON impostare mai `sl`/`sl_confirm_atr` su SH_BTC/SH_ETH. Direzione futura: liquidity-gate sull'entry (skip dopo feed flat). Diario `docs/diary/2026-06-05-sh01-sl-research.md`. - **Data layer Cerbero v2:** `get_historical_v2` unificato + `get_instruments` (naming robusto) + `get_ticker_batch`. Trading su Deribit. @@ -411,9 +430,9 @@ queste fade, ma va confermato col paper trader live prima di rischiare capitale single-leg con exit a orizzonte H=12 — niente TP/SL, `_place_real_tp` no-op e `_real_close` chiude tutto market reduce-only, disaster-bracket on-book come unica protezione di coda (v1.1.13). Motivo: SH01 è il diversificatore più decorrelato (senza i 5 sleeve PAPER il DD del portafoglio sale - 3.96→5.35%). Copertura reale ora ~83% (fade+DIP+**6 pairs incl. ETH/BTC 15m**+SH01); restano - simulati TR01/ROT02/TSM01 (book multi-asset, bloccati dal capitale: rumore arrotondamento 20-30% - a €2k, serve ~€20k). Diari `docs/diary/2026-06-08-pairs-executor.md`. + 3.96→5.35%). Copertura reale ora 15 sleeve su 19 (fade+DIP+**6 pairs incl. ETH/BTC 15m**+SH01); + restano simulati TR01/ROT02/TSM01/XS01 (book multi-asset, bloccati dal capitale: rumore + arrotondamento 20-30% a €2k, serve ~€20k). Diari `docs/diary/2026-06-08-pairs-executor.md`. - **ESECUZIONE REALE — shadow (v1.0.3, 2026-06-03).** I **6 fade** (MR01/MR02/MR07 × BTC/ETH) eseguono ordini **REALI su Deribit testnet** accanto al fill simulato (*shadow*: sim + reale in parallelo, il sim resta la verità che guida le decisioni). `src/live/execution.py` `ExecutionClient`: `open` (market) + `close_amount` (market **reduce-only della SOLA quota del worker** — i 3 fade BTC condividono lo strumento e le posizioni si nettano per conto, quindi NON si usa `close_position` che flatterebbe le quote altrui); **verifica l'esecuzione sul TRADE** (order_id in `get_trade_history`, non sulla size netta aggregata); **fee REALI lette dai `trades[]`**. Strumenti = **lineari USDC** (`BTC_USDC`/`ETH_USDC-PERPETUAL`, amount nel base-coin, step 0.0001/0.001): scelti perché il **payoff lineare == matematica del backtest** (l'inverse `*-PERPETUAL` introdurrebbe una base 1/prezzo) e fee/PnL sono in USDC. Lo `StrategyWorker` tiene un **ledger reale parallelo** (`real_capital`, persistito) e logga `REAL_OPEN`/`REAL_CLOSE` col confronto **slippage** (prezzo sim vs eseguito) e **fee** (assunta 0.10% vs reale). Config: `portfolios.yml` → `overrides.execution {enabled, sleeves:[MR01,MR02,MR07,DIP01], instruments:{BTC:BTC_USDC-PERPETUAL, ETH:ETH_USDC-PERPETUAL}}` (**DIP01 aggiunto il 2026-06-04**: stesso wiring single-leg, TP resting incluso); pairs/rotation/tsmom/shape restano **simulati** (pairs richiede un executor a 2 gambe con gestione leg-risk; shape non ha TP). **Fee reali misurate = 0.05%/lato = 0.10% RT** (== assunto del backtest, su ETH; BTC inverse era ~0.094%). **Alert Telegram:** `REAL_EXEC_LIVE` (primo ordine reale verificato per worker) + `REAL_OPEN_FAIL`. Smoke (testnet, €0): `scripts/analysis/live_exec_smoke.py` (layer: ordine→verifica→fee) e `live_shadow_smoke.py` (catena worker open/close). **Capitale live portato a 2000** (notional fade ~$35) per ridurre il rumore di arrotondamento su BTC (step lineare ~$6.7). NB: ledger reale ≠ ledger sim — i worker già in posizione sim a un restart non hanno quota reale corrispondente; lo shadow reale parte pulito dalla prossima apertura. - **Disaster-bracket on-book + alert outage (v1.1.4, 2026-06-07).** A ogni `REAL_OPEN` dei fade eseguiti il worker piazza uno **STOP_MARKET reduce-only a ~−30%** dall'ingresso (trigger sul mark, diff --git a/docs/TODO.md b/docs/TODO.md index 73ffc7c..cbdd73d 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -1,17 +1,18 @@ # TODO — prossimi passi -> Raccolta dei follow-up aperti. Aggiornato 2026-06-08 (pairs reali ATTIVI v1.1.12; -> roadmap improvement-sweep 10/10 completata). +> Raccolta dei follow-up aperti. Aggiornato 2026-06-11 (XS01 dispersion-gate live v1.1.20; +> real-truth ledger attivo; reset portafoglio 2026-06-10). ## Stato esecuzione per sleeve (REALE vs SIMULATO) -**REALE (shadow su Deribit testnet) — il "vero" risultato monetario:** +**REALE (shadow su Deribit testnet, REAL-TRUTH: il ledger segue i fill reali) — 15 sleeve:** - 6 fade (MR01/MR02/MR07 × BTC/ETH) + DIP01_BTC → single-leg, v1.0.3+ -- 5 pairs PR01 (ETH/BTC, LTC/ETH, ADA/ETH, BTC/LTC, ETH/SOL) → 2 gambe, v1.1.12 (2026-06-08) +- 6 pairs PR01 (ETH/BTC, LTC/ETH, ADA/ETH, BTC/LTC, ETH/SOL + ETH/BTC 15m) → 2 gambe, + v1.1.12 (2026-06-08); il 15m dal v1.1.16 (2026-06-09) - SH01 × BTC/ETH → single-leg, exit a orizzonte (no TP/SL), v1.1.13 (2026-06-08) -**SIMULATO (paper, NON esegue reale) — categoria distinta:** -- TR01 / ROT02 / TSM01 → book multi-asset, bloccati dal CAPITALE (rumore arrotondamento) +**SIMULATO (paper, NON esegue reale) — 4 book multi-asset, fuori dal capitale-pool:** +- TR01 / ROT02 / TSM01 / XS01 → bloccati dal CAPITALE (rumore arrotondamento) ## Esecuzione reale — pezzi mancanti @@ -20,7 +21,7 @@ (_place_real_tp no-op senza TP, _real_close chiude tutto market reduce-only a orizzonte). Bastava accettare kind 'ml' in _exec_for + SH01 in execution.sleeves. Disaster-bracket on-book = unica protezione di coda. Test SH01 open/close reale OK. -- [ ] **Multi-asset in reale** (SIMULATO: TR01/ROT02/TSM01) — **SBLOCCATO DA CAPITALE ≥ ~€20k**. +- [ ] **Multi-asset in reale** (SIMULATO: TR01/ROT02/TSM01/XS01) — **SBLOCCATO DA CAPITALE ≥ ~€20k**. Strumenti USDC tutti esistenti (BNB/DOGE/XRP inclusi), ma a €2k il rumore di arrotondamento per-asset è 20-30% (DOGE/XRP/SOL step grandi in $, esposizione frammentata su 5-8 asset) → l'esecuzione reale misurerebbe il rumore dei lotti, non la strategia. Serve un @@ -33,7 +34,8 @@ - [ ] **Valutare aumento capitale a €5.000-10.000** per togliere il rumore di arrotondamento. A €2.000 il rumore BTC per trade è ~2.4% (morde); soglie: ~€4.800 (<1%), ~€9.500 (<0.5%, "punto dolce"), ~€19.000 (trascurabile). Le commissioni invece sono % e neutre al capitale. - Riguarda solo i 7 single-leg che eseguono reale; pairs/SH01 sono simulati. + Col real-truth ledger il rumore di arrotondamento entra DIRETTAMENTE nell'equity → più + capitale = ledger più fedele alla strategia. Riguarda i 15 sleeve che eseguono reale. ## Follow-up dal code-review (bassa priorità, non urgenti) diff --git a/docs/report/strategie_attive.html b/docs/report/strategie_attive.html index a946fe2..cb03c5e 100644 --- a/docs/report/strategie_attive.html +++ b/docs/report/strategie_attive.html @@ -9,8 +9,8 @@ box-shadow:0 1px 3px rgba(0,0,0,.05)} .badge{display:inline-block;font-size:11px;font-weight:700;padding:2px 9px;border-radius:10px; margin-right:6px;color:#fff} .b-fade{background:#1f6fd6}.b-honest{background:#e08c1a}.b-pairs{background:#9467bd} -.b-tsm{background:#5ab4ac}.b-shape{background:#d64545}.b-real{background:#2e9e6b} -.b-sim{background:#8a8f98} +.b-tsm{background:#5ab4ac}.b-shape{background:#d64545}.b-xsec{background:#8c564b} +.b-real{background:#2e9e6b}.b-sim{background:#8a8f98} img{max-width:100%;border:1px solid #eee;border-radius:6px;margin-top:10px} table{border-collapse:collapse;width:100%;font-size:13px;margin-top:8px} td,th{border:1px solid #e3e5e8;padding:5px 9px;text-align:left} @@ -20,17 +20,18 @@ font-size:13px;margin-top:10px}

PythagorasGoal — Strategie attive

-

Portafoglio live PORT06 — definizione 18 sleeve; pool live real-only 15 sleeve -(i 3 book multi-asset girano in statistica, fuori dal capitale-pool). Capitale pool €2.000, leva 2x · -v1.1.16 · generato 2026-06-09 11:57 UTC · backtest canonico: FULL Sharpe 7.20 / DD 3.68% — OOS Sharpe 9.66 / DD 1.31%

+

Portafoglio live PORT06 — definizione 19 sleeve; pool live real-only 15 sleeve +(i 4 book multi-asset TR01/ROT02/TSM01/XS01 girano in statistica, fuori dal capitale-pool). +Capitale pool €2.000, leva 2x, real-truth ledger · +v1.1.20 · generato 2026-06-11 09:57 UTC · backtest canonico: FULL Sharpe 7.34 / DD 3.46% — OOS Sharpe 10.07 / DD 1.48%

-

Tre famiglie principali quasi scorrelate fra loro (fade↔honest ~0.05, pairs ~0.02-0.09, -shape ~0.08): la diversificazione è la leva anti-drawdown. Pesi equal con tetti per famiglia, -ribilancio giornaliero su capitale pool condiviso. Fee Deribit 0.10% round-trip incluse ovunque; -ogni meccanismo live è passato da un gate out-of-sample a livello di portafoglio.

-
+

Famiglie quasi scorrelate fra loro (fade↔honest ~0.05, pairs ~0.02-0.09, +shape ~0.08, xsec ~0): la diversificazione è la leva anti-drawdown. Pesi equal con tetti +per famiglia, ribilancio giornaliero su capitale pool condiviso. Fee Deribit 0.10% round-trip +incluse ovunque; ogni meccanismo live è passato da un gate out-of-sample a livello di portafoglio.

+
-

FADE — mean-reversion intraday 1h (6 sleeve × 6.47%)

+

FADE — mean-reversion intraday 1h (6 sleeve × 5.69%)

Tesi della famiglia: sui perpetui crypto l'edge è la reversione: i movimenti estremi rientrano (i breakout falliscono — l'intera famiglia squeeze-breakout è stata scartata come artefatto di look-ahead). Le fade vendono l'eccesso e comprano il panico, con tre @@ -54,8 +55,8 @@ estremo in un'ora), fada il movimento. Exit in multipli di ATR. È la fade più sono falsi negativi — l'overshoot che buca lo stop e rientra è esattamente il movimento che la fade sta comprando. Con EXIT-16 lo SL intrabar è disattivato: si esce solo se il close della barra completata sfonda il livello di 0.5·ATR. Il TP intrabar resta. Impatto sul -portafoglio: OOS Sharpe 8.82→10.06. Esteso oggi anche a DIP01 (grid 36/36).

-

HONEST — long-only multi-regime (3 sleeve × 6.47%)

+portafoglio: OOS Sharpe 8.82→10.06. Esteso anche a DIP01 (2026-06-07, grid 36/36).

+

HONEST — long-only multi-regime (3 sleeve × 5.69%)

DIP01 — Dip Buy (BTC)

HONESTESECUZIONE REALE (testnet)

Compra il dip: quando lo z-score del prezzo incrocia sotto −2.5 (sell-off rapido), entra long. TP alla SMA50, EXIT-16 sul SL, max 24 barre. È l'unico sleeve BTC con round-trip @@ -68,7 +69,7 @@ le fade per costruzione non prendono. Valuta solo barre 4h COMPLETE.

<

Rotazione: ogni giorno ordina 8 crypto per momentum a 60 giorni e tiene le top-3 (solo se positive), gross 0.45. Gate di regime: tutto cash se BTC<SMA100. Diversificare su 3 asset invece di 2 ha quasi dimezzato il DD (40%→26%) alzando il ritorno.

annoROT02 (universo 8)
trdPnL%DD%
2021+00
2022+00
2023+8110
2024+437
2025+1312
2026-89
TOT+13019

PnL = ritorno % dell'anno dall'equity giornaliera canonica (2021-2026, leva 3x convenzione test); DD = max drawdown nell'anno; trd non applicabile (ribilancio giornaliero del book).

-

PAIRS — spread reversion market-neutral (6 sleeve: 5 coppie 1h + ETH/BTC 15m a mezza size, famiglia ≤33%)

+

PAIRS — spread reversion market-neutral (6 sleeve × 5.26%: 5 coppie 1h + ETH/BTC 15m a mezza size, famiglia ≤33%)

PR01 — Pairs Reversion (ETH/BTC, LTC/ETH, ADA/ETH, BTC/LTC, ETH/SOL + ETH/BTC 15m)

PAIRSESECUZIONE REALE (testnet)

Market-neutral: quando il rapporto fra due asset si allontana troppo dalla sua media (|z| del log-ratio ≥ 2), compra la gamba debole e shorta la forte; chiude quando il rapporto @@ -83,12 +84,27 @@ barre stale O=H=L=C). Worker validato (replay == backtest). A mezza size sul caveat slippage): porta il PORT06 a FULL Sharpe ~7.2 / OOS ~9.7.

Esecuzione reale a 2 gambe su Deribit testnet (PairsExecutionClient): open/close long A / short B, leg-risk unwind, mai close_position.

annoETH/BTCLTC/ETHADA/ETHBTC/LTCETH/SOLETH/BTC·15m
2018-343 (177, dd 45)-492 (913, dd 31)
2019+233 (198, dd 8)+792 (963, dd 4)
2020+323 (211, dd 25)+452 (867, dd 15)
2021+549 (202, dd 12)+1122 (949, dd 5)
2022+1344 (206, dd 3)+292 (45, dd 14)+899 (157, dd 5)+328 (58, dd 8)+1243 (147, dd 9)+2136 (898, dd 5)
2023+464 (213, dd 4)+56 (94, dd 5)+341 (173, dd 10)+61 (106, dd 14)+125 (168, dd 24)+689 (976, dd 11)
2024+1661 (253, dd 6)+1024 (195, dd 9)+1078 (225, dd 16)+638 (186, dd 10)+1302 (199, dd 12)+6313 (1353, dd 4)
2025+1173 (225, dd 16)+962 (196, dd 10)+1046 (187, dd 19)+686 (178, dd 7)+1264 (202, dd 11)+3664 (1123, dd 7)
2026+61 (71, dd 2)+279 (76, dd 3)+140 (71, dd 3)+265 (71, dd 3)+270 (88, dd 4)+155 (411, dd 4)
TOT+5464 (1756, dd 48)+2614 (606, dd 14)+3504 (813, dd 19)+1978 (599, dd 21)+4204 (804, dd 24)+14832 (8453, dd 34)

cella: PnL% anno (n trade, max DD% anno) — Σ rendimenti netti per trade, fee 0.20% RT/coppia (2 gambe), leva 3x convenzione test. NB: la finestra canonica del portafoglio parte dal 2021; gli anni precedenti (spesso negativi) sono mostrati per onestà storica.

-

TSM — trend-following multi-orizzonte (1 sleeve × 6.47%)

+

TSM — trend-following multi-orizzonte (1 sleeve × 5.69%)

TSM01 — TSMOM (1d)

TSMSIMULATO

Long sugli asset con consenso pieno di momentum su 3 orizzonti (3/6/12 mesi), gross 0.30, cash totale se BTC<SMA100. Mai un anno negativo nel backtest. Non è un motore di ritorno: è il diversificatore che lavora nei regimi in cui le fade soffrono. Attualmente flat by-design (risk-off).

annoTSM01 (universo 8)
trdPnL%DD%
2021+00
2022+00
2023+00
2024-22
2025+76
2026+00
TOT+56

PnL = ritorno % dell'anno dall'equity giornaliera canonica (2021-2026, leva 3x convenzione test); DD = max drawdown nell'anno; trd non applicabile (ribilancio giornaliero del book).

+

XSEC — reversione cross-sectional (1 sleeve × 5.69%)

+

XS01 — Cross-Sectional Reversion (8 asset)

XSECSIMULATO

+

Famiglia nuova (2026-06-09): ogni 12 ore classifica 8 crypto (BTC, ETH, LTC, ADA, +SOL, BNB, XRP, DOGE) per rendimento a 48 ore e va long i perdenti relativi / short i +vincenti (peso ∝ −(ret − media cross-section)), market-neutral gross 1. Cattura il +fattore reversione cross-sezionale — distinto dai pairs (pairwise) e dai fade +(single-asset): correlazione ~0 con entrambi. Gate PORT06: OOS Sharpe 9.66→10.07, +FULL DD 3.68→3.46. Plateau robusto (lb 12-72 × hold 6-24 tutte OOS+).

+

Dispersion-gate (2026-06-10, v1.1.20): entra solo se la dispersione +cross-section del momentum ≥ 0.0313 (mediana TRAIN) — la reversione paga quando c'è +dispersione da far rientrare. Diagnostica monotona TRAIN e OOS, plateau p30-p70, +standalone Sharpe 2.50→3.46 (regge fee 2x), PORT06 OOS 10.07→10.37 a DD pari. +Solo path live (backtest canonico non filtrato → il live farà meglio del backtest).

+

8 gambe → niente esecuzione reale: gira PAPER come i book multi-asset +(il rumore di arrotondamento a €2k dominerebbe). Worker validato (replay == backtest esatto).

annoXS01 (universo 8)
trdPnL%DD%
2022180+3416
2023106+68
2024195+218
2025674+2258
2026272+854
TOT1427+37016

PnL = Σ rendimenti netti per trade del book (%, gross 1, fee 0.20% RT/book = turnover 2×0.10%); DD dall'equity compounding (pos 0.15, leva 3x convenzione test). Engine canonico SENZA dispersion-gate (il gate agisce solo sul path live, come trend/hurst sulle fade → il live farà meglio del backtest).

SHAPE — ML morfologico (2 sleeve × 2.94%, famiglia ≤5.88%)

SH01 — Shape-ML (BTC, ETH)

SHAPEESECUZIONE REALE (testnet)

Una LogisticRegression legge 17 feature della forma delle ultime 24 barre e @@ -99,7 +115,7 @@ l'edge): la coda si gestisce dimezzando il peso della famiglia (cap 5.88%).

Esecuzione reale single-leg su Deribit testnet: niente TP/SL, chiusura a orizzonte H=12 (market reduce-only), disaster-bracket on-book come unica protezione di coda — è il diversificatore più decorrelato del portafoglio.

-

Fix di oggi (punto-10): il training live usa la storia COMPLETA dal parquet +

Fix punto-10 (2026-06-07): il training live usa la storia COMPLETA dal parquet locale (il regime corto a 365g non era robusto: trade-rate 22% vs 10% validato).

annoBTCETH
trdPnL%DD%trdPnL%DD%
2018237-6623239+7415
2019318+8815365-1921
2020240+19410219-29353
2021224+30113146+6718
2022142+641191+7922
2023118+17517+215
2024144+110847+1086
202585+775108+5407
202623+59225-307
TOT1531+845231257+54761

PnL = Σ rendimenti netti per trade (%, leva 3x, fee 0.10% RT, convenzione test; il live gira a leva 2x); DD = max drawdown nell'anno (equity compounding pos 0.15); riga TOT: DD dell'intero periodo. NB: la finestra canonica di valutazione del portafoglio parte dal 2021 — gli anni 2018-2020 (regime microstrutturale diverso, spesso negativi) sono mostrati per onestà storica.

Metodologia

@@ -107,7 +123,8 @@ locale (il regime corto a 365g non era robusto: trade-rate 22% vs 10% validato).
  • Fee sempre incluse: 0.10% round-trip taker Deribit (misurate reali = assunte). Molte operazioni = morte per fee: ogni strategia regge lo stress a fee doppie.
  • Niente look-ahead: direzione e prezzo decisi solo con dati fino al close corrente; barre in formazione escluse (lezione EXIT-16). La famiglia squeeze (accuratezze 76-82%) è stata scartata proprio per questo artefatto.
  • Gate out-of-sample: nessun meccanismo va in produzione senza migliorare (o non degradare) il portafoglio FULL e OOS — robusto individualmente ≠ migliora PORT06.
  • -
  • Esecuzione reale shadow (~83% del portafoglio): 15 sleeve eseguono ordini reali su Deribit testnet accanto al sim — i 6 fade + DIP01 (single-leg, TP limit al livello, disaster-stop −30% on-book), i 6 pairs incl. ETH/BTC 15m flat-skip (2 gambe, leg-risk unwind) e i 2 SH01 (single-leg, exit a orizzonte, niente TP/SL). Restano simulati solo i book multi-asset TR01/ROT02/TSM01 (bloccati dal capitale: serve ~€20k per il rumore di arrotondamento). Fee reali verificate dai trade; divergenze sim/reale ≥100bps alertate su Telegram.
  • +
  • Esecuzione reale shadow (15 sleeve su 19): i 6 fade + DIP01 (single-leg, TP limit al livello, disaster-stop −30% on-book), i 6 pairs incl. ETH/BTC 15m flat-skip (2 gambe, leg-risk unwind) e i 2 SH01 (single-leg, exit a orizzonte, niente TP/SL) eseguono ordini reali su Deribit testnet. Restano simulati solo i book multi-asset TR01/ROT02/TSM01/XS01 (bloccati dal capitale: serve ~€20k per il rumore di arrotondamento). Fee reali verificate dai trade; divergenze sim/reale ≥100bps alertate su Telegram.
  • +
  • Real-truth ledger (2026-06-10): il capitale dei worker eseguiti si aggiorna col PnL dei fill reali (fee reali incluse), non col sim — equity, pesi e notional derivano dai soldi veri sul conto; il sim resta diagnostica nel log (fallback dichiarato solo se il trade reale non è mai esistito). Le decisioni di entry/exit restano guidate dal feed.
  • Generato da scripts/analysis/make_strategy_doc.py — grafici da episodi reali sui dati parquet locali.

    \ No newline at end of file diff --git a/scripts/analysis/make_strategy_doc.py b/scripts/analysis/make_strategy_doc.py index 6190581..dfda0c9 100644 --- a/scripts/analysis/make_strategy_doc.py +++ b/scripts/analysis/make_strategy_doc.py @@ -379,13 +379,43 @@ def chart_sh01(): return b64(fig) +def chart_xs01(): + """Book corrente (long perdenti/short vincenti) + dispersione cross-section col gate.""" + from scripts.strategies.XS01_cross_sectional import aligned_panel, UNIVERSE, LB + M = aligned_panel() + logC = np.log(M.values) + ts = pd.to_datetime(M.index, unit="ms", utc=True) + dm = logC[-1] - logC[-1 - LB] + dm = dm - dm.mean() + w = -dm / np.sum(np.abs(dm)) + fig, (ax, ax2) = plt.subplots(1, 2, figsize=(8.6, 3.4), width_ratios=[1, 1.5]) + ax.bar(UNIVERSE, w * 100, color=[C_TP if x > 0 else C_SL for x in w]) + ax.set_ylabel("peso book %") + ax.tick_params(axis="x", rotation=60) + ax.set_title("book: long i perdenti relativi,\nshort i vincenti (mom 48h demeaned)", + loc="left", fontweight="bold", fontsize=9) + D = logC[LB:] - logC[:-LB] + disp = pd.Series(D.std(axis=1), index=ts[LB:]).iloc[-24 * 180:] + ax2.plot(disp.index, disp.values, color="#333", lw=0.7) + ax2.axhline(0.0313, color=C_SL, ls="--", lw=1.2) + on = disp.values >= 0.0313 + ax2.fill_between(disp.index, 0, disp.values.max(), where=on, alpha=0.10, color=C_TP) + ax2.annotate("disp_min 0.0313 (p50 TRAIN)\nentry solo sopra soglia", + (disp.index[-1], 0.0313), xytext=(-150, 10), + textcoords="offset points", color=C_SL, fontsize=8) + ax2.set_title("dispersion-gate: std cross-section del momentum", + loc="left", fontweight="bold", fontsize=9) + fig.tight_layout() + return b64(fig) + + def chart_weights(): p = PORTFOLIOS["PORT06"] ids = p.sleeve_ids w = W.weight_vector("cap", ids, None, caps=p.caps) fam = {i: W.family_of(i) for i in ids} colors = {"FADE": "#1f6fd6", "HONEST": "#e08c1a", "PAIRS": "#9467bd", - "TSM": "#5ab4ac", "SHAPE": "#d64545"} + "TSM": "#5ab4ac", "SHAPE": "#d64545", "XSEC": "#8c564b"} order = sorted(ids, key=lambda i: (fam[i], i)) fig, ax = plt.subplots(figsize=(8.6, 2.9)) ax.bar(order, [w[i] * 100 for i in order], color=[colors[fam[i]] for i in order]) @@ -547,6 +577,25 @@ def stats_multi(): yearly_table({"TSM01 (universo 8)": equity_yearly(tsm)}, note)) +def stats_xs01(): + """XS01 per-anno dall'engine canonico (UNGATED, come il backtest di portafoglio).""" + from scripts.strategies.XS01_cross_sectional import xsec_sim + r = xsec_sim() + s = pd.Series(r["eq_v"], index=pd.to_datetime(r["eq_ts"], utc=True)) + years = {} + for y in sorted(r["yearly"]): + g = s[s.index.year == y] + dd = float(((g.cummax() - g) / g.cummax()).max() * 100) if len(g) else 0.0 + years[int(y)] = {"n": r["yearly_n"].get(y, 0), "pnl": r["yearly"][y], "dd": dd} + pk = s.cummax() + note = ("PnL = Σ rendimenti netti per trade del book (%, gross 1, fee 0.20% RT/book = " + "turnover 2×0.10%); DD dall'equity compounding (pos 0.15, leva 3x convenzione " + "test). Engine canonico SENZA dispersion-gate (il gate agisce solo sul path " + "live, come trend/hurst sulle fade → il live farà meglio del backtest).") + return yearly_table({"XS01 (universo 8)": (years, float(((pk - s) / pk).max() * 100))}, + note) + + def stats_sh01(): """SH01 per-anno dal walk-forward EXPANDING (il regime validato e ora live).""" from scripts.analysis.shape_ml_research import ml_wf_entries @@ -580,8 +629,8 @@ box-shadow:0 1px 3px rgba(0,0,0,.05)} .badge{display:inline-block;font-size:11px;font-weight:700;padding:2px 9px;border-radius:10px; margin-right:6px;color:#fff} .b-fade{background:#1f6fd6}.b-honest{background:#e08c1a}.b-pairs{background:#9467bd} -.b-tsm{background:#5ab4ac}.b-shape{background:#d64545}.b-real{background:#2e9e6b} -.b-sim{background:#8a8f98} +.b-tsm{background:#5ab4ac}.b-shape{background:#d64545}.b-xsec{background:#8c564b} +.b-real{background:#2e9e6b}.b-sim{background:#8a8f98} img{max-width:100%;border:1px solid #eee;border-radius:6px;margin-top:10px} table{border-collapse:collapse;width:100%;font-size:13px;margin-top:8px} td,th{border:1px solid #e3e5e8;padding:5px 9px;text-align:left} @@ -609,6 +658,7 @@ def main(): st_dip = stats_dip() t_pairs = stats_pairs() t_tr, t_rot, t_tsm = stats_multi() + t_xs = stats_xs01() print(" SH01 walk-forward expanding (il piu' lento)...") st_sh = stats_sh01() @@ -631,6 +681,7 @@ def main(): g_pr = chart_pr01() g_tsm = chart_tsm01(panel) g_sh = chart_sh01() + g_xs = chart_xs01() # metriche canoniche del default per l'intestazione (sempre aggiornate) pr = PORTFOLIOS["PORT06"].backtest() @@ -665,7 +716,7 @@ estremo in un'ora), fada il movimento. Exit in multipli di ATR. È la fade più sono falsi negativi — l'overshoot che buca lo stop e rientra è esattamente il movimento che la fade sta comprando. Con EXIT-16 lo SL intrabar è disattivato: si esce solo se il close della barra completata sfonda il livello di 0.5·ATR. Il TP intrabar resta. Impatto sul -portafoglio: OOS Sharpe 8.82→10.06. Esteso oggi anche a DIP01 (grid 36/36).

    """, g_e16) +portafoglio: OOS Sharpe 8.82→10.06. Esteso anche a DIP01 (2026-06-07, grid 36/36).

    """, g_e16) c_dip = card("DIP01 — Dip Buy (BTC)", B("honest", "HONEST") + real, """

    Compra il dip: quando lo z-score del prezzo incrocia sotto −2.5 (sell-off rapido), @@ -713,24 +764,41 @@ l'edge): la coda si gestisce dimezzando il peso della famiglia (cap 5.88%).

    Esecuzione reale single-leg su Deribit testnet: niente TP/SL, chiusura a orizzonte H=12 (market reduce-only), disaster-bracket on-book come unica protezione di coda — è il diversificatore più decorrelato del portafoglio.

    -

    Fix di oggi (punto-10): il training live usa la storia COMPLETA dal parquet +

    Fix punto-10 (2026-06-07): il training live usa la storia COMPLETA dal parquet locale (il regime corto a 365g non era robusto: trade-rate 22% vs 10% validato).

    """, g_sh, yearly_table(st_sh)) + c_xs = card("XS01 — Cross-Sectional Reversion (8 asset)", B("xsec", "XSEC") + sim, """ +

    Famiglia nuova (2026-06-09): ogni 12 ore classifica 8 crypto (BTC, ETH, LTC, ADA, +SOL, BNB, XRP, DOGE) per rendimento a 48 ore e va long i perdenti relativi / short i +vincenti (peso ∝ −(ret − media cross-section)), market-neutral gross 1. Cattura il +fattore reversione cross-sezionale — distinto dai pairs (pairwise) e dai fade +(single-asset): correlazione ~0 con entrambi. Gate PORT06: OOS Sharpe 9.66→10.07, +FULL DD 3.68→3.46. Plateau robusto (lb 12-72 × hold 6-24 tutte OOS+).

    +

    Dispersion-gate (2026-06-10, v1.1.20): entra solo se la dispersione +cross-section del momentum ≥ 0.0313 (mediana TRAIN) — la reversione paga quando c'è +dispersione da far rientrare. Diagnostica monotona TRAIN e OOS, plateau p30-p70, +standalone Sharpe 2.50→3.46 (regge fee 2x), PORT06 OOS 10.07→10.37 a DD pari. +Solo path live (backtest canonico non filtrato → il live farà meglio del backtest).

    +

    8 gambe → niente esecuzione reale: gira PAPER come i book multi-asset +(il rumore di arrotondamento a €2k dominerebbe). Worker validato (replay == backtest esatto).

    """, + g_xs, t_xs) + html = f""" PythagorasGoal — Strategie attive PORT06

    PythagorasGoal — Strategie attive

    Portafoglio live PORT06 — definizione {n_def} sleeve; pool live real-only 15 sleeve -(i 3 book multi-asset girano in statistica, fuori dal capitale-pool). Capitale pool €2.000, leva 2x · +(i 4 book multi-asset TR01/ROT02/TSM01/XS01 girano in statistica, fuori dal capitale-pool). +Capitale pool €2.000, leva 2x, real-truth ledger · v{ver} · generato {now} · backtest canonico: {hdr}

    -

    Tre famiglie principali quasi scorrelate fra loro (fade↔honest ~0.05, pairs ~0.02-0.09, -shape ~0.08): la diversificazione è la leva anti-drawdown. Pesi equal con tetti per famiglia, -ribilancio giornaliero su capitale pool condiviso. Fee Deribit 0.10% round-trip incluse ovunque; -ogni meccanismo live è passato da un gate out-of-sample a livello di portafoglio.

    +

    Famiglie quasi scorrelate fra loro (fade↔honest ~0.05, pairs ~0.02-0.09, +shape ~0.08, xsec ~0): la diversificazione è la leva anti-drawdown. Pesi equal con tetti +per famiglia, ribilancio giornaliero su capitale pool condiviso. Fee Deribit 0.10% round-trip +incluse ovunque; ogni meccanismo live è passato da un gate out-of-sample a livello di portafoglio.

    -

    FADE — mean-reversion intraday 1h (6 sleeve × 6.47%)

    +

    FADE — mean-reversion intraday 1h (6 sleeve × 5.69%)

    Tesi della famiglia: sui perpetui crypto l'edge è la reversione: i movimenti estremi rientrano (i breakout falliscono — l'intera famiglia squeeze-breakout è stata scartata come artefatto di look-ahead). Le fade vendono l'eccesso e comprano il panico, con tre @@ -741,14 +809,16 @@ non si fada un crollo/parabolica), EXIT-16 (stop solo sul close confermat {c_mr02} {c_mr07} {c_e16} -

    HONEST — long-only multi-regime (3 sleeve × 6.47%)

    +

    HONEST — long-only multi-regime (3 sleeve × 5.69%)

    {c_dip} {c_tr} {c_rot} -

    PAIRS — spread reversion market-neutral (6 sleeve: 5 coppie 1h + ETH/BTC 15m a mezza size, famiglia ≤33%)

    +

    PAIRS — spread reversion market-neutral (6 sleeve × 5.26%: 5 coppie 1h + ETH/BTC 15m a mezza size, famiglia ≤33%)

    {c_pr} -

    TSM — trend-following multi-orizzonte (1 sleeve × 6.47%)

    +

    TSM — trend-following multi-orizzonte (1 sleeve × 5.69%)

    {c_tsm} +

    XSEC — reversione cross-sectional (1 sleeve × 5.69%)

    +{c_xs}

    SHAPE — ML morfologico (2 sleeve × 2.94%, famiglia ≤5.88%)

    {c_sh} @@ -757,7 +827,8 @@ non si fada un crollo/parabolica), EXIT-16 (stop solo sul close confermat
  • Fee sempre incluse: 0.10% round-trip taker Deribit (misurate reali = assunte). Molte operazioni = morte per fee: ogni strategia regge lo stress a fee doppie.
  • Niente look-ahead: direzione e prezzo decisi solo con dati fino al close corrente; barre in formazione escluse (lezione EXIT-16). La famiglia squeeze (accuratezze 76-82%) è stata scartata proprio per questo artefatto.
  • Gate out-of-sample: nessun meccanismo va in produzione senza migliorare (o non degradare) il portafoglio FULL e OOS — robusto individualmente ≠ migliora PORT06.
  • -
  • Esecuzione reale shadow (~83% del portafoglio): 15 sleeve eseguono ordini reali su Deribit testnet accanto al sim — i 6 fade + DIP01 (single-leg, TP limit al livello, disaster-stop −30% on-book), i 6 pairs incl. ETH/BTC 15m flat-skip (2 gambe, leg-risk unwind) e i 2 SH01 (single-leg, exit a orizzonte, niente TP/SL). Restano simulati solo i book multi-asset TR01/ROT02/TSM01 (bloccati dal capitale: serve ~€20k per il rumore di arrotondamento). Fee reali verificate dai trade; divergenze sim/reale ≥100bps alertate su Telegram.
  • +
  • Esecuzione reale shadow (15 sleeve su 19): i 6 fade + DIP01 (single-leg, TP limit al livello, disaster-stop −30% on-book), i 6 pairs incl. ETH/BTC 15m flat-skip (2 gambe, leg-risk unwind) e i 2 SH01 (single-leg, exit a orizzonte, niente TP/SL) eseguono ordini reali su Deribit testnet. Restano simulati solo i book multi-asset TR01/ROT02/TSM01/XS01 (bloccati dal capitale: serve ~€20k per il rumore di arrotondamento). Fee reali verificate dai trade; divergenze sim/reale ≥100bps alertate su Telegram.
  • +
  • Real-truth ledger (2026-06-10): il capitale dei worker eseguiti si aggiorna col PnL dei fill reali (fee reali incluse), non col sim — equity, pesi e notional derivano dai soldi veri sul conto; il sim resta diagnostica nel log (fallback dichiarato solo se il trade reale non è mai esistito). Le decisioni di entry/exit restano guidate dal feed.
  • Generato da scripts/analysis/make_strategy_doc.py — grafici da episodi reali sui dati parquet locali.

    """