chore(reset): v2.0.0 — storico certificato Deribit mainnet, ripartenza pulita
Reset del progetto su fondamenta verificate dopo la scoperta che l'intera libreria "validata OOS" era artefatto di feed contaminato (print fantasma del feed Cerbero TESTNET + storico Binance/USDT). - Storico ricostruito da Deribit MAINNET (ccxt pubblico, tokenless) e CERTIFICATO (certify_feed.py): BTC/ETH puliti su TUTTA la storia (mediana 2-6 bps vs Coinbase USD), integrita' OHLC + coerenza resample (maxΔ 0.00) + cross-venue OK. Alt esclusi (illiquidi/divergenti: LTC/DOGE 50-82% barre flat; XRP/BNB non certificabili). - Verdetto sul feed pulito: FADE / PAIRS / XS01 / TSM01 morti (ogni portafoglio Sharpe -2.3..-3.0, DD ~40%); solo SH01 e frammenti HONEST con segnale residuo, da ri-validare in isolamento. - Cleanup "restart pulito": strategie, stack live (src/live, src/portfolio, runner/executor, yml, docker), ~100 script ricerca/gate, waste/games/ portfolios, dati non certificati + cache e 60+ diari -> archiviati in Old/ (preservati, non cancellati). Diario consolidato in un unico documento. - Skeleton ricerca tenuto: Strategy ABC + indicatori + src/fractal + src/backtest/engine + load_data; tool dati certificati (rebuild_history, certify_feed, audit_feed, multi_source_check). - Universo dati ATTIVO: solo BTC/ETH (5m/15m/1h); guardrail fisico (load_data su alt -> FileNotFoundError). Esecuzione DISABILITATA, conto flat. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,92 +0,0 @@
|
||||
# 2026-05-26 — Giorno 1: Setup e download dati
|
||||
|
||||
### 23:15 — Inizializzazione progetto
|
||||
|
||||
**Cosa:** creato struttura progetto Python con uv, git init, moduli base
|
||||
**Perché:** servono fondamenta solide per ricerca iterativa. Struttura: src/data (download/storage), src/fractal (analisi pattern), src/strategies (strategie trading), src/backtest (engine di test), src/nn (reti neurali), src/utils (utility)
|
||||
**Atteso:** progetto funzionante con dipendenze installate
|
||||
**Reale:** in corso
|
||||
|
||||
### 23:20 — Verifica Cerbero MCP
|
||||
|
||||
**Cosa:** testato accesso API Cerbero su cerbero-mcp.tielogic.xyz per dati storici crypto
|
||||
**Perché:** verificare se può fornire dati dal 2018
|
||||
**Atteso:** dati storici cross-exchange (consensus multi-sorgente)
|
||||
**Reale:** API funziona, dati recenti OK. Per storico 2018→oggi uso Binance via ccxt (copertura temporale maggiore, dati 1m disponibili)
|
||||
|
||||
### 23:25 — Script download dati
|
||||
|
||||
**Cosa:** creato src/data/downloader.py — scarica OHLCV da Binance per BTC/USDT e ETH/USDT su 4 timeframe (1m, 5m, 15m, 1h) dal 2018-01-01 a oggi. Formato: parquet (veloce, compresso). Supporta resume in caso di interruzione.
|
||||
**Perché:** dati locali per iterazione veloce. Parquet per caricamento istantaneo vs CSV.
|
||||
**Atteso:** ~4.2M candele 1m per asset, ~70K candele 1h per asset. Download 1m stimato ~30-60 min per asset.
|
||||
**Reale:** in corso (avvio download)
|
||||
|
||||
### Metriche target
|
||||
|
||||
| Metrica | Valore target |
|
||||
|---|---|
|
||||
| Accuratezza previsione direzione | >80% |
|
||||
| ROI annuo (con fees) | >30% |
|
||||
| Capitale iniziale | €1.000 |
|
||||
| Obiettivo giornaliero (steady state) | €50/giorno |
|
||||
| Fee considerate | 0.1% maker/taker (Binance standard) |
|
||||
|
||||
### Approccio
|
||||
|
||||
1. **Focus frattali**: pattern ricorrenti multi-scala, non indicatori classici
|
||||
2. **Multi-timeframe**: conferma segnali su scale diverse (1m→1h)
|
||||
3. **Fuori dagli schemi**: combinare Fourier, auto-similarità, entropia di Shannon, dimensione frattale di Hausdorff
|
||||
4. **Pragmatismo**: se un approccio non funziona, pivotare veloce. Misurare tutto.
|
||||
|
||||
### 23:40 — Analisi baseline completata
|
||||
|
||||
**Cosa:** analisi distribuzione pattern discreti (U/D/0) su BTC 1h, 73.557 candele 2018→2026
|
||||
**Perché:** baseline per capire se pattern candlestick semplici hanno potere predittivo
|
||||
**Atteso:** almeno alcuni pattern con >60% accuracy direzionale
|
||||
**Reale:** NESSUN pattern supera 55% accuracy a 24h. Max: DDD→58.5% a 1h, ma scende a 53.6% a 24h. Pattern discreti semplici NON hanno edge significativo.
|
||||
**Lezione:**
|
||||
- Distribuzione candele quasi uniforme: UP 42.1%, DOWN 40.8%, DOJI 17.1%
|
||||
- 1080 pattern unici (esattamente lo spazio teorico 3^3 + 3^4 + 3^5 + 3^6)
|
||||
- Pattern alternanti (UDU, DUD) più frequenti → mercato mean-reverting a scala oraria
|
||||
- Serve andare oltre: features continue (body/shadow ratios, volume), Fourier, self-similarity, ML
|
||||
**Benchmark:** Buy & Hold test period: +110%, annualizzato 34.3%, Sharpe 0.52
|
||||
|
||||
### 23:40 — Download dati completato
|
||||
|
||||
**Cosa:** scaricati dati storici BTC + ETH, 3 timeframe (5m, 15m, 1h) dal 2018-01-01
|
||||
**Fonti:** Cerbero MCP (Deribit) per set 2018+, Binance/ccxt per gap iniziale
|
||||
**Reale:**
|
||||
|
||||
| Asset | TF | Candele | Peso |
|
||||
|-------|-----|---------|---------|
|
||||
| BTC | 5m | 882.630 | 23.6 MB |
|
||||
| BTC | 15m | 294.213 | 9.1 MB |
|
||||
| BTC | 1h | 73.557 | 2.8 MB |
|
||||
| ETH | 5m | 882.312 | 19.4 MB |
|
||||
| ETH | 15m | 294.107 | 7.9 MB |
|
||||
| ETH | 1h | 73.531 | 2.5 MB |
|
||||
|
||||
**Note:** 1m rimandato (troppo pesante per primo round). 5m sufficiente per analisi fine-grained.
|
||||
|
||||
### 23:50 — Strategia 3: Fourier projection — FALLITA
|
||||
|
||||
**Cosa:** proiezione FFT naive su BTC 1h (ispirata dal paper Pythagoras)
|
||||
**Atteso:** almeno 55% accuracy direzionale
|
||||
**Reale:** 49.8% accuracy (=random), -99.9% return. Tutte le varianti parametri (W=144-588, N=5-50) identicamente pessime.
|
||||
**Lezione:** FFT extrapola sinusoidi che non continuano fuori finestra. Il paper Pythagoras non fa proiezione naive — usa trasformazioni geometriche (centro inversione, riflessioni). Approccio sbagliato, non la tecnica in sé.
|
||||
|
||||
### 00:05 — Strategia 4: Regime-aware fractal ML — PARZIALE SUCCESSO
|
||||
|
||||
**Cosa:** RandomForest + GradientBoosting su features frattali (Hurst, fractal dim, self-similarity, vol ratio, momentum, candle patterns)
|
||||
**Atteso:** >55% accuracy con ML su features ricche
|
||||
**Reale:**
|
||||
- RF: 38% accuracy (3 classi), pochissimi segnali ad alta confidenza (8 @ thr 0.55 → 100% acc)
|
||||
- GB: 41.6% accuracy, MA a threshold sweep:
|
||||
- thr=0.65: **63.6% accuracy**, 66 segnali, **+5.7% return**, Sharpe 0.21
|
||||
- thr=0.80: **80% accuracy**, 5 segnali
|
||||
- Feature importance: volatility (21%) > momentum (10%) > fractal features (6%)
|
||||
**Lezione:**
|
||||
1. Classificazione 3-classi troppo dispersiva → switch a binario
|
||||
2. Features frattali contribuiscono ma non dominano — serve combinarle meglio
|
||||
3. Trade filtering ad alta confidenza funziona: meno trade, più precisi
|
||||
4. Direzione giusta: ML su features frattali produce edge reale, anche se piccolo
|
||||
@@ -1,162 +0,0 @@
|
||||
# 2026-05-27 — Giorno 2: Strategie e risultati
|
||||
|
||||
### 00:00 — Strategia 5: Enhanced fractal (DATA LEAKAGE trovata!)
|
||||
|
||||
**Cosa:** GBM con features multi-window (4 finestre × 9 features), classification binaria, BTC + ETH su 3 lookahead
|
||||
**Atteso:** miglioramento rispetto a #4 con più features e classificazione binaria
|
||||
**Reale:** risultati iniziali troppo belli (84.5% accuracy BTC, 85% ETH) → **DATA LEAKAGE TROVATA**
|
||||
**Bug:** `returns[i-w : i]` includeva `returns[i-1]` che usa `close[i]` (1 candle nel futuro)
|
||||
**Fix:** cambiato a `returns[i-w : i-1]` — re-run in corso
|
||||
**Lezione:** SEMPRE verificare che nessuna feature usi dati oltre il timestamp di decisione. Returns ha off-by-one insidioso.
|
||||
|
||||
### 00:10 — Strategia 6: Structural Pattern KNN + GBM
|
||||
|
||||
**Cosa:** features normalizzate da finestra OHLC (close norm, body, direction, shadow, volume), con KNN e GBM
|
||||
**Reale:**
|
||||
- KNN: max 55.9% accuracy (K=100, thr=0.65) → edge minimo
|
||||
- **GBM: thr=0.65, 795 trades, 58.6% accuracy, +57.5% return** ← MIGLIOR SINGOLO (senza leakage)
|
||||
**Lezione:** features strutturali normalizzate battono features raw. GBM >> KNN per questo tipo di dati.
|
||||
|
||||
### 00:20 — Strategia 7: LSTM
|
||||
|
||||
**Cosa:** LSTM (2 layer, 64 hidden, dropout 0.3) su sequenze di 48 candele × 6 features per-candle
|
||||
**Reale:**
|
||||
- BTC test: 51.9% base, ma thr=0.60: **58.4% accuracy, 214 trades, +4.3%**
|
||||
- BTC thr=0.65: **64.3% accuracy** ma solo 14 trade
|
||||
- ETH: 52.6% base, thr=0.55: **54.5%, +19.9%**
|
||||
- Training su CPU (CUDA non disponibile) → 14 epoch con early stopping
|
||||
**Lezione:** LSTM cattura pattern ma non aggiunge molto rispetto a GBM su features ingegnerizzate. Edge comparabile (~58-64%) con molte meno features. CPU training lento.
|
||||
|
||||
### 00:30 — Strategia 8: Ensemble multi-timeframe
|
||||
|
||||
**Cosa:** 3 modelli (structural 1h, multi-tf 15m, combined) con voting e media probabilità
|
||||
**Reale:**
|
||||
- M1_structural thr=0.65: 829 trades, **58.3% acc, +53.4%, 17.8% annualizzato**
|
||||
- M2_multi_tf: scarso (15m features da sole non bastano)
|
||||
- Ensemble agree≥2, thr=0.65: 520 trades, **59.2% accuracy, +19.9%**
|
||||
- Ensemble agree≥3, thr=0.65: 27 trades, **70.4% accuracy** ma pochi trade
|
||||
**Lezione:**
|
||||
1. Multi-timeframe aggiunge margine (+1% accuracy nell'ensemble)
|
||||
2. Consensus forte (3/3) raggiunge 70%+ ma troppo pochi trade
|
||||
3. Il collo di bottiglia è la frequenza segnali ad alta confidenza
|
||||
|
||||
### 00:45 — Strategie 9 e 10 in esecuzione
|
||||
|
||||
- **#9**: Walk-forward validation con GBM, features combinate structural+fractal
|
||||
- **#10**: High precision (target >80%) con ensemble 5 modelli (2×GBM, RF, ExtraTrees, LogReg), consensus voting, leva 3x
|
||||
|
||||
### Riepilogo risultati validi (no leakage)
|
||||
|
||||
| # | Nome | Accuracy | Return | Ann. | Trades | Note |
|
||||
|---|------|----------|--------|------|--------|------|
|
||||
| 6 | GBM structural | 58.6% | +57.5% | ~20% | 795 | Miglior singolo |
|
||||
| 8/M1 | Structural WF | 58.3% | +53.4% | 17.8% | 829 | Robusto |
|
||||
| 8/ens | Ensemble 2/3 | 59.2% | +19.9% | 7.2% | 520 | Più filtrato |
|
||||
| 8/ens3 | Ensemble 3/3 | 70.4% | +11.3% | 4.2% | 27 | Alta acc, pochi trade |
|
||||
| 4 | GBM fractal | 63.6% | +5.7% | ~3% | 66 | Pochi ma precisi |
|
||||
| 7 | LSTM | 58.4% | +4.3% | 3.1% | 214 | Comparabile a GBM |
|
||||
|
||||
### Analisi gap verso target
|
||||
|
||||
| Target | Attuale | Gap |
|
||||
|--------|---------|-----|
|
||||
| Accuracy >80% | max 70.4% (ens 3/3) | serve +10% |
|
||||
| ROI annuo >30% | max ~20% (structural) | serve +10% |
|
||||
| €50/giorno da €1000 | richiede ~5% daily | richiede crescita capitale su 6 mesi |
|
||||
|
||||
### 01:00 — Strategia 5 corretta (senza leakage)
|
||||
|
||||
**Reale dopo fix:** 53-58% accuracy (BTC LA=3 thr=0.65). Massimo 72.7% ma solo 11 trade. Conferma: senza leakage, edge tipico è 55-60%.
|
||||
|
||||
### 01:15 — SVOLTA: Strategia 11 — Volatility Squeeze Breakout
|
||||
|
||||
**Cosa:** approccio completamente diverso. Non predire la direzione direttamente. Identifica periodi di COMPRESSIONE (Bollinger dentro Keltner = squeeze), poi segui il breakout quando la volatilità ESPLODE.
|
||||
**Perché:** dopo compressione, il prezzo accumula "energia" e il breakout ha forte momentum direzionale. Approccio fisicamente motivato, non ML puro.
|
||||
**Atteso:** migliore di ML generico perché sfruttiamo un pattern strutturale ben definito
|
||||
**Reale:** **ECCEZIONALE**
|
||||
|
||||
| Config | Asset | TF | Trades | Accuracy | Ann. Return |
|
||||
|---|---|---|---|---|---|
|
||||
| BBw=20 sqThr=0.8 +VOL | ETH | 1h | 87 | **83.9%** | 22.2% |
|
||||
| BBw=30 sqThr=0.9 | ETH | 1h | 203 | **82.8%** | 46.8% |
|
||||
| BBw=20 sqThr=0.8 | ETH | 1h | 285 | **79.3%** | **65.7%** |
|
||||
| BBw=14 sqThr=0.8 | BTC | 1h | 438 | **77.6%** | **53.3%** |
|
||||
| BBw=14 sqThr=0.8 +VOL | BTC | 15m | 315 | **75.6%** | 6.0% |
|
||||
|
||||
**Lezione CRUCIALE:** gli approcci strutturali (compressione→espansione) battono ML generico di 20+ punti percentuali in accuracy. La struttura frattale del prezzo si manifesta nei cicli di compressione-espansione.
|
||||
|
||||
### Target assessment
|
||||
|
||||
| Target | Risultato | Status |
|
||||
|--------|-----------|--------|
|
||||
| Accuracy >80% | 83.9% (ETH 1h +VOL) | ✅ RAGGIUNTO |
|
||||
| ROI annuo >30% | 65.7% (ETH 1h) | ✅ RAGGIUNTO |
|
||||
| Fees considerate | 0.1% maker/taker | ✅ |
|
||||
|
||||
### 01:30 — Strategia 9: Walk-forward ML — COMPLETATA
|
||||
|
||||
**Cosa:** GBM con features structural+fractal, walk-forward validation (train 15K, step 3K), BTC e ETH su 2 lookahead × 4 threshold
|
||||
**Reale:**
|
||||
- BTC: max 58.4% acc, +75% ret, 8.8% ann, Sharpe 3.27 (LA=3, thr=0.70)
|
||||
- **ETH LA=3 thr=0.70: 57.7% acc, +758% ret, 38.1% ann, Sharpe 7.40, €3.12/giorno**
|
||||
- **ETH LA=6 thr=0.70: 56.5% acc, +1994% ret, 57.9% ann, Sharpe 6.72, €8.20/giorno**
|
||||
**Lezione:** walk-forward elimina il bias del singolo split. ETH più predittibile di BTC con ML. Sharpe >7 eccezionale per un sistema reale. Drawdown alto (47-52%) → servono nervi saldi.
|
||||
|
||||
### TOP 5 DEFINITIVO (aggiornato con strategia 9)
|
||||
|
||||
| # | Nome | Acc. | ROI ann | Sharpe | DD | €/day | Best for |
|
||||
|---|------|------|---------|--------|----|-------|----------|
|
||||
| 1 | ETH Squeeze+Vol (BBw=20) | **83.9%** | 22.2% | - | 2.0% | €0.71 | Precisione |
|
||||
| 2 | ETH Squeeze (BBw=30,sq=0.9) | **82.8%** | **46.8%** | - | 3.2% | €1.77 | Bilanciato |
|
||||
| 3 | ETH WF-ML (LA=3,thr=0.70) | 57.7% | **38.1%** | **7.40** | 47% | **€3.12** | Daily PnL |
|
||||
| 4 | ETH Squeeze aggressivo | 79.3% | **65.7%** | - | 3.6% | €2.79 | Max ROI |
|
||||
| 5 | ETH WF-ML (LA=6,thr=0.70) | 56.5% | **57.9%** | **6.72** | 53% | **€8.20** | Max growth |
|
||||
|
||||
### Piano operativo consigliato
|
||||
|
||||
**Fase 1 (mesi 1-3):** usa M2 (squeeze BBw=30, 82.8% acc, 3.2% DD) per crescita sicura
|
||||
**Fase 2 (mesi 4-6):** aggiungi M3 (WF-ML) per accelerare crescita con capitale più alto
|
||||
**Fase 3 (mese 6+):** combina entrambi — squeeze per trade sicuri, ML per volume
|
||||
|
||||
### 02:00 — Strategia 13: Squeeze + ML IBRIDA — IL VINCITORE
|
||||
|
||||
**Cosa:** squeeze breakout come pre-filtro (QUANDO tradare), GBM su features frattali/strutturali come conferma direzionale (QUALE direzione). Walk-forward validation. 12 configurazioni testate su BTC + ETH, 1h + 15m.
|
||||
**Atteso:** combinare accuratezza squeeze (>80%) con volume trade ML
|
||||
**Reale:**
|
||||
|
||||
**Vincitore assoluto: ETH 15m BBw=14 sq=0.8 ml_thr=0.70**
|
||||
- 76.9% accuracy, 118.1% annualizzato, 4.2% max drawdown
|
||||
- **€13.78/giorno da €1000** (!!)
|
||||
- 1213 trades nel test, ~313/anno → ~1 trade/giorno
|
||||
- Con 3x leva, 15% position size
|
||||
|
||||
**Runner-up: BTC 15m BBw=14 sq=0.9 ml_thr=0.70**
|
||||
- 78.8% accuracy, 68.8% ann, 7% DD, €5.51/day
|
||||
|
||||
**Osservazioni chiave:**
|
||||
1. Il 15m batte il 1h per frequenza trade (più segnali di squeeze a timeframe basso)
|
||||
2. ML non migliora drammaticamente l'accuracy rispetto a squeeze puro (baseline ETH 15m squeeze: 79.5%) ma RIDUCE il drawdown (da ~8% a 4.2%)
|
||||
3. Il vero valore del ML è nel filtraggio: scarta i breakout deboli, tiene i forti
|
||||
4. ETH più predittibile di BTC in tutte le configurazioni
|
||||
|
||||
**Piano per €50/giorno:**
|
||||
- Capitale attuale: €1000
|
||||
- Crescita stimata: 118% annuo
|
||||
- €1000 → €3600 in ~8 mesi
|
||||
- €3600 × €13.78/€1000 = €49.60/giorno ≈ target
|
||||
|
||||
### TOP 5 DEFINITIVO FINALE
|
||||
|
||||
| # | Config | Acc. | Ann. | DD | €/day | Tipo |
|
||||
|---|--------|------|------|----|-------|------|
|
||||
| 1 | ETH 15m Squeeze+ML (BBw=14,sq=0.8,ml=0.70) | 76.9% | **118%** | 4.2% | **€13.78** | Ibrido |
|
||||
| 2 | ETH 1h Squeeze+Vol (BBw=20,sq=0.8) | **83.9%** | 22% | 2.0% | €0.71 | Strutturale |
|
||||
| 3 | BTC 15m Squeeze+ML (BBw=14,sq=0.9,ml=0.70) | **78.8%** | 69% | 7.0% | €5.51 | Ibrido |
|
||||
| 4 | ETH 1h Squeeze (BBw=30,sq=0.9) | **82.8%** | **47%** | 3.2% | €1.77 | Strutturale |
|
||||
| 5 | ETH WF-ML (LA=3,thr=0.70) | 57.7% | 38% | 47% | €3.12 | ML puro |
|
||||
|
||||
### Prossimi passi
|
||||
|
||||
1. Implementare sistema live con Cerbero MCP per segnali real-time
|
||||
2. Paper trading per 2-4 settimane prima di capitale reale
|
||||
3. Risk management: stop-loss, max daily loss, correlation filter
|
||||
@@ -1,136 +0,0 @@
|
||||
# 2026-05-28 — Ricerca onesta di nuove strategie (post-squeeze)
|
||||
|
||||
## Contesto e mandato
|
||||
|
||||
Dopo aver scoperto che l'intera famiglia squeeze-breakout era un artefatto di
|
||||
look-ahead (accuratezze 76-82% svanite sotto ingresso eseguibile), il mandato è
|
||||
stato: trovare in modo **onesto** almeno 3 strategie attendibili, testate su ~8
|
||||
anni e su più criptovalute, con le fee incluse nella valutazione, partendo da
|
||||
€1.000 con l'obiettivo (aspirazionale) di €50/giorno. Esplorare anche idee fuori
|
||||
dal comune e l'uso combinato di più crypto e timeframe.
|
||||
|
||||
## Metodologia (engine onesto)
|
||||
|
||||
Tutto il lavoro usa un unico engine condiviso (`scripts/analysis/honest_lab.py`)
|
||||
con questi vincoli anti-illusione:
|
||||
|
||||
1. **Ingresso eseguibile.** Ogni segnale alla barra `i` usa solo dati fino a
|
||||
`close[i]` e l'ingresso avviene a `close[i]` (ciò che il worker live vede e
|
||||
può eseguire). Disponibile anche l'ingresso più conservativo a `open[i+1]`.
|
||||
2. **Uscita realistica.** Take-profit / stop-loss valutati intrabar su `high`/`low`,
|
||||
in modo conservativo (SL prima del TP nello stesso bar), più time-limit.
|
||||
Una posizione per volta (non-overlap), capitale composto.
|
||||
3. **Fee di prim'ordine.** Tutto è NETTO dopo fee round-trip realistiche Deribit
|
||||
(0.10% RT) moltiplicate per la leva (3x), con sweep fino a 0.20% RT.
|
||||
4. **Validazione severa.** FULL + out-of-sample (ultimo 30%) + conteggio anni
|
||||
positivi + sweep fee + griglia parametri + test su **8 crypto**
|
||||
(BTC, ETH, SOL, BNB, XRP, LTC, DOGE, ADA, 2018→2026).
|
||||
|
||||
## Lezione madre
|
||||
|
||||
**Shortare le crypto perde OOS in modo sistematico in questo campione.** Sia la
|
||||
mean-reversion sul lato short, sia il momentum short, crollano fuori campione: il
|
||||
periodo 2018-2026 è net-bull e ogni rialzo "estremo" tende a continuare invece di
|
||||
rientrare. Tutte le configurazioni che sopravvivono oneste sono **long-biased**.
|
||||
È un fatto da dichiarare: parte della performance OOS è correlata al beta rialzista
|
||||
delle crypto. Le strategie aggiungono *timing* sopra quel beta, non lo eliminano.
|
||||
|
||||
## Le 3 strategie selezionate (meccanismi distinti)
|
||||
|
||||
| Codice | Meccanismo | TF | Asset robusti | OOS netto (fee 0.10% RT) | DD | Anni+ |
|
||||
|--------|-----------|----|---------------|--------------------------|----|-------|
|
||||
| **DIP01** | Dip-buy z-score reversion (long-only) | 1h | BTC, ETH, SOL | BTC +59% · ETH +224% · SOL +13% | 23-55% | 6-7/9 |
|
||||
| **TR01** | EMA 20/100 trend-following (long-only) | 4h | BNB, BTC, DOGE, SOL, XRP | BTC +27% · DOGE +53% · XRP +29% | 29-53% | 4-6/8 |
|
||||
| **ROT01** | Rotazione cross-sectional momentum sul paniere | 1d | intero paniere (8) | **+44%** | 53% | 5/7 |
|
||||
|
||||
Dettagli e riproducibilità: `scripts/analysis/honest_final.py` (tabella di
|
||||
validazione unica), `honest_rotation.py`, `honest_trend.py`, `honest_candidates.py`,
|
||||
`honest_diag.py`/`honest_diag2.py` (diagnostica long/short e filtro trend).
|
||||
|
||||
### DIP01 — compra le capitolazioni
|
||||
Long-only: entra quando lo z-score del prezzo rispetto alla media a 50 barre scende
|
||||
sotto −2.5 (capitolazione), prende profitto al rientro verso la media, SL a 2.5·ATR.
|
||||
È la versione robusta e onesta della famiglia mean-reversion: regge lo sweep fee
|
||||
fino a 0.20% RT (BTC +45% OOS anche a 0.20%). Funziona sui major (BTC/ETH/SOL); sugli
|
||||
alt molto parabolici (DOGE/BNB) un dip fisso continua a scendere e non ha edge.
|
||||
|
||||
### TR01 — cavalca i trend
|
||||
Long-only: in posizione quando EMA(20) > EMA(100) sul 4h, altrimenti cash. Poche
|
||||
operazioni (≈200 flip in 8 anni) ⇒ le fee non sono letali. È **complementare** a
|
||||
DIP01: guadagna nei regimi di trend, dove la reversione soffre.
|
||||
|
||||
### ROT01 — la più affidabile e "fuori dal comune"
|
||||
Una sola strategia che usa **tutto il paniere** in un unico book: ogni giorno ordina
|
||||
le 8 crypto per momentum (rendimento a 60 giorni) e alloca a parti uguali alle 2
|
||||
migliori con momentum positivo, il resto in cash. Cattura la *dispersione* tra
|
||||
crypto (gli alt forti corrono molto più di BTC nei bull) senza shortare nulla.
|
||||
È **param-insensitive** (tutte le combinazioni lookback/top-k sono positive OOS) e
|
||||
regge le fee fino a 0.20% RT (+41% OOS). Risponde direttamente alla richiesta di
|
||||
combinare più crypto e un timeframe diverso in un'unica strategia. Per-anno:
|
||||
2020 +33% · 2021 +181% · 2022 −29% (bear) · 2023 +43% · 2024 +59% · 2025 +6% · 2026 −10% (YTD).
|
||||
|
||||
## Diversificazione
|
||||
|
||||
I tre meccanismi coprono regimi diversi e in larga misura anti-correlati:
|
||||
reversione (DIP01), momentum di singolo asset (TR01), forza relativa cross-asset
|
||||
(ROT01). Eseguirli insieme produce una curva di equity più liscia del singolo.
|
||||
|
||||
## Onestà sull'obiettivo €50/giorno
|
||||
|
||||
Va detto chiaramente: **€50/giorno su €1.000 in pochi mesi non è raggiungibile a
|
||||
rischio sano.** Significa ~€18.250/anno, cioè ~1.825%/anno; gli edge onesti qui
|
||||
trovati rendono il 30-60% OOS su orizzonti pluriennali. Le strade per avvicinare
|
||||
quel numero sono: (a) far crescere il capitale per anni con interesse composto —
|
||||
€50/giorno diventa plausibile solo quando il capitale è molto più grande; (b) alzare
|
||||
la leva, che però aumenta proporzionalmente il drawdown (già 23-55%) ed espone a
|
||||
rovina; (c) aggiungere capitale. Nessuna di queste è una scorciatoia. La proposta
|
||||
onesta è un portafoglio delle 3 strategie a leva moderata, puntando alla
|
||||
**sopravvivenza e alla crescita composta**, non al target giornaliero immediato.
|
||||
|
||||
## Miglioramenti (alzare Acc, ridurre DD, migliorare PnL)
|
||||
|
||||
Leve oneste e documentate, senza tuning sui singoli anni
|
||||
(`scripts/analysis/honest_improve.py`, `honest_improve2.py`):
|
||||
|
||||
### ROT02 — dual-momentum overlay (migliora TUTTO)
|
||||
Alla rotazione cross-sectional di ROT01 si aggiunge un overlay di *absolute
|
||||
momentum*: cash quando BTC è sotto la sua media a 100 giorni (mercato risk-off).
|
||||
Taglia i bear di sistema (gli unici anni rossi di ROT01).
|
||||
|
||||
| | FULL% | OOS% | DD% |
|
||||
|---|---|---|---|
|
||||
| ROT01 base | +679 | +44 | 53 |
|
||||
| **ROT02 (SMA100)** | **+1095** | **+98** | **40** |
|
||||
|
||||
PnL su, DD giù: dominanza su tutte e tre le metriche. Param-insensitive (SMA100-150).
|
||||
|
||||
### DIP01 — market-gate (variante low-DD)
|
||||
Comprare i dip solo quando BTC è risk-on alza l'**Acc** (ETH 52→57%, SOL 49→52%) e
|
||||
**dimezza il DD** (ETH 53→23%, SOL 25→13%), al costo di parte della PnL (meno trade).
|
||||
È de-risking, non un pasto gratis: utile per chi vuole una curva più liscia. Su BTC
|
||||
il gate va evitato (i dip migliori di BTC arrivano proprio quando BTC è sotto la
|
||||
propria SMA), quindi DIP01 base resta la versione di riferimento per BTC.
|
||||
|
||||
### PORT01 — portafoglio combinato (il vero motore di risk-reduction)
|
||||
Equal-weight giornaliero ribilanciato delle 3 sleeve anti-correlate
|
||||
(DIP01 BTC + TR01 basket + ROT02). La diversificazione porta il DD del portafoglio
|
||||
**sotto** quello della sleeve meno rischiosa, mantenendo una CAGR alta.
|
||||
|
||||
| Sleeve | ret% | DD% | CAGR% |
|
||||
|--------|------|-----|-------|
|
||||
| DIP01 BTC | +322 | 15 | 31 |
|
||||
| TR01 basket | +591 | 27 | 43 |
|
||||
| ROT02 dual-mom | +771 | 40 | 49 |
|
||||
| **PORTAFOGLIO** | **+642** | **12** | **45** |
|
||||
|
||||
Per-anno portafoglio: 2021 +203% · 2022 **−1%** (bear neutralizzato, era −30% su ROT) ·
|
||||
2023 +47% · 2024 +50% · 2025 +14% · 2026 −2% (YTD). Nessun anno realmente negativo,
|
||||
DD massimo 12%, CAGR 45%. È la configurazione di deployment raccomandata.
|
||||
|
||||
## Prossimi passi
|
||||
|
||||
- Integrare DIP01 nel worker (già compatibile: Signal con tp/sl/max_bars).
|
||||
- Trailing-stop ad ATR per TR01 (per alzarne l'Acc e ridurne ulteriormente il DD).
|
||||
- Estendere il worker per strategie position-based (TR01) e di portafoglio (ROT01).
|
||||
- Backtest del portafoglio combinato con ribilanciamento del capitale.
|
||||
- Walk-forward rolling (oltre al singolo split 70/30) per confermare la stabilità.
|
||||
@@ -1,193 +0,0 @@
|
||||
# 2026-05-28 — Giorno 3: Bug dati Cerbero, paper trader fermo, fix MT01 multi-timeframe
|
||||
|
||||
### 12:20 — Sintomo: paper trader live a zero trade
|
||||
|
||||
**Cosa:** check del container `pythagoras-multi` (multi-strategy paper trader, 6 strategie).
|
||||
**Reale:** container healthy da ore, ma **0 trade** su tutte le strategie, tutte FLAT a €1000.
|
||||
Primo falso indizio: `last_bar_ts: 0` in tutti gli `status.json`. Indagando il worker,
|
||||
quel campo si aggiorna **solo a posizione aperta** (contatore `hold_bars`), non ad ogni
|
||||
candela → non è la causa. Il loop era vivo (status.json riscritti ogni 60s).
|
||||
**Lezione:** non fidarsi del nome di un campo; verificare nel codice quando viene scritto.
|
||||
L'healthcheck del container controlla solo l'esistenza di `status.json`, non la freschezza
|
||||
→ un loop bloccato risulterebbe comunque "healthy".
|
||||
|
||||
### 12:45 — Causa radice: bug lato Cerbero MCP `get_historical`
|
||||
|
||||
**Cosa:** probe dirette all'endpoint `/mcp-deribit/tools/get_historical`.
|
||||
**Reale:** due bug lato server:
|
||||
1. **`end_date` data-nuda tronca a mezzanotte:** `end=oggi` restituiva candele solo fino a
|
||||
`oggi 00:00`. Il `df` live finiva sempre alla barra di mezzanotte e **non avanzava** durante
|
||||
la giornata → nessun breakout fresco sull'ultima barra → nessun ingresso (condizione worker
|
||||
`last_signal.idx >= last_idx - 1`).
|
||||
2. **Cap a ~5000 righe** che ignora `start_date`: una richiesta di 365g a 15m restituiva ~52
|
||||
giorni. Ecco perché ML01 si addestrava su soli 88 samples (overfit, train_acc 100%).
|
||||
**Lezione:** lo zero-trade non era nelle strategie ma nel feed dati. Sempre validare la
|
||||
freschezza/copertura dei dati prima di sospettare la logica.
|
||||
|
||||
### 13:30 — Fix lato Cerbero + verifica
|
||||
|
||||
**Cosa:** report passato al dev di `cerbero-mcp`; fix deployato (riavvio container) + doc
|
||||
aggiornata in `cerbero-mcp/docs/API_REFERENCE.md`.
|
||||
**Reale dopo deploy (verificato con probe):**
|
||||
- `end=oggi` (data nuda) → ultima candela = ora corrente (age ~3 min). ✅
|
||||
- 365g a 15m → **35.099 candele**, span 365.6g, nessun cap. ✅
|
||||
- Supportati anche timestamp con orario (`...T14:00:00`, naive = UTC). ✅
|
||||
|
||||
Nostro client (`src/live/cerbero_client.py`) invariato: passa già `end=oggi`, ora corretto.
|
||||
**Lezione:** "trust but verify" — la doc dichiarava i fix prima che fossero deployati; solo
|
||||
la probe diretta ha confermato cosa era davvero attivo sul server.
|
||||
|
||||
### 14:00 — Problema residuo: MT01 usava un trend 1h STANTIO
|
||||
|
||||
**Cosa:** check di tutte le strategie sul percorso di codice reale con dati freschi.
|
||||
**Reale:**
|
||||
- Tutte le 6 strategie girano senza crash; SQ01/SQ02 generano molti segnali.
|
||||
- **MT01 leggeva il trend 1h dal parquet statico** (`load_data(asset,"1h")`), non da Cerbero.
|
||||
Il parquet finiva a mezzanotte → per ogni barra 15m di oggi `searchsorted` cadeva oltre la
|
||||
fine e si agganciava sempre alla candela di mezzanotte (gap 14.8h). La conferma
|
||||
multi-timeframe — il cuore di MT01 — era di fatto congelata e il gap cresce ogni giorno.
|
||||
- In `data/raw/` mancavano del tutto i parquet **15m** (`btc_15m`, `eth_15m`) → backtest 15m rotti.
|
||||
**Lezione:** una strategia live che dipende da un file statico ha un punto cieco temporale;
|
||||
il dato live e quello di backtest devono provenire da fonti coerenti.
|
||||
|
||||
### 14:30 — Fix MT01: trend 1h live da Cerbero
|
||||
|
||||
**Cosa:** modifica al runner perché MT01 prenda l'1h live, non dal parquet.
|
||||
- `MT01.generate_signals` accetta un `df_1h` opzionale (fallback al parquet se assente).
|
||||
- `StrategyWorker.tick(df, df_1h=None)` lo inoltra ai signal.
|
||||
- `multi_runner` fa fetch 1h live (resolution 60) per gli asset MT01 ad ogni poll (`htf_cache`).
|
||||
**Reale (verificato a codice montato, pre-rebuild):** gap del trend 1h sull'ultima barra
|
||||
**0.75h** (fresco) contro **14.8h** col parquet statico. Segnali invariati sullo storico.
|
||||
**Lezione:** isolare la dipendenza dal file statico rende MT01 immune al drift tra un
|
||||
`download_all()` e l'altro.
|
||||
|
||||
### 14:55 — Rigenerazione dati + rebuild
|
||||
|
||||
**Cosa:** `download_asset` per 15m+1h (saltati 1m/5m, lenti e inutilizzati), poi
|
||||
`docker compose up -d --build` (il codice `src/` è baked nell'immagine).
|
||||
**Reale:** parquet rigenerati con storia completa 2018→2026 e freschi (15m fino alle 14:45,
|
||||
1h fino alle 14:00). Container ripartito: 6 strategie attive, ML01 riaddestrato su **534
|
||||
samples** (anno pieno), MT01 senza errori, fetch 1h live OK.
|
||||
|
||||
### 15:00 — Regressione backtest sui dati rigenerati
|
||||
|
||||
**Cosa:** rilanciati i backtest per confermare che i numeri documentati si riproducano sui
|
||||
dati ricreati da zero (BTC/ETH 15m, hold=3, fee 0.2% RT, leva 3x, pos 15%).
|
||||
**Reale:** accuratezze e drawdown **identici**, solo +1/+3 trade dalle barre recenti in più.
|
||||
|
||||
| Strategia | Ottenuto | Documentato | Esito |
|
||||
|---|---|---|---|
|
||||
| SQ01 BTC 15m | 76.7% / DD 6.7% / 4063t | 76.7% / 6.7% / 4062 | ✓ |
|
||||
| SQ01 ETH 15m | 76.4% / 6.2% / 2951t | 76.4% / 6.2% / 2948 | ✓ |
|
||||
| SQ02 BTC 15m | 79.7% / 6.5% / 1251t | 79.7% / 6.5% / 1250 | ✓ |
|
||||
| SQ02 ETH 15m | 78.6% / 3.4% / 944t | 78.6% / 3.4% / 942 | ✓ |
|
||||
| **MT01 BTC 15m (ema20+vol)** | **82.7% / 5.9% / 503t** | 82.7% / 5.9% / 503 | ✓ esatto |
|
||||
| MT01 ETH 15m (ema20+vol) | 81.2% / 2.9% / 404t | — | ok |
|
||||
|
||||
**Lezione:** l'integrità dei dati rigenerati è confermata — la pipeline di download produce
|
||||
risultati riproducibili. La config live di MT01 (ema20+vol) coincide col best documentato.
|
||||
|
||||
### Punti aperti
|
||||
|
||||
1. **Backtest e drift dati:** MT01 live ora è immune (1h da Cerbero), ma i backtest girano
|
||||
sempre sui dati fino all'ultimo `download_all()`. Per dati di backtest sempre freschi
|
||||
serve uno scheduling del download (cron/job).
|
||||
2. **Healthcheck:** valutare un check su mtime di `status.json` (< 180s) per rilevare uno
|
||||
stallo del loop, non solo l'esistenza del file.
|
||||
|
||||
---
|
||||
|
||||
### 23:00 — 3 nuove strategie con edge OOS fee-aware (branch `strategy_free`)
|
||||
|
||||
**Obiettivo:** trovare almeno 3 nuove strategie (oltre MR01), edge netto validato
|
||||
out-of-sample e fee-aware, per il target €1.000 → ~€50/giorno.
|
||||
|
||||
**Metodologia (invariata dalla lezione squeeze):** ingresso eseguibile a `close[i]`
|
||||
(nessun look-ahead), backtest netto dopo fee Deribit 0.10% RT + leva 3x, OOS = ultimo
|
||||
30% held-out, robustezza su griglia parametri + sweep fee 0.00–0.20% RT, exit
|
||||
TP/SL intrabar o time-limit, una posizione per volta, capitale composto.
|
||||
|
||||
**Candidati** (`scripts/analysis/strategy_research_v2.py`), tutti mean-reversion
|
||||
(l'edge è sempre il rientro, mai la continuazione):
|
||||
|
||||
| Candidato | Esito | Motivo |
|
||||
|---|---|---|
|
||||
| **MR02 Donchian Fade** | ✅ | Robusto su tutta la griglia `n × sl_atr` e tutte le fee |
|
||||
| **MR03 Keltner Fade** | ✅ | Robusto su tutta la griglia `n × k`; banda ATR, indipendente da Bollinger |
|
||||
| **MR07 Return Reversal** | ✅ | Intero blocco `tp_atr=2.0` positivo full+OOS; esposizione ~8% |
|
||||
| MR04 Z-score Reversion | ⛔ | Robusto ma è MR01 riparametrizzato (stessa banda std): edge non *nuovo* |
|
||||
| MR05 Bollinger + filtro ADX | ⛔ | Non robusto: negativo su gran parte della griglia BTC |
|
||||
| MR06 RSI(2) Connors | ⛔ | ETH 1h negativo; non robusto su entrambi gli asset |
|
||||
|
||||
**Risultati** (netto 0.10% RT, leva 3x, OOS, 1h):
|
||||
|
||||
| Codice | Meccanismo | BTC OOS | ETH OOS | DD (full) |
|
||||
|---|---|---|---|---|
|
||||
| MR02 | estremi canale Donchian H/L | +172% | enorme | 30% / 42% |
|
||||
| MR03 | canale ATR su EMA | +112% | +886% | 37% / 66% |
|
||||
| MR07 | z dei rendimenti di barra | +105% | +195% | 25% / 46% |
|
||||
|
||||
**Validazione live-path** (`oos_validation.py`, legge `strategies.yml`, exit hold
|
||||
del worker): tutte e tre positive netto OOS su tutto lo sweep fee, anche al
|
||||
pessimistico 0.20% RT → edge robusto pure al meccanismo di exit.
|
||||
|
||||
**Verifiche:** equivalenza esatta backtest produzione vs research engine (MR02 BTC:
|
||||
2039 trade, DD 29% identici); le 3 classi si caricano dal `strategy_loader`;
|
||||
aggiunte a `strategies.yml` (BTC+ETH 1h). Nessuna suite di test nel progetto.
|
||||
|
||||
**Onestà sul target:** con 4 fade indipendenti × 2 asset il PnL storico aggregato
|
||||
supera €50/giorno, ma sono backtest a leva 3x su 8 anni con annate eccezionali
|
||||
(ETH 2024). Plausibile ma da confermare col paper trader live prima del capitale reale.
|
||||
DD alto su ETH (MR03 ~66%, come MR01) → leva più bassa consigliata per quell'asset.
|
||||
|
||||
**File:** `strategy_research_v2.py`, `src/strategies/fade_base.py`,
|
||||
`scripts/strategies/MR0{2,3,7}_*.py` (nuovi); `strategy_loader.py`, `strategies.yml`,
|
||||
`CLAUDE.md` (aggiornati).
|
||||
**Lezione confermata:** ogni edge robusto trovato finora è mean-reversion; ogni
|
||||
variante trend/continuation o oscillatore senza filtro perde netto.
|
||||
|
||||
---
|
||||
|
||||
### 23:45 — Aumentare Acc e ridurre DD (filtro trend + portafoglio)
|
||||
|
||||
**Obiettivo:** alzare accuratezza e abbassare drawdown sulle 4 fade, senza
|
||||
distruggere l'edge né overfittare (ogni leva misurata FULL **e** OOS).
|
||||
|
||||
**Diagnosi:** perdite/DD concentrati 2018–2021 (bear/covid/caos vol), su ETH DD
|
||||
pieno 66–71%. Banco di prova: `scripts/analysis/risk_improvements.py` e
|
||||
`risk_portfolio.py`.
|
||||
|
||||
**Leve testate:**
|
||||
|
||||
| Leva | Esito | Motivo |
|
||||
|---|---|---|
|
||||
| Sizing vol-target (size ∝ 1/dist-SL) | ⛔ | Over-size sui trade a stop stretto → DD su, ritorno giù |
|
||||
| Skip alta volatilità (ATR% in coda alta) | ⛔ | L'alta vol è *positiva* per le fade (più reversione): Acc e ritorno giù |
|
||||
| **Filtro trend** (`\|close−EMA200\|/ATR > soglia` → salta) | ✅ | Non fada trend/crolli estremi: Acc↑ ovunque, DD↓ molto su ETH, OOS regge |
|
||||
| **Portafoglio** equipesato (sotto-conti indipendenti) | ✅ | Curve poco correlate → DD aggregato 14% (full)/10% (OOS) vs 20-70% singolo |
|
||||
|
||||
**Filtro trend — sweep soglia** (assoluta in ATR, regola unica per tutte = niente
|
||||
overfit): 3.0 ATR è l'equilibrio (2.0 taglia troppo ritorno). Effetto su config
|
||||
deployata (base → filtro):
|
||||
|
||||
| Sleeve | Acc | DD |
|
||||
|---|---|---|
|
||||
| MR01 ETH | 46→55 | **71→26** |
|
||||
| MR02 ETH | 49→55 | 42→25 |
|
||||
| MR03 ETH | 49→52 | 66→34 |
|
||||
| MR07 ETH | 48→54 | 46→21 |
|
||||
| MR01 BTC | 51→54 | 32→34* |
|
||||
| MR02 BTC | 48→52 | 29→23 |
|
||||
| MR07 BTC | 49→53 | 25→18 |
|
||||
| MR03 BTC | 47→47 | 37→37 (filtro OFF) |
|
||||
|
||||
\*MR01 BTC: DD full +2pt ma Acc +3.7 e DD OOS piatto (14.8→15.0). **MR03 BTC**:
|
||||
il filtro peggiora entrambe (unico sleeve) → lasciato disattivo nello yaml.
|
||||
|
||||
**Implementazione:** helper `trend_distance()` in `fade_base.py`; param opzionali
|
||||
`trend_max`/`ema_long` (default None = retro-compatibile) in tutte le strategie
|
||||
(MR01/02/03/07); `strategies.yml` con `trend_max: 3.0, ema_long: 200` (eccetto
|
||||
MR03 BTC). Verificato: equivalenza produzione vs ricerca.
|
||||
|
||||
**Lezione:** il modo onesto di ridurre il DD non è strozzare il sizing (peggiora),
|
||||
ma (a) non opporsi a trend estremi e (b) diversificare su strategie scorrelate.
|
||||
@@ -1,155 +0,0 @@
|
||||
# Diario — 2026-05-29 — Esplorazione di nuove famiglie di strategie
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Trovare 5-10 nuove famiglie di strategie, diverse da quelle esistenti, migliori o
|
||||
complementari, con DD basso e attenzione alle fee. Esplorazione onesta (no
|
||||
look-ahead, netto fee, OOS) condotta con **agenti paralleli**, ognuno su una famiglia
|
||||
indipendente, tutti sullo stesso harness condiviso (`scripts/analysis/explore_lab.py`).
|
||||
Lavoro sul branch `strategy_explore`.
|
||||
|
||||
## Famiglie esplorate (9) ed esito onesto
|
||||
|
||||
| Famiglia | Esito | Note |
|
||||
|---|---|---|
|
||||
| **Pairs / spread reversion** | ✅ **VINCITORE** | Market-neutral, genuinamente nuova, decorrelata |
|
||||
| **TSMOM multi-orizzonte** | ✅ diversificatore | Marginale ma distinto (corr 0.53 con ROT02), DD basso |
|
||||
| Stagionalità settimanale | ⚠️ marginale/fragile | "Mercoledì-long-24h" 7/8 asset OOS+ ma effetto concentrato a 00:00 UTC |
|
||||
| Vol-target BTC | ⚠️ marginale | Sharpe 0.94 vs 0.76 buy&hold, DD ancora 44% |
|
||||
| Stagionalità intraday (ora) | ❌ rumore | L'edge orario muore sotto le fee |
|
||||
| Stagionalità mensile/turn-of-month | ❌ rumore | Reale in-sample, morto OOS dal 2024 |
|
||||
| Cross-sectional reversal | ❌ nessun edge | Perde vs equal-weight, corr 0.98 col momentum |
|
||||
| Opening-range breakout | ❌ non generalizza | Solo BTC/ETH, alcuni regimi, fee-fragile |
|
||||
| Lead-lag BTC→alt | ❌ nessun edge | Reazione contemporanea (corr lag+1 ≈ 0), non batte buy&hold |
|
||||
| Momentum/continuation intraday | ❌ negativo | Conferma: il *fade* (mean-reversion) domina |
|
||||
|
||||
7 famiglie su 9 sono rumore — e l'harness le ha rifiutate senza produrre falsi
|
||||
positivi (segnale che la metodologia onesta funziona). Due edge reali emergono.
|
||||
|
||||
## Vincitore 1 — PAIRS (market-neutral) — `PR01_pairs_reversion.py`
|
||||
|
||||
Scommette sul rientro del log-ratio di due cripto verso la media (z-score). Quando
|
||||
`z ≤ −2` → long A / short B; `z ≥ +2` → l'opposto; esce al rientro (`|z| ≤ 0.5`) o a
|
||||
tempo. Engine onesto verificato in `pairs_research.py` (test esplicito no-look-ahead:
|
||||
`z[i]` invariato perturbando il futuro). Fee contate su **2 gambe** (0.20% RT/coppia).
|
||||
|
||||
Validazione (netto, leva 3x, OOS = ultimo 30%, 1h):
|
||||
|
||||
| Coppia | CAGR | Sharpe | OOS DD | anni+ |
|
||||
|---|--:|--:|--:|--:|
|
||||
| ETH/BTC | 144% | 4.04 | 17% | 8/9 |
|
||||
| LTC/ETH | 71% | 2.52 | 10% | 7/8 |
|
||||
| ADA/ETH | 77% | 2.16 | 11% | 7/8 |
|
||||
|
||||
Tutte le 10 coppie testate positive FULL+OOS, regge fee 0.40% RT/coppia, correlazione
|
||||
col mercato ~0.02 (market-neutral confermato). DD pieno 42-49% (alto), ma OOS DD
|
||||
10-17% (buono) e soprattutto **quasi-zero correlazione** col resto → diversificatore
|
||||
eccezionale. Limite: 2 gambe (long+short), il worker live va esteso prima del live.
|
||||
|
||||
## Vincitore 2 — TSM01 (TSMOM multi-orizzonte) — `tsmom_research.py`
|
||||
|
||||
Long-only multi-crypto: tiene equal-weight gli asset con consenso pieno del segno di
|
||||
momentum su 3/6/12 mesi, cash se BTC<SMA100. Distinto da ROT02 (persistenza assoluta
|
||||
vs ranking relativo), corr 0.53. FULL +169% / OOS +80% / DD 22% / Sharpe 1.07,
|
||||
**mai un anno negativo**, regge fee 0.40%. Verificato no-look-ahead (cheat-test
|
||||
esplode a +575%). Marginale come stand-alone (rende meno di ROT02) ma utile in ensemble.
|
||||
|
||||
## Il payoff — combinare le nuove fonti col MASTER (`combine_v2.py`)
|
||||
|
||||
Le nuove sleeve sono quasi scorrelate col MASTER-9 (pairs ~0.02-0.08, TSM01 0.05).
|
||||
Aggiungerle migliora nettamente il portafoglio:
|
||||
|
||||
| Portafoglio | CAGR | DD% | Sharpe | OOS DD% | OOS Sharpe |
|
||||
|---|--:|--:|--:|--:|--:|
|
||||
| MASTER-9 (base) | 47 | 5.2 | 4.23 | 4.7 | 4.33 |
|
||||
| **MASTER + pairs (12)** | **66** | **3.8** | **5.67** | **3.3** | **6.86** |
|
||||
| MASTER + TSM01 (10) | 44 | 4.7 | 4.21 | 4.2 | 4.33 |
|
||||
| MASTER esteso (13) | 62 | 3.6 | 5.66 | 3.0 | 6.79 |
|
||||
|
||||
I **pairs** sono l'aggiunta decisiva: alzano la CAGR (47→66), **abbassano il DD**
|
||||
(5.2→3.8 full, 4.7→**3.3** OOS) e portano lo Sharpe OOS a **6.86** — il free-lunch
|
||||
della diversificazione da una fonte market-neutral scorrelata. TSM01 contribuisce
|
||||
poco (diluisce il ritorno) ma abbassa lievemente il DD.
|
||||
|
||||
## Caveat onesti
|
||||
|
||||
- I pairs hanno DD pieno alto (42-49%) sull'1h; il vantaggio sta nella decorrelazione,
|
||||
non nel DD stand-alone. Richiedono esecuzione a 2 gambe (short del perp B) — da
|
||||
verificare shortabilità/liquidità sugli alt e raddoppio fee nel worker.
|
||||
- Sharpe combinati 5-7 e CAGR 60%+ sono backtest a leva 3x su finestra 2021-2026 con
|
||||
OOS ~1.6 anni e il 2024 cripto eccezionale: numeri ottimistici, da confermare in
|
||||
paper trading live.
|
||||
- TSMOM e le strategie honest condividono l'overlay risk-off SMA100: parte della loro
|
||||
difensività è comune (non perfettamente indipendente).
|
||||
|
||||
## Terza ondata — espansione dei meccanismi provati + 2 nuovi sondaggi
|
||||
|
||||
Esplorate altre 4 direzioni con agenti paralleli:
|
||||
- **Fade su 6 nuovi alt (ADA/BNB/DOGE/LTC/SOL/XRP)**: 0 robuste. La mean-reversion
|
||||
fade vive solo su BTC/ETH (liquidi); sugli alt sparisce o è artefatto di pochi pump
|
||||
(DOGE). Coerente con la lezione del progetto.
|
||||
- **Espansione PAIRS** (tutte le 28 coppie): trovate **3 nuove coppie robuste** →
|
||||
BTC/LTC (robusta 1h *e* 4h, Sharpe 2.21, DD 24-34%, concentrazione PnL 9%), ETH/SOL
|
||||
e BNB/ETH (Sharpe 2.4+, solo 1h). Pattern: sempre alt-liquido vs major, mai alt/alt.
|
||||
PR01 ora ha **6 coppie**.
|
||||
- **Low-volatility anomaly**: ❌ in cripto è INVERTITA (vince l'alta vol = alta beta),
|
||||
ridondante con EW+risk-off/ROT02. L'anti-test high-vol stravince.
|
||||
- **Confluenza multi-timeframe (fade 1h confermato da 4h)**: non crea edge nuovo e non
|
||||
migliora lo Sharpe, ma **dimezza il DD** di MR01 (ETH: stesso Sharpe 3.17 a DD 38% vs
|
||||
63%) e stabilizza l'OOS → utile variante low-DD, non strategia indipendente.
|
||||
|
||||
## Bilancio finale e MASTER esteso (6 pairs)
|
||||
|
||||
Robusti deployabili: **famiglia PAIRS (6 coppie) + TSM01** (+ confluenza MTF come variante
|
||||
low-DD di MR01, + tilt stagionale mercoledì marginale). I 6 pairs sono quasi scorrelati col
|
||||
MASTER (corr 0.02-0.08). MASTER + 6 pairs:
|
||||
|
||||
| Portafoglio | CAGR | DD% | Sharpe | OOS DD% | OOS Sharpe |
|
||||
|---|--:|--:|--:|--:|--:|
|
||||
| MASTER-9 (base) | 47 | 5.2 | 4.23 | 4.7 | 4.33 |
|
||||
| **MASTER + 6 pairs (15)** | **71** | 5.7 | **5.93** | **2.3** | **7.71** |
|
||||
| MASTER esteso +TSM01 (16) | 67 | 5.4 | 5.95 | **2.2** | 7.67 |
|
||||
|
||||
Aggiungere i 6 pairs porta l'**OOS DD a 2.2-2.3%** (da 4.7%) con Sharpe OOS ~7.7 e tutti
|
||||
gli anni positivi: il guadagno di diversificazione da fonti market-neutral scorrelate.
|
||||
|
||||
## Quarto giro — validazione anti-overfitting e irrobustimento
|
||||
|
||||
Tre audit scettici paralleli (walk-forward, plateau, stress, scomposizione):
|
||||
|
||||
**Pairs — de-overfittati.** Sostituita la config per-coppia (cherry-picking di z_exit/n)
|
||||
con **una config universale `n=50 z_in=2.0 z_exit=0.75 max_bars=72`**. Verifiche:
|
||||
- plateau (non picco): heatmap n×z_in → 20/20 celle Sharpe>1 su ETH/BTC e BTC/LTC;
|
||||
- walk-forward (train 2y / test 6m rolling): ETH/BTC 11/12 finestre positive, BTC/LTC
|
||||
9/10 → edge distribuito su tutta la storia, non un regime singolo;
|
||||
- **BNB/ETH scartata** (era robusta solo coi suoi parametri → overfit; crolla con la
|
||||
universale e muore per prima allo stress costi). Famiglia ridotta a **5 pairs**.
|
||||
- stress: 5/6 reggono fee+slippage realistici; solo ETH/BTC regge fee 6x (coda fee-fragile).
|
||||
|
||||
**Master — numeri sobri.** L'OOS Sharpe 7.7 / DD 2.3% è **ottimistico ~50%** perché l'OOS
|
||||
cade nel bull calmo 2024-25. Numeri onesti da usare:
|
||||
- worst-DD su finestra mobile 90g (2021-2026) = **5.7%** (bear FTX) → budget DD ~6%, non 2.3%;
|
||||
- Sharpe per-semestre: mediana **~5** (min 1.2, max 12) → atteso ~5, non 7.7;
|
||||
- ogni anno e ogni semestre dal 2021 positivo (anche il 2022 bear, grazie alle gambe short);
|
||||
- equal-weight ≈ inverse-vol (non dipende da pesi fortunati);
|
||||
- regge **leva 2x + slippage doppio** (CAGR 36%, Sharpe 5.1);
|
||||
- **rischio concentrato: i pairs portano ~57% del rischio** → cap consigliato ~30-35%.
|
||||
- Config robusta raccomandata: **MASTER-esteso, equal-weight, leva 2x, cap pairs ~30-35%**.
|
||||
|
||||
**TSM01 — confermato robusto** (36/36 config OOS+, walk-forward stabile) ma corr reale con
|
||||
ROT02 = **0.62** (non 0.53), e gran parte del DD basso viene dall'overlay risk-off condiviso.
|
||||
Tenuto come diversificatore con **gross 0.30** (stesso Sharpe, DD 22%→15%).
|
||||
|
||||
**Confluenza multi-TF — SCARTATA: era overfit.** Taglia il 97% dei trade (restano ~40 in
|
||||
8 anni = non significativo), distrugge lo Sharpe (1.58→0.27 su BTC) e il caso "bello" non
|
||||
sopravvive alle perturbazioni. Per abbassare il DD di MR01 meglio ridurne la leva, non il filtro 4h.
|
||||
|
||||
**Risultato del giro:** quanto trovato regge l'esame anti-overfit (NON è l'errore squeeze),
|
||||
ma i numeri vanno comunicati sobri (Sharpe ~5, DD ~6%) e con leva 2x + cap pairs. Famiglia
|
||||
pairs consolidata a 5 coppie con config universale; confluenza MTF rimossa dai vincitori.
|
||||
|
||||
## File creati (branch strategy_explore)
|
||||
|
||||
`scripts/analysis/explore_lab.py` (harness onesto condiviso), `pairs_research.py`
|
||||
(verifica + ricerca pairs), `tsmom_research.py` (TSM01), `combine_v2.py` (master
|
||||
esteso); `scripts/strategies/PR01_pairs_reversion.py` (artefatto pairs).
|
||||
@@ -1,84 +0,0 @@
|
||||
# Diario — 2026-05-29 — Pattern del segnale per FORMA (analog/shape forecasting)
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Verificare se la **forma** del segnale (la morfologia recente del prezzo) permette di
|
||||
prevedere l'andamento successivo, e ricavarne edge verso il target €1000 → €50/giorno.
|
||||
Esplorazione onesta (no look-ahead, netto fee, OOS) con **agenti paralleli**, ognuno su
|
||||
una famiglia di forma indipendente, tutti sullo stesso harness shape (`scripts/analysis/
|
||||
shape_lab.py`, che riusa l'engine netto-fee+OOS di `explore_lab.py`). Branch `shape_patterns`.
|
||||
|
||||
## Harness
|
||||
|
||||
`shape_lab.py` — analog forecasting causale: a ogni barra `i` si guarda la forma recente
|
||||
`W` (closes z-normalizzati fino a `close[i]`), si cercano nel passato le `K` finestre più
|
||||
simili **il cui esito a `H` barre era già noto prima di `i`** (KDTree ricostruito ogni
|
||||
`rebuild` barre → niente O(N²)), si prevede la direzione = segno del rendimento medio degli
|
||||
analoghi. **No-look-ahead verificato** (perturbare il futuro non cambia la forma a `i`,
|
||||
max diff 0.0). Baseline forma grezza: marginale e **muore sulle fee** (W24H12K50: FULL
|
||||
+112% / OOS +48% ma a 0.20% RT → −72%; troppi trade, exp 74%, win 49.5%).
|
||||
|
||||
## Famiglie esplorate (5) ed esito onesto
|
||||
|
||||
| Famiglia | Esito | Note |
|
||||
|---|---|---|
|
||||
| Analog kNN (forma grezza, selettività) | ❌ RUMORE | Solo BTC-overfit, non robusto ≥2 asset |
|
||||
| Encoding candele (UP/DOWN/DOJI + body/shadow) | ❌ RUMORE | Hit-rate condizionale ~50%, segno incoerente fra asset |
|
||||
| DTW + template geometrici (M/W, testa-spalle, V, U) | ❌ RUMORE | DTW *peggiora* l'euclidea; template overfit (FULL ok, OOS crolla) |
|
||||
| PIP / pivot / zig-zag (geometria svolte) | ❌ RUMORE | 0/48 config robuste; le rotture S/R rientrano (riconferma MR) |
|
||||
| **Feature-vector + ML walk-forward** | ✅ **EDGE REALE** | LogisticRegression sulla forma, fee-robusto |
|
||||
|
||||
4 famiglie su 5 sono rumore: riconfermano che la forma grezza non contiene edge
|
||||
direzionale eseguibile e che l'unico edge "classico" resta la mean-reversion (fade/pairs).
|
||||
|
||||
## L'edge: SH01 — Shape-ML
|
||||
|
||||
Una **LogisticRegression** legge 17 feature di forma (body/shadow ratio, rendimenti,
|
||||
pendenza/curvatura del path, posizione di max/min, RSI, estensione) e predice il segno del
|
||||
rendimento a `H` barre. **Walk-forward rigoroso**: scaler+modello fittati solo sul passato
|
||||
con esito noto, poi predicono il blocco corrente; si entra a `close[i]` se la probabilità
|
||||
≥ soglia. Causalità verificata con check espliciti (feature e predizioni invarianti al
|
||||
futuro). Il GradientBoosting dà edge equivalente ma è ~60× più lento → si usa il logit.
|
||||
|
||||
A differenza della famiglia squeeze (che moriva anche a fee zero), **questo edge
|
||||
sopravvive a fee 0.20% RT**. Win-rate ~50% → l'edge è nell'**asimmetria** (quando indovina
|
||||
la direzione i moti sono più grandi), non nella frequenza.
|
||||
|
||||
### Validazione dura (config W24 H12 th0.58, netto fee, leva 3x, pos 0.15, OOS 30%)
|
||||
|
||||
- **Multi-asset expanding**: robusti **BTC** (FULL +219% / OOS +42% / Sharpe 2.72 / DD 23%
|
||||
/ 8-9 anni+ / accOOS 56%), **ETH** (+80% / +144% / Sharpe 1.21, più volatile), **ADA**
|
||||
(+707% / +57% / Sharpe 3.22). Scartati LTC/SOL/XRP (perdono netti).
|
||||
- **Walk-forward rolling (train fisso 2 anni)**: regge **solo BTC** (+166% / +96% / Sharpe
|
||||
2.05). L'edge si appoggia in parte alla memoria lunga → BTC è il più solido.
|
||||
- **Stress leva 2x + slippage doppio (0.20% RT)**: BTC OK (+40% / +17% / Sharpe 1.24),
|
||||
ETH marginale (+7% / +73% / Sharpe 0.37).
|
||||
- **Griglia (W,H,thresh) su BTC**: **5/27 celle robuste**, su una **cresta** stretta (W24,
|
||||
H8-12), non altopiano largo → rischio overfit moderato. Per prudenza si sceglie la config
|
||||
robusta sul maggior numero di test (W24 H12 th0.58), non il PnL massimo (W24 H8 rende di
|
||||
più ma accOOS ~49% = più drift che segnale).
|
||||
|
||||
### Il valore vero: diversificatore di portafoglio
|
||||
|
||||
Correlazione daily col MASTER **+0.08** (quasi scorrelato). Aggiungere lo sleeve shape
|
||||
(BTC+ETH) al MASTER migliora l'OOS: **Sharpe 4.33 → 5.10, DD 4.7% → 4.2%** (FULL: Sharpe
|
||||
4.23 → 4.37, DD 5.2% → 4.3%). Non è un motore standalone (per-asset troppo stretto fuori
|
||||
da BTC), ma un **free-lunch** da aggiungere al paniere.
|
||||
|
||||
## Artefatti
|
||||
|
||||
- `scripts/analysis/shape_lab.py` — harness analog/forma causale.
|
||||
- `scripts/analysis/shape_{analog,candle,template,pivot,ml}_research.py` — le 5 ricerche.
|
||||
- `scripts/analysis/shape_ml_validate.py` — validazione dura del candidato ML.
|
||||
- `scripts/strategies/SH01_shape_ml.py` — la strategia (Strategy + run() riproducibile).
|
||||
- Aggiunta a `MODULE_MAP` (caricabile per backtest).
|
||||
|
||||
## Conclusione e prossimi passi
|
||||
|
||||
La forma del segnale **non** predice in modo grezzo (4/5 famiglie rumore), ma un modello
|
||||
lineare sulle feature di forma in walk-forward onesto **sì**, soprattutto su BTC, e vale
|
||||
come diversificatore quasi-scorrelato del MASTER. Da fare prima del live:
|
||||
1. **Worker con retraining periodico** (lo StrategyWorker attuale è a regola fissa; SH01
|
||||
riallena il modello → serve un loop tipo legacy signal_engine).
|
||||
2. Validazione live-path (replay worker == backtest) come fatto per i pairs.
|
||||
3. Decidere il peso nel MASTER-esteso (cap, leva) col paper trader.
|
||||
@@ -1,64 +0,0 @@
|
||||
# Diario di ricerca — 2026-05-29
|
||||
|
||||
## Combinare le strategie migliora i risultati?
|
||||
|
||||
**Domanda:** usare insieme le due famiglie di strategie presenti sul repo migliora
|
||||
il profilo rischio/rendimento rispetto a usarle separatamente?
|
||||
|
||||
- **FADE** (mie): reversione intraday 1h, long/short, BTC/ETH — MR01 Bollinger,
|
||||
MR02 Donchian, MR03 Keltner, MR07 Return-reversal (tutte col filtro trend 3.0 ATR).
|
||||
- **HONEST** (altra sessione): long-only multi-regime multi-crypto — DIP01 (dip-buy
|
||||
1h BTC), TR01 (EMA-trend 4h basket), ROT02 (dual-momentum rotation 1d).
|
||||
|
||||
**Metodo** (`scripts/analysis/combine_portfolio.py`): per ogni sleeve si costruisce
|
||||
l'equity **giornaliera** normalizzata su un indice comune (2021-01-01 → 2026-05-26),
|
||||
si passa ai rendimenti giornalieri, si misura la correlazione cross-famiglia e si
|
||||
confrontano i portafogli equal-weight (ribilanciati ogni giorno), 50/50 fra famiglie
|
||||
e inverse-vol. Metriche FULL e OOS (ultimo 30% della finestra comune, da 2024-10-12):
|
||||
ritorno, CAGR, max DD, Sharpe annualizzato. Le curve honest sono riusate da
|
||||
`honest_improve2.py`; quelle fade da `risk_management.build_trades`.
|
||||
|
||||
**Correlazione:** cross-famiglia **+0.05** (quasi indipendenti). Intra-fade +0.18,
|
||||
intra-honest +0.05. L'unica coppia un po' correlata è MR01_BTC↔DIP01_BTC (+0.43),
|
||||
entrambe mean-reversion su BTC. Famiglie scorrelate ⇒ diversificazione quasi ideale.
|
||||
|
||||
**Risultati (FULL | OOS):**
|
||||
|
||||
| Portafoglio | Ret% | CAGR | DD% | Sharpe | oDD% | oSharpe |
|
||||
|---|---|---|---|---|---|---|
|
||||
| FADE only (8) | +549 | 41 | 8.6 | 3.75 | 5.4 | 4.14 |
|
||||
| HONEST only (3) | +642 | 45 | 12.0 | 1.90 | 6.5 | 2.23 |
|
||||
| **ALL equal-weight (11)** | +589 | 43 | 6.1 | **3.95** | 4.6 | **4.46** |
|
||||
| **ALL 50/50 famiglie** | +615 | 44 | **5.5** | 3.18 | **4.0** | 3.87 |
|
||||
| ALL inverse-vol | +483 | 39 | 5.8 | 3.97 | 4.6 | 4.02 |
|
||||
|
||||
**Conclusione: sì, combinare conviene.**
|
||||
- DD crolla: combinato 5.5–6.1% full / 4.0–4.6% OOS, contro 8.6% (fade) e **12%**
|
||||
(honest) da sole → drawdown ridotto del 35–50%.
|
||||
- Sharpe sale: combinato OOS **4.46** vs honest 2.23 (raddoppia) e batte pure fade (4.14).
|
||||
- CAGR resta ~43–44% (≈ media delle due famiglie) ma con metà del rischio: è il
|
||||
"free lunch" della diversificazione fra sorgenti di edge scorrelate.
|
||||
- Best Sharpe = equal-weight degli 11 sleeve; best DD = 50/50 fra le due famiglie.
|
||||
|
||||
**Caveat onesti:** la finestra comune è 2021–2026 (5.4 anni), OOS ~2024-10→oggi
|
||||
(1.6 anni) — pochi regimi. CAGR e Sharpe sono backtest a leva 3x; il 2024 cripto
|
||||
favorevole pesa. Il target €50/giorno resta vincolato dal capitale: 43% CAGR su
|
||||
€1000 non fa €50/giorno a breve, serve compounding pluriennale o più capitale.
|
||||
Prossimo passo: confermare il portafoglio combinato nel paper trader live.
|
||||
|
||||
**File:** `scripts/analysis/combine_portfolio.py` (nuovo).
|
||||
|
||||
## Pulizia roster + miglioria ROT02
|
||||
|
||||
- **Waste delle peggiori:** MR03 Keltner (fade più debole, Sharpe 1.22, ridondante
|
||||
con MR01 — rimuoverla *migliora* il portafoglio fade: DD 8.6→8.2, ret +549→+666)
|
||||
e ROT01 (dominata da ROT02). Spostate in `scripts/waste/`.
|
||||
- **Portafogli pronti:** `PORT02_fade_master` (6 sleeve fade) e `PORT03_all_master`
|
||||
(9 sleeve fade+honest, varianti equal/5050).
|
||||
- **ROT02 DD alto → migliorato:** la rotazione concentrava il book su 2 asset
|
||||
(DD 40%). Sweep su `rot_improved`: `top_k=3` dimezza quasi il DD (40%→26%) e
|
||||
*alza* il ritorno full (+1095→+1303%, ret/DD 27→50). Il vol-target abbassa il DD
|
||||
ma sacrifica ritorno (de-leverage) → tenuto top_k=3 senza VT. Caveat onesto:
|
||||
l'OOS di ROT02 cala un po' (+98→+68%, DD 12→14%), ma il MASTER (config deployata)
|
||||
migliora lo Sharpe full 3.95→4.23. Applicato a `ROT02_dual_momentum.py` e
|
||||
`_rot_daily_equity`. Sweep in `honest_improve.rot_improved`.
|
||||
@@ -1,68 +0,0 @@
|
||||
# 2026-05-31 — Studio sugli EXIT delle fade: scalping, TP dinamico, TP-ATR
|
||||
|
||||
> Innescato da una domanda operativa ("un TP è stato raggiunto, non si poteva
|
||||
> scalpare / fare un TP dinamico?"). Studio fee-aware su MR02 (Donchian fade,
|
||||
> segnali invariati `n=20 sl_atr=2.0 max_bars=24`, fee 0.10% RT, leva 3x). Tre
|
||||
> alternative di uscita misurate contro il baseline attuale (**TP = centro del
|
||||
> canale**). Verdetto: **il design attuale è già ottimale; nessuna alternativa lo batte.**
|
||||
|
||||
## 1. "Scalping" = timeframe più veloce (15m vs 1h)
|
||||
A fee 0.10% il 15m rende di più in lordo (~4× più trade), MA è molto più **fragile**:
|
||||
|
||||
| | trade | PnL @0% | @0.10% | @0.20% | DD @0.10% |
|
||||
|---|--:|--:|--:|--:|--:|
|
||||
| BTC 1h | 2041 | +22.768 | +16.645 | +10.522 | 29% |
|
||||
| BTC 15m | 8251 | +65.286 | +40.533 | +15.780 | 29% |
|
||||
| ETH 15m | 9388 | +120.103 | +91.939 | +63.775 | **62%** |
|
||||
|
||||
Da 0% a 0.20% il 15m perde **~76%** del profitto (vs 54% del 1h) e il DD esplode
|
||||
(ETH 15m → 93% a 0.20%). 4× più trade = 4× più fee + slippage (non modellato, ma
|
||||
peggiore su book sottili). **L'1h è scelto per il margine di sicurezza, non per il PnL
|
||||
lordo.** Lo scalping vero (<0.3% target) è in pieno territorio "morte da fee".
|
||||
|
||||
## 2. TP dinamico / trailing ("lascia correre il vincitore")
|
||||
Stessi segnali, exit per trailing a k·ATR dal massimo favorevole invece del TP fisso:
|
||||
|
||||
| policy | BTC win% | ETH win% | equity |
|
||||
|--------|---------:|---------:|--------|
|
||||
| FIXED (centro, attuale) | **48%** | **49%** | 🟢 di gran lunga il migliore |
|
||||
| TRAIL (lascia correre) | 36% | 36% | 🔴 azzerato |
|
||||
| MID+TRAIL | 47% | 47% | 🔴 peggio |
|
||||
|
||||
Il win-rate crolla 48%→36%: i trade che avrebbero incassato il TP fanno andata-e-ritorno
|
||||
e stoppano fuori. **Concettuale:** l'edge della fade è la reversione *fino* alla media;
|
||||
una volta toccata, l'edge è esaurito. Lasciar correre *oltre* = scommettere sulla
|
||||
continuazione, che sui perp crypto NON ha edge (rientra). È la stessa logica per cui
|
||||
SMA/ORB/WR (continuazione) hanno fallito: **let-it-run = trend = il lato perdente.**
|
||||
|
||||
## 3. TP scalato all'ATR (TP = entry + dir·m·ATR, SL fisso 2 ATR → R:R = m/2)
|
||||
| Config | win% | avg %/trade | Sharpe | sumRet% |
|
||||
|--------|-----:|-----------:|-------:|--------:|
|
||||
| **BTC MID (attuale)** | 48% | **0.816** | **3.8** | **1664** |
|
||||
| BTC ATR m=0.5 (RR0.25) | **77%** | −0.081 | −1.0 | −217 |
|
||||
| BTC ATR m=1.0 | 67% | 0.192 | 1.6 | 465 |
|
||||
| BTC ATR m=2.0 | 53% | 0.563 | 3.0 | 1199 |
|
||||
| BTC ATR m=3.0 | 46% | 0.679 | 3.0 | 1331 |
|
||||
| **ETH MID (attuale)** | 49% | **1.738** | **7.5** | **4169** |
|
||||
| ETH ATR m=0.5 | 77% | 0.041 | 0.5 | 134 |
|
||||
| ETH ATR m=3.0 | 46% | 1.082 | 4.7 | 2515 |
|
||||
|
||||
OOS (ultimo 30%) identico: **MID** batte ogni `m` (BTC MID avg 1.14/Sh 3.2; ETH MID avg
|
||||
4.43/Sh 10.9). Due lezioni:
|
||||
- **TP stretto (m=0.5) = trappola dello scalping quantificata:** win-rate **77%** ma edge
|
||||
**zero/negativo** (BTC −0.08%/trade). I rari stop a 2 ATR spazzano via le micro-vincite,
|
||||
la fee mangia il resto. **Win-rate alto ≠ edge.**
|
||||
- **Nessun multiplo ATR fisso batte il centro del canale**, su avg/trade E Sharpe, FULL e OOS,
|
||||
entrambi gli asset.
|
||||
|
||||
## Verdetto unificato
|
||||
Il **TP al centro del canale è ottimale** perché è un target *adattivo alla struttura*: un
|
||||
multiplo fisso di ATR misura solo *quanta* vol c'è, ma ignora *dove* sta la media; il centro
|
||||
adatta al punto reale di reversione **ed è già scalato alla volatilità** (il canale si allarga
|
||||
in regime volatile). Per una mean-reversion il punto giusto dove chiudere è **la media — niente
|
||||
prima, niente dopo.** Tre alternative escluse coi numeri (15m, trailing, TP-ATR) → la scelta
|
||||
di design corrente è blindata.
|
||||
|
||||
> Nota metodologica ricorrente: diffidare del **win-rate alto**. Il segnale vero è
|
||||
> rendimento-medio-per-trade × Sharpe; un TP stretto regala win-rate e nasconde l'assenza
|
||||
> di edge. (Stesso tranello dei guru: backtest cherry-picked ad alta % di vincite.)
|
||||
@@ -1,70 +0,0 @@
|
||||
# 2026-05-31 — Stato trade LIVE PORT06 (paper trading)
|
||||
|
||||
> Snapshot verificato del paper trader a portafoglio (`src.portfolio.runner`, Docker
|
||||
> `pythagoras-portfolio`). Dati da `data/portfolios/PORT06/` + log del container.
|
||||
> Avvio container: 2026-05-29 18:37 UTC. Snapshot: 2026-05-31 13:20 UTC (~43h).
|
||||
|
||||
## Riepilogo capitale
|
||||
| Metrica | Valore |
|
||||
|---------|--------|
|
||||
| Capitale iniziale | €1000.00 (17 sleeve equal-weight, ~€58.82 ciascuno) |
|
||||
| `total_capital` (realizzato, ultimo rebal 00:00) | **€1000.09** (+0.09) |
|
||||
| Equity mark-to-market (live) | **€1000.36** (+0.036%) |
|
||||
| Peggior punto toccato | −€0.01 |
|
||||
| **Max DD** | **0.40%** |
|
||||
| Container | running, healthy, 0 restart |
|
||||
|
||||
## Trade chiusi (storia completa dallo startup: 10 trade, 9W/1L)
|
||||
| # | Sleeve | Uscita | Net % | PnL € | Esito |
|
||||
|---|--------|--------|------:|------:|:---:|
|
||||
| 1 | PR01 ETH/SOL | mean_revert | +0.503 | +0.040 | W |
|
||||
| 2 | PR01 ETH/SOL | mean_revert | +0.683 | +0.060 | W |
|
||||
| 3 | SH01 BTC (ML) | hold_limit | −0.462 | −0.040 | L |
|
||||
| 4 | SH01 BTC (ML) | hold_limit | +0.017 | +0.000 | W |
|
||||
| 5 | PR01 ETH/SOL | mean_revert | +0.488 | +0.040 | W |
|
||||
| 6 | PR01 ETH/SOL | mean_revert | +0.284 | +0.030 | W |
|
||||
| 7 | PR01 LTC/ETH | mean_revert | +0.745 | +0.070 | W |
|
||||
| 8 | PR01 BTC/LTC | mean_revert | +0.434 | +0.040 | W |
|
||||
| 9 | MR02 ETH fade | take_profit | +0.995 | +0.090 | W |
|
||||
| 10 | SH01 ETH (ML) | hold_limit | +0.742 | +0.070 | W |
|
||||
| | **TOTALE** | | | **+0.400** | **90% win** |
|
||||
|
||||
### Aggregato per sleeve (trade chiusi)
|
||||
| Sleeve | n | win | acc% | PnL € |
|
||||
|--------|--:|----:|----:|------:|
|
||||
| PR01 ETH/SOL | 4 | 4 | 100 | +0.170 |
|
||||
| MR02 ETH fade | 1 | 1 | 100 | +0.090 |
|
||||
| PR01 LTC/ETH | 1 | 1 | 100 | +0.070 |
|
||||
| SH01 ETH (ML) | 1 | 1 | 100 | +0.070 |
|
||||
| PR01 BTC/LTC | 1 | 1 | 100 | +0.040 |
|
||||
| SH01 BTC (ML) | 2 | 1 | 50 | −0.040 |
|
||||
|
||||
Motore del PnL finora: **pairs PR01** (market-neutral, mean_revert rapidi 1-6 barre) +
|
||||
una fade **MR02** su take_profit. Unica perdita: SH01 BTC (ML) su hold_limit (fisiologico,
|
||||
edge nell'asimmetria, win-rate ~50%). Sleeve daily (ROT02/TSM01/TR01) e diverse fade non
|
||||
hanno ancora chiuso trade (orizzonte più lungo / pochi segnali in ~2 giorni).
|
||||
|
||||
## Posizioni aperte (3)
|
||||
| Sleeve | Dir | Entry | Capitale |
|
||||
|--------|-----|------:|---------:|
|
||||
| MR02 BTC fade | short | 73969.0 | €58.83 |
|
||||
| MR02 ETH fade | long | 2016.15 | €58.92 |
|
||||
| SH01 BTC (ML) | long | 73811.5 | €58.83 |
|
||||
|
||||
## Verifica (check 2026-05-31)
|
||||
- **0 anomalie** sui 10 CLOSE: `net = gross − fee` rispettato, flag `win` coerente col
|
||||
PnL, fee sempre presente (pairs 0.4% su 2 gambe, fade 0.10% RT).
|
||||
- **Uscite = backtest**: tutti i CLOSE pairs sono `mean_revert` con **|z| ≤ 0.75** al close
|
||||
(0.363/0.605/0.684/0.619/0.656) = esattamente `z_exit=0.75` di PR01; MR02 esce a TP al
|
||||
livello. Il worker live replica la regola del backtest.
|
||||
- **Riconciliazione**: +0.40 realizzato vs +0.09 `total_capital` NON è un errore — è il
|
||||
timing del ribilancio giornaliero (`total_capital` snapshotta a 00:00, le posizioni
|
||||
aperte restano sul notional fino al rebal; CLAUDE.md). L'equity MtM live (+0.36) è il
|
||||
numero corrente, confermato da `equity.jsonl`.
|
||||
|
||||
## Lettura onesta
|
||||
Campione minuscolo (**~2 giorni, 10 trade**) → il PnL (+€0.40 realizzato, +€0.36 MtM) è a
|
||||
livello di **rumore**: non se ne deduce performance. Quello che il check conferma a questo
|
||||
stadio è che il sistema è **sano e fedele**: esecuzione corretta, costi reali inclusi,
|
||||
uscite conformi al backtest, DD trascurabile (0.40%), 0 errori/restart. L'edge si
|
||||
manifesterà solo su orizzonte settimane/mesi. Monitor Docker attivo per down/unhealthy/restart.
|
||||
@@ -1,51 +0,0 @@
|
||||
# 2026-05-31 — Copertura opzioni: idee testate e SCARTATE (record anti-ripetizione)
|
||||
|
||||
> Record delle conclusioni. Il **codice** di queste prove è stato testato e poi
|
||||
> scartato (non conservato nel repo): qui restano i numeri e il *perché*, così da
|
||||
> non ri-testare le stesse idee in futuro. Motore di pricing usato: Black-Scholes
|
||||
> r=0 + IV stimata onestamente = RV × moltiplicatore VRP ≥ 1 (il compratore
|
||||
> SOVRAPPAGA, come in W18-W21), fee Deribit reali (0.03%/gamba + ~0.10% slippage).
|
||||
|
||||
## TL;DR
|
||||
**La copertura opzioni non genera edge nuovo per questo progetto.** I due edge
|
||||
disponibili (trend e mean-reversion) sono già catturati **50-100× più a buon
|
||||
mercato dai perp** (fee 0.10% RT) di quanto facciano le opzioni (premio + VRP +
|
||||
asimmetria coda). Comprare premio perde contro il VRP crypto; venderlo paga le
|
||||
code grasse. Cappare la perdita su una strategia senza expectancy positiva limita
|
||||
solo *quanto* perdi: **non esiste il pasto gratis "leva alta + perdite coperte".**
|
||||
|
||||
## 1. Overlay opzioni su PORT06 — non fattibile
|
||||
Mismatch di orizzonte: l'edge di PORT06 è intraday (hold fade ~9h). Carry ATM 9h
|
||||
≈ **0.96%** del notional vs edge fade per-trade **0.10-0.30%** → costo 3-10× l'edge.
|
||||
La coda di PORT06 è già piccola (DD ~5%) e market-neutral (pairs ~57% del rischio):
|
||||
poco da assicurare. La copertura giusta era già lì (diversificazione + stop), gratis.
|
||||
|
||||
## 2. Strategie nuove a copertura opzioni
|
||||
- **OH01 — direzionale (TSMOM) + opzione protettiva / sola opzione.** Frontiera
|
||||
iso-rischio: il **perp NON coperto domina a ogni livello di rischio** (Sharpe 0.90
|
||||
vs 0.33-0.57; CAGR +33% vs negativo). Comprare protezione su un trend perde per il
|
||||
carry/VRP (il trend-following è "long vol" nel *payoff*, non comprando opzioni).
|
||||
- **OH02 — spread di credito su mean-reversion (vendi premio = VRP a favore).**
|
||||
La copertura funziona (perdita cappata, DD basso, win-rate 73-80%: la reversione è
|
||||
reale). Ma **expectancy ~0/leggermente negativa**: il 27% di trade dove il movimento
|
||||
*continua* (code grasse) costa ~5× ogni vincita. Un trend filter porta solo *singole
|
||||
celle* a +1-2% (overfit: config diversa per asset). Non robusto.
|
||||
|
||||
## 3. V5 — Bull Call Spread / debit spread (stile Casario)
|
||||
È **la migliore struttura long-premium**: rischio definito funziona (worstRoll −13%
|
||||
vs −64% della call secca, DD 54% vs 94%). **Ma net-negativo in crypto** (BTC −2.2%
|
||||
full / −13.5% OOS) e il perp non coperto lo batte. Sweep larghezza: spread più larghi
|
||||
rendono di più → **cappare l'upside toglie le code grasse che pagano il premio**.
|
||||
**Verdetto:** valido **sulle AZIONI** (vol/VRP bassi, uptrend puliti da screener), NON
|
||||
in crypto. Casario ha ragione nel suo dominio (equity), non trasferibile ai perp crypto.
|
||||
|
||||
## 4. V4 — Box strategy (max/min giorno prima, supply/demand) → SKIP
|
||||
Core tradabile = **fadare gli estremi del canale = MR02** (già live). La candela di
|
||||
conferma (doji/hammer/rejection) = pattern di rigetto = rumore (vedi diario TA). Nessun
|
||||
edge nuovo: costruirlo ri-deriverebbe solo MR02.
|
||||
|
||||
## Cosa servirebbe per un vero edge a opzioni (fuori scope attuale)
|
||||
Non direzione né reversione (già coperte dai perp), ma un edge *specifico delle opzioni*:
|
||||
dislocazioni della superficie IV/skew, o gestione attiva (chiusura al 50% del credito,
|
||||
roll). Richiede storico prezzi opzioni reale (qui assente, prezzi sintetici da BS) e un
|
||||
feed greche/IV che il `CerberoClient` oggi non espone.
|
||||
@@ -1,43 +0,0 @@
|
||||
# 2026-05-31 — 3 strategie TA "classiche": testate e SCARTATE (record anti-ripetizione)
|
||||
|
||||
> Record delle conclusioni. Codice testato e poi scartato (non conservato nel repo).
|
||||
> Strategie da contenuti trading-guru: (1) SMA20/200 trend+pullback, (2) Opening Range
|
||||
> Breakout "ironclad", (3) "Weakness rectangle" reversal (ICT). Testate con la
|
||||
> metodologia onesta del progetto: ingresso eseguibile a `close[i]`, SL/TP intrabar,
|
||||
> fee Deribit 0.10% RT, leva 3x, OOS(ultimo 30%), griglia robustezza, sweep fee.
|
||||
|
||||
## TL;DR — tutte e 3 NO EDGE (negative anche a fee ZERO)
|
||||
Tutte e tre **direzionali/continuazione**, tutte negative su BTC/ETH, su tutta la
|
||||
griglia, **anche a fee 0%** → il problema è il *segnale* (avg_R per-trade ≤ 0), non i
|
||||
costi. Riconfermano la lezione centrale: *sui perp crypto i breakout/continuazione
|
||||
rientrano; l'unico edge robusto è la mean-reversion.*
|
||||
|
||||
| Strategia | Tipo | avg_R @ fee0 | Motivo |
|
||||
|-----------|------|--------------|--------|
|
||||
| **SMA01** MA-pullback | continuazione | −0.15 BTC / −0.07 ETH | win ~30% (serve ~40% a R:R 2) |
|
||||
| **ORB01** opening-range breakout | breakout | −0.10…−0.19 | crypto 24/7: manca l'asta d'apertura, ragione d'essere dell'ORB |
|
||||
| **WR01** weakness rectangle | reversal→continuazione | ≈ −0.05/−0.00 | R:R "5:1" illusorio (win cala in proporzione); le weakness vengono travolte |
|
||||
|
||||
> Verificato indipendentemente (reimplementazione minima SMA01): a fee 0 avg_R
|
||||
> −0.15/−0.07. Il −100% di CAGR è solo l'edge negativo composto a leva 3x su migliaia
|
||||
> di trade, non un bug.
|
||||
|
||||
## Tentativo di MIGLIORAMENTO — ribaltarle sul lato fade
|
||||
Miglioramento *di principio* (non tuning): visto che perdono perché sono continuazione,
|
||||
ribaltate sul **fade** (l'unico lato con edge in crypto).
|
||||
|
||||
| versione fade | edge? (avg_R@fee0) | verdetto |
|
||||
|---------------|--------------------|----------|
|
||||
| **SMA02** fade dell'estensione→SMA20 | **+** (0.04…0.36) | = **MR01 inferiore** (FULL 1h negativo, Sharpe 0.4-0.9 vs 2.7+) |
|
||||
| **ORB02** fade del breakout del range | **+** (win 35%→50-66%) | = **MR02/MR07** senza controlli di rischio (DD 90-100%) |
|
||||
| **WR02** weakness come reversione | **≈0** | **rumore**, non una fade-family nascosta |
|
||||
|
||||
- Il flip restituisce segno positivo a 2/3 (riconferma *fade > continuazione*) **ma nulla
|
||||
di additivo**: SMA02/ORB02 sono ri-scoperte inferiori di strategie già live; WR02 è rumore.
|
||||
- **Ipotesi "SMA200 piatta = meglio fadare" SMENTITA**: il regime *range* non batte il fade
|
||||
semplice; semmai il regime *trend* dà avg_R migliore ma con time-in-market 0.5-9%.
|
||||
|
||||
## Lezione metodologica
|
||||
La prova del nove è l'**avg_R a fee 0**: se una strategia perde anche senza costi, il
|
||||
problema è il segnale e nessun tuning la salva. Le strategie che funzionano restano
|
||||
MR01/MR02/MR07 (fade) + PR01 (pairs) + PORT06 — l'edge è mean-reversion + diversificazione.
|
||||
@@ -1,81 +0,0 @@
|
||||
# 2026-06-01 — Bugfix: SH01 usciva a 3 barre invece di H=12 (exit a orizzonte)
|
||||
|
||||
> Diagnosi partita da un check sulla debolezza apparente di **SH01_BTC** nel paper
|
||||
> trading live PORT06 (accuratezza 33,3% su 3 trade). Non era sfortuna statistica:
|
||||
> era un bug di exit nello `StrategyWorker`.
|
||||
|
||||
## Sintomo
|
||||
|
||||
Nel live PORT06 (Docker `pythagoras-portfolio`), SH01_BTC mostrava 3 trade tutti
|
||||
`long`, **tutti chiusi con `reason: "hold_limit"` a `bars_held: 3`**, con `tp: null
|
||||
sl: null`:
|
||||
|
||||
| # | entry | exit | bars | net % | esito |
|
||||
|---|-------|------|------|------:|:---:|
|
||||
| 1 | 73529.5 | 73433.0 | 3 | −0,46% | ❌ |
|
||||
| 2 | 73759.5 | 73839.5 | 3 | +0,02% | ✅ |
|
||||
| 3 | 73811.5 | 73766.0 | 3 | −0,32% | ❌ |
|
||||
|
||||
`oos_signal_precision` nei log di TRAIN scendeva 55,6% → 50,0% → 43,3%.
|
||||
|
||||
## Causa
|
||||
|
||||
SH01 (`scripts/strategies/SH01_shape_ml.py`, config **W24 H12 th0.58**) è una
|
||||
strategia **horizon-only**: predice il segno del rendimento a **H=12 barre** ed esce a
|
||||
H barre. I suoi Signal portano `metadata={"max_bars": H}` (=12) e **nessun TP/SL**.
|
||||
|
||||
Nello `StrategyWorker.tick()` la logica di uscita era:
|
||||
|
||||
```python
|
||||
if self.tp and self.sl: # SH01: False (tp=sl=0)
|
||||
... usa self.max_bars ... # -> max_bars=12 consultato SOLO qui
|
||||
elif self.bars_held >= self.hold_bars: # fallback legacy hold_bars=3
|
||||
self._close_position(..., "hold_limit") # SH01 finiva QUI
|
||||
```
|
||||
|
||||
`self.max_bars` (=12, settato correttamente in `_open_position`) era onorato **solo
|
||||
dentro il ramo `tp and sl`**. Senza TP/SL, SH01 cadeva sul fallback `hold_bars=3` e
|
||||
chiudeva a 3 barre. L'edge di SH01 — per CLAUDE.md è nell'**asimmetria sull'orizzonte
|
||||
H, non nella frequenza** (win-rate ~50%) — non aveva tempo di realizzarsi: tagliato a
|
||||
3/12, degenera in rumore.
|
||||
|
||||
Solo SH01 (BTC+ETH) era colpito: tutte le fade (MR01/MR02/MR07, DIP01) portano
|
||||
tp+sl+max_bars e usano il ramo intrabar corretto.
|
||||
|
||||
## Fix
|
||||
|
||||
`src/live/strategy_worker.py`: aggiunto un ramo per l'exit a orizzonte puro, prima del
|
||||
fallback `hold_bars`:
|
||||
|
||||
```python
|
||||
elif self.max_bars:
|
||||
# Exit puro a orizzonte (strategie senza TP/SL, es. SH01 shape-ML H=12):
|
||||
# onora max_bars dalla metadata del Signal, non il fallback hold_bars=3.
|
||||
if self.bars_held >= self.max_bars:
|
||||
self._close_position(current_price, "time_limit")
|
||||
```
|
||||
|
||||
Le fade restano invariate (entrano nel ramo `tp and sl`).
|
||||
|
||||
## Verifica
|
||||
|
||||
- Nuovo test `tests/portfolio/test_horizon_exit.py` (2 casi): con `max_bars=12` resta
|
||||
in posizione a 3 barre; esce a 12 con `reason: "time_limit"` e `bars_held: 12`.
|
||||
- Suite completa: **43 passed**.
|
||||
- Container riavviato: **tutti i 17 sleeve RESUME puliti**, inclusa una posizione
|
||||
SH01_ETH short aperta che ora seguirà l'exit a 12 barre.
|
||||
|
||||
## Atteso d'ora in poi
|
||||
|
||||
I trade SH01 nei log mostreranno `reason: "time_limit"` con `bars_held: 12` invece di
|
||||
`hold_limit / 3`. Il 33% di accuratezza era un artefatto dell'exit prematuro; ora la
|
||||
strategia gira sull'orizzonte su cui è validata (BTC OOS Sharpe 2,72, expanding).
|
||||
Resta comunque un **diversificatore** del MASTER, non un motore di ritorno standalone.
|
||||
|
||||
## Lezione
|
||||
|
||||
Il backtest di SH01 (`fade_base`/engine onesto) esce a H barre via `max_bars`; il
|
||||
worker live deve replicarlo. Quando una strategia non porta TP/SL ma solo un
|
||||
orizzonte, il fallback `hold_bars` del worker la **falsa silenziosamente**. Verificare
|
||||
sempre che la convenzione di exit del worker live coincida con quella del backtest
|
||||
validato — non solo l'ingresso.
|
||||
@@ -1,71 +0,0 @@
|
||||
# 2026-06-01 — SH01 live eseguiva la strategia SBAGLIATA (squeeze scartato), non shape-ML
|
||||
|
||||
> Scoperto verificando perché SH01 continuava a chiudere a `hold_limit/3` **anche dopo**
|
||||
> il rebuild col fix horizon-exit. Il fix era corretto ma in un **ramo morto**: SH01 live
|
||||
> non passava da `StrategyWorker.tick()`.
|
||||
|
||||
## Sintomo
|
||||
|
||||
Dopo il deploy del fix SH01 (exit a H=12), un close SH01_BTC delle 12:00 era ancora
|
||||
`reason=hold_limit bars=3` (perdita −1,27%). Il fix non aveva effetto sul path reale.
|
||||
|
||||
## Causa (bug di wiring, più grave del previsto)
|
||||
|
||||
`src/portfolio/runner.py` importava `MLWorkerWrapper` da **`src/live/multi_runner.py`** e
|
||||
ci avvolgeva lo sleeve SH01:
|
||||
|
||||
```python
|
||||
if spec.kind == "ml":
|
||||
return MLWorkerWrapper(worker, {"retrain_hours": 24})
|
||||
```
|
||||
|
||||
Ma quel wrapper è **legacy, per la famiglia squeeze ML01** (scartata, vedi CLAUDE.md):
|
||||
- usa `SignalEngine` = squeeze-detection + GradientBoosting (NON SH01_shape_ml);
|
||||
- ha una `tick()` propria che apre con un `Signal` **nudo** (niente tp/sl/max_bars) ed
|
||||
esce con `if bars_held >= hold_bars: close("hold_limit")` → ignora del tutto la
|
||||
strategia caricata e il fix horizon.
|
||||
|
||||
Quindi lo sleeve "SH01" del portafoglio live **non eseguiva shape-ML**: eseguiva il
|
||||
motore squeeze scartato. I log `TRAIN OK / oos_signal_precision` venivano da lì. Il
|
||||
`worker` con strategy=SH01_shape_ml era costruito ma la sua `generate_signals` non
|
||||
veniva **mai** chiamata.
|
||||
|
||||
## Fix
|
||||
|
||||
SH01 (`kind="ml"`) ora gira come **StrategyWorker normale**: `SH01_shape_ml.generate_signals`
|
||||
fa il walk-forward (retraining) **internamente** ad ogni tick (`ml_wf_entries`) ed emette
|
||||
`metadata.max_bars=H=12` → gli exit passano per `StrategyWorker.tick()` e il fix horizon
|
||||
si applica davvero.
|
||||
|
||||
```python
|
||||
# runner.py: niente più MLWorkerWrapper per kind="ml"
|
||||
return StrategyWorker(strategy=strategy, asset=spec.asset, tf=spec.tf, ...)
|
||||
```
|
||||
|
||||
**Lookback dati.** `ml_wf_entries` ha `train_min=4000` → servono ≥4000 barre 1h prima di
|
||||
produrre segnali (con 90g/2160 barre → 0 segnali, runtime 0.01s — il falso "muto"). Le
|
||||
candele 1h di BTC/ETH già arrivano a 440g (le richiede TSM01/ROT02 a 1d), ma per non
|
||||
dipendere da quella coincidenza ho aggiunto `_ML_LOOKBACK_DAYS=365`: gli asset usati da
|
||||
sleeve ml fetchano ≥365g (~8760 barre). Costo `generate_signals` su 365g: **0,17–0,24s**
|
||||
(modello logit) → trascurabile sul poll 60s.
|
||||
|
||||
**Verifica.** Build SH01 → `StrategyWorker` con `strategy.name=="SH01_shape_ml"`, niente
|
||||
attributo `engine` (regression test `test_build_ml_sh01_is_plain_strategyworker`). Smoke
|
||||
su 365g: 766–1786 segnali, tutti `max_bars=12`; tick live 0,17s. `ml_wf_entries` non
|
||||
predice mai l'ultima barra (`n-1`) ma fino a `n-2` = esattamente la condizione di apertura
|
||||
del worker (`idx >= last_idx-1`) → apre quando il segnale è fresco. Suite: 51 passed.
|
||||
|
||||
**Stato live.** SH01 BTC/ETH erano flat: contatori resettati a 0 (capitale preservato
|
||||
58,76/58,78), vecchi trade squeeze archiviati in `trades_squeeze_archive.jsonl`. Rebuild
|
||||
+ recreate: 14 worker RESUME puliti, container healthy, nessun log TRAIN/squeeze, zero
|
||||
errori.
|
||||
|
||||
## Lezione
|
||||
|
||||
1. **Verificare il path REALE, non solo il codice del fix.** Il fix horizon era giusto ma
|
||||
SH01 non lo attraversava. Un fix non testato end-to-end sul percorso vivo è un fix
|
||||
presunto. (Mi ero fidato del rebuild senza confermare il reason dei close SH01.)
|
||||
2. Riusare un wrapper legacy "perché c'è" è un rischio: `MLWorkerWrapper` di multi_runner
|
||||
era per la famiglia squeeze scartata, non per shape-ML.
|
||||
3. Un modello ML "muto" può essere solo **fame di dati** (train_min), non un bug logico:
|
||||
controllare sempre la dimensione della finestra prima di concludere.
|
||||
@@ -1,89 +0,0 @@
|
||||
# 2026-06-01 — "Win" che perdono: metrica netto-fee + filtro TP edge-minimo
|
||||
|
||||
> Partito da un'osservazione dell'utente sui trade live PORT06: **ci sono close con
|
||||
> `win=True` ma `pnl` negativo**. Due problemi distinti, entrambi risolti.
|
||||
|
||||
## Problema 1 — la metrica `win` mentiva (lordo invece di netto)
|
||||
|
||||
In `strategy_worker.py::_close_position`:
|
||||
|
||||
```python
|
||||
trade_return = price_change * direction # LORDO, prima delle fee
|
||||
net = trade_return * leverage - fee_rt * leverage
|
||||
pnl = capital * position_size * net # corretto (netto)
|
||||
is_win = trade_return > 0 # BUG: usa il LORDO
|
||||
```
|
||||
|
||||
`is_win` scattava appena il prezzo si muoveva di un soffio a favore, **prima delle
|
||||
fee**. Capitale e PnL erano giusti (netti); solo la metrica `win`/`accuracy` era
|
||||
gonfiata.
|
||||
|
||||
**Quantificazione (51 close live):** 39 win dichiarate (76,5%) → **13 falsi win**
|
||||
(`win=True` ma `pnl≤0`) → accuratezza **netta reale 52,9%**. PnL realizzato +€0,77
|
||||
(resta positivo: lo trascinano i pairs).
|
||||
|
||||
**Fix:** `is_win = net > 0`. + `tests/portfolio/test_win_net_of_fees.py` (mossa
|
||||
sotto-fee = non win; oltre-fee = win; perdita = non win).
|
||||
|
||||
**Riconciliazione contatori persistiti:** i `total_wins` su disco erano gonfiati dal
|
||||
vecchio conteggio lordo. Ricalcolati come `net_return>0` dai `trades.jsonl`:
|
||||
**MR01_BTC 7→1, DIP01_BTC 7→1** (gli unici toccati; tutti gli altri già coerenti).
|
||||
Capitale invariato.
|
||||
|
||||
## Problema 2 — i 13 falsi win erano tutti MR01_BTC / DIP01_BTC in take_profit
|
||||
|
||||
Causa: in `MR01_bollinger_fade` e `DIP01_dip_buy` il **TP è la media** (`tp = ma[i]`)
|
||||
e l'entry è a `close[i]` appena fuori banda. Nel regime BTC **piatto** (inchiodato
|
||||
~73.700 per ore, vol bassissima) la media è a pochi dollari dall'entry → il TP cade
|
||||
**dentro** il costo round-trip (0,10%): colpire il TP = perdita netta garantita.
|
||||
|
||||
**Meccanismo del fix (importante).** "Spostare il TP più in là" NON garantisce di non
|
||||
perdere: il prezzo rientra solo fino alla media, non oltre → si finirebbe su SL/time-
|
||||
limit, perdendo di più. La mossa provabilmente non-perdente è un **filtro di edge
|
||||
minimo**: se `|tp − entry|/entry ≤ min_tp_frac` non si apre la trade. Break-even
|
||||
esatto = `fee_rt` (= 0,10%, indipendente dalla leva, perché
|
||||
`ret = mossa·lev − fee_rt·lev > 0 ⇔ mossa > fee_rt`).
|
||||
|
||||
**Implementazione:** parametro `min_tp_frac` (default 0.0 = off) in **tutte le 4 fade**
|
||||
(MR01 banda, MR02 midpoint canale, MR07 ATR-scaled) e DIP01; salta i segnali sotto
|
||||
soglia. Cablato negli sleeve live a **0.0015 (1,5× fee)** in `_defs.py` (`MIN_TP_FRAC`).
|
||||
|
||||
**Validazione backtest (BTC+ETH 1h, config sleeve, min_tp_frac ∈ {0,.001,.0015,.002}):**
|
||||
neutro su tutte e 4 le fade.
|
||||
- MR01: 0 trade rimossi (BTC +8028€, ETH +10395€) — metriche identiche.
|
||||
- DIP01 BTC: −1 trade a 0.002, **migliora** (+7492→+7522€, DD 26,3→25,9%).
|
||||
- MR02 BTC: −1 trade a 0.0015 (pnl invariato +12198€), ETH 0 rimossi.
|
||||
- MR07 BTC/ETH: 0 rimossi (TP ATR-scaled sempre ben oltre le fee nello storico).
|
||||
|
||||
Conclusione: i micro-scalp sotto-fee **non esistono nel campione storico** — sono un
|
||||
artefatto del regime attuale. Il filtro è **puro upside**: neutro sul backtest validato,
|
||||
protettivo dal vivo. (Le 12 trade live incriminate, tutte MR01/DIP01 BTC, avevano gap
|
||||
~0,026%, ben sotto 0,15% → tutte bloccate.)
|
||||
|
||||
+ `tests/portfolio/test_min_tp_frac.py` (monotonia + ogni superstite ha gap > soglia
|
||||
+ default-off invariato).
|
||||
|
||||
## Nota deploy — il codice è COTTO nell'immagine, non montato
|
||||
|
||||
Scoperta durante il deploy: `docker-compose.yml` monta solo `./data` e
|
||||
`./portfolios.yml`; il sorgente (`src/`, `scripts/`) è `COPY` nel Dockerfile. Quindi
|
||||
**`docker compose restart` NON ricarica le modifiche al codice** — serve
|
||||
`docker compose up -d --build`. Conseguenza retroattiva: anche il fix SH01
|
||||
horizon-exit di stamattina è andato live solo con questo rebuild. Da ricordare per ogni
|
||||
futura modifica ai worker. Il volume `./data` persiste → i 14 worker fanno RESUME
|
||||
puliti dopo il rebuild (capitale e posizioni intatti).
|
||||
|
||||
## Stato finale
|
||||
|
||||
- `is_win = net > 0` live; contatori riconciliati (MR01/DIP01 BTC 1/9).
|
||||
- Filtro `min_tp_frac=0.0015` live su tutti i fade + DIP01 (attivo solo MR01/DIP01).
|
||||
- Fix SH01 horizon-exit ora **effettivamente** live (rebuild).
|
||||
- Suite: 49 passed. Container ricostruito, healthy, 14 sleeve in RESUME.
|
||||
|
||||
## Lezione
|
||||
|
||||
1. Una metrica di "win" deve essere **netto fee**, altrimenti l'accuracy è teatro.
|
||||
2. Quando il TP è dentro il costo di transazione, la trade è persa in partenza: meglio
|
||||
**non prenderla** che ritoccare il TP.
|
||||
3. Per i worker live in Docker: **rebuild**, non restart. Il restart ricarica solo lo
|
||||
stato dal volume, non il codice.
|
||||
@@ -1,67 +0,0 @@
|
||||
# 2026-06-02 — Loss-guard per le fade: filtro Hurst (regime persistente)
|
||||
|
||||
> Goal: limitare le perdite delle fade in "bassa vol". Diagnosi empirica + ricerca web + workflow
|
||||
> 11 agenti + test decisivo a livello PORT06. Branch `feat/fade-lossguard`.
|
||||
|
||||
## Riformulazione del problema (la premessa era imprecisa)
|
||||
|
||||
Diagnosi su 3022 trade fade (MR01/MR02/MR07 × BTC/ETH, 2021+): **le perdite NON si concentrano in
|
||||
bassa vol** — anzi il terzile low-DVOL è net positivo (+2,30%/trade). Il vero driver è il **regime
|
||||
PERSISTENTE/trending**, misurato dall'Hurst:
|
||||
- somma perdite peggiore: **hurst>0,55** (−2695% in low-vol, dominante in ogni terzile vol)
|
||||
- **stop-rate 43% per hurst>0,55 vs 21% per hurst<0,45** (anti-persistente) — 2x
|
||||
- peggiori 1% trade: Hurst medio 0,61 (77% con hurst>0,55, solo 13% in bassa-DVOL)
|
||||
|
||||
## Ricerca web (confermata e smentita dai dati reali)
|
||||
- **Hurst regime filter** (MR solo H<0,45, evitare H>0,55): **CONFERMATO** sui dati reali. ✅
|
||||
- **ADX** (PF 1,62 sotto 20 vs −0,74 sopra 30): **NON si replica** — ADX-skip uccide l'edge
|
||||
(Sharpe 4,82→0,99) e lo stop-rate non scende. ❌
|
||||
- **vol-expansion ATR-ratio>1,5 (−72% perdite)**: **NON si replica** — alza DD e stop-rate. ❌
|
||||
- **time-stop ~15 barre**: riduce stop-rate ma alza il DD full → non passa standalone. ❌
|
||||
|
||||
## Workflow 11 agenti — meccanismi testati
|
||||
| Meccanismo | OOS Sharpe (base→filt) | DD full | Buon loss-guard? |
|
||||
|---|---|---|---|
|
||||
| **Hurst-SKIP h<0,55** | 4,82→4,96 ↑ | 24,3→13,8% ↓ | **SÌ** |
|
||||
| **Hurst-SIZE 1/0,5/0,25** | 4,65→5,32 ↑ (full) | 33,6→11,3% maxDD ↓ | **SÌ** |
|
||||
| ADX-skip | 4,82→0,99 ✗ | — | NO (uccide edge) |
|
||||
| vol-expansion vratio | 4,82→4,04 | 24,3→27,5% ✗ | NO |
|
||||
| Kaufman ER, time-stop, vol-target, DVOL-rising, combo | tutti ↓ o DD↑ | — | NO |
|
||||
|
||||
**Solo l'Hurst** isola chirurgicamente il regime tossico; gli altri sono "dimmer uniformi" che
|
||||
tagliano winner insieme ai loser (gate FR01 fallito).
|
||||
|
||||
## TEST DECISIVO a livello PORT06 — SUPERATO ✅
|
||||
|
||||
Applicato l'Hurst-skip alle 6 fade dentro il PORT06 intero (equal-weight, le altre 11 sleeve
|
||||
invariate):
|
||||
|
||||
| Portafoglio | FULL Sharpe | FULL DD | OOS Sharpe | OOS DD | OOS ret |
|
||||
|-------------|:--:|:--:|:--:|:--:|:--:|
|
||||
| PORT06 baseline | 6,62 | 4,10% | 8,89 | 1,22% | +175% |
|
||||
| **+ Hurst-skip h<0,55** | **6,76** | **2,39%** | **9,15** | 1,54% | +158% |
|
||||
| + Hurst-skip h<0,50 | 6,61 | 2,08% | 9,02 | 1,54% | +150% |
|
||||
|
||||
**A differenza di FR01 (che diluiva), il filtro Hurst MIGLIORA il PORT06**: FULL Sharpe ↑, **FULL
|
||||
DD quasi dimezzato (4,10→2,39%)**, OOS Sharpe ↑ (8,89→9,15). Costo: OOS DD +0,3pp (resta minuscolo),
|
||||
OOS ret −17pp. **h<0,55 è il pick** (0,50 taglia più ritorno). Non aumenta il profitto: è puro
|
||||
**rischio** — dimezza il DD mantenendo/alzando lo Sharpe.
|
||||
|
||||
## Implementazione
|
||||
Aggiunto `hurst_skip_mask` in `src/strategies/fade_base.py` (rolling-Hurst causale dalle SOLE close)
|
||||
+ parametro `hurst_max` (default None=off) in MR01/MR02/MR07. Test: `test_hurst_lossguard.py`.
|
||||
|
||||
**Vantaggio operativo decisivo vs FR01:** l'Hurst si calcola **dalle sole close** → nessun feed
|
||||
DVOL/regime live necessario. Lo `StrategyWorker` lo computa inline dai dati che già ha → **deployabile
|
||||
senza nuova infrastruttura**, basta settare `hurst_max: 0.55` nei params degli sleeve fade.
|
||||
|
||||
## Da fare per attivarlo live (deploy)
|
||||
1. Settare `hurst_max: 0.55` nei params delle fade in `_defs.py` (sleeve live) + aggiornare i params
|
||||
fade del backtest (`combine_portfolio`/`report_families`) per PARITÀ + rigenerare il
|
||||
regression-lock PORT06 (i numeri canonici cambiano: DD 4,9→~2,4%).
|
||||
2. Verificare che il rolling-Hurst live nel worker coincida col backtest (stessa finestra 100,
|
||||
stesso stepping causale).
|
||||
3. Rebuild immagine Docker (`up -d --build`, non restart) + verifica RESUME.
|
||||
|
||||
Default attuale: `hurst_max` OFF → zero impatto su backtest/parità/live finché non lo si attiva
|
||||
esplicitamente. Il SISTEMA è trovato e validato; l'attivazione è una decisione di deploy.
|
||||
@@ -1,89 +0,0 @@
|
||||
# 2026-06-02 — Ricerca a 100 agenti: Frattali del segnale × Regime ARGO
|
||||
|
||||
> Workflow multi-agente (171 agenti, 8,4M token, ~7h) per cercare una strategia che combini
|
||||
> un SEGNALE FRATTALE con un GATE/INTERAZIONE DI REGIME ARGO (DVOL/funding/VRP), validata OOS.
|
||||
> Branch: `feat/fractal-argo-search`. Substrato e codice sul branch, niente impatto su main/live.
|
||||
|
||||
## Substrato costruito
|
||||
- `regime_fetcher.py`: DVOL (2021-03→oggi) + funding (2019→oggi) BTC/ETH da **Deribit mainnet
|
||||
public** (no-auth, OI/IV reali — non il testnet farlocco di Cerbero).
|
||||
- `regime_lab.py`: allineamento regime↔prezzo **causale no-look-ahead** (merge_asof backward),
|
||||
feature regime (dvol_pct, **vrp=dvol−rv**, funding_z, dvol_chg) + frattali (rolling Hurst,
|
||||
Higuchi FD, vol-ratio, Williams pivot), cache feature precalcolate, validazione netto-fee OOS
|
||||
via `explore_lab`. Bug corretto in corsa: `vrp` annualizzava la realized-vol sempre come 1h →
|
||||
rotta su 4h/1d (sempre negativa); fix per timeframe.
|
||||
- `fractal_argo_workflow.js`: 84 agenti griglia (7 famiglie frattali × 6 angoli regime × BTC/ETH)
|
||||
+ 8 wildcard + verifica avversariale dei survivor + sintesi.
|
||||
|
||||
## Verdetto
|
||||
|
||||
**Esistono edge frattale×regime reali, causali, robusti** (15 confermati dalla batteria
|
||||
avversariale: audit look-ahead bit-esatto, cross-asset, split alternativo, fee 0.2% RT, plateau).
|
||||
**MA nessuno batte PORT06 standalone** (OOS Sharpe 8,19 / DD 2,3%): sono **diversificatori a
|
||||
bassa esposizione** (1,5-8%, ~100-460 trade), profilo SH01/pairs.
|
||||
|
||||
### Top candidati confermati
|
||||
| Strategia | Asset/TF | OOS Sharpe | OOS DD | trade |
|
||||
|-----------|----------|:--:|:--:|:--:|
|
||||
| FRAC-VRP multiscala (chop × VRP<0) | ETH 1h | 5,55 | 11% | 184 |
|
||||
| HigVRP-Fade (Higuchi alto × VRP<0) | BTC 1h | 4,55 | 7,2% | 286 |
|
||||
| **HurstCalmFade (hurst<0,55 × dvol<0,4)** | BTC 1h | **3,73** | 5,1% | 198 |
|
||||
| WILD8 Pivot-Hurst | BTC 4h | 3,87 | 10% | 482 |
|
||||
| AnalogFundingFade (kNN forma × funding) | ETH 4h | 2,15 | 9,3% | 229 |
|
||||
|
||||
## Il finding chiave (controintuitivo): il prior ARGO è SMENTITO
|
||||
|
||||
La tesi naïve **"VRP>0 = GEX+ = range = fade" FALLISCE** sistematicamente. L'edge robusto e
|
||||
ripetuto è su **VRP<0** (vol implicita *sottoprezzata* vs realizzata → mean-reversion whippy) e su
|
||||
**DVOL bassa**, l'opposto del brief. Gate invertito VRP>0 → Sharpe −2,08/−1,30 su entrambi gli
|
||||
asset. È il risultato più solido di tutta la ricerca, look-ahead-clean (lag-1/3/6 robusto).
|
||||
|
||||
## Cosa aggiunge valore vs cosa è decorativo
|
||||
- **Load-bearing (confermato per ablazione):** VRP<0; hurst-low × dvol-low (HurstCalmFade taglia
|
||||
DD OOS 17%→5%); funding_z estremo |fz|≥1,8 (analog ETH 4h).
|
||||
- **Decorativo (DD-reducer, non interazione):** dvol_chg, dvol_high/low e funding come gate spesso
|
||||
riducono solo esposizione senza migliorare il segno.
|
||||
|
||||
## Cosa è RUMORE (conferma i priori del progetto)
|
||||
- Frattali da soli (angolo=none): hurst/Higuchi/vratio/chop/candle/analog intraday → non robusti
|
||||
(DD 30-90%, muoiono di fee). Conferma `shape_lab`.
|
||||
- Momentum/breakout gateato (hurst>0,6, dvol-rising): catastrofico (Sharpe −2…−7) → riconferma
|
||||
dominanza mean-reversion, i breakout rientrano.
|
||||
- ARGO-GEX nella direzione attesa (VRP>0): perde. Coerente con W18/19/21 scartate.
|
||||
- Pivot-fade non-laggato (frac_up[i]): artefatto squeeze-like, va sempre laggato a i−2.
|
||||
|
||||
## Vincitore selezionato + test decisivo
|
||||
|
||||
**FR01 HurstCalmFade BTC 1h** (`scripts/strategies/FR01_hurst_calm_fade.py`): il più verificato,
|
||||
DD più basso (5,1% OOS), generalizza a ETH. **Test di correlazione decisivo** (la domanda che
|
||||
conta: aggiungerlo migliora il PORT06 o è ridondante?): correlazione daily-returns coi fade
|
||||
esistenti **MR01 +0,17 / MR02 +0,08 / MR07 −0,03** → **BASSA, quasi-ortogonale**, NON ridondante.
|
||||
Passa il gate → vale l'inserimento come diversificatore.
|
||||
|
||||
## Onestà finale
|
||||
L'edge frattale×regime è **reale, causale, robusto** ma è sempre **mean-reversion già nota
|
||||
condizionata dal regime (VRP<0 / hurst-low / dvol-low)**, non un motore ortogonale nuovo. Valore =
|
||||
**riduzione DD aggregato come sleeve a bassa esposizione**. La correlazione bassa lo qualifica come
|
||||
diversificatore reale.
|
||||
|
||||
## TEST DECISIVO SUL MASTER — VERDETTO FINALE: NON deployare
|
||||
|
||||
Misurato il contributo marginale di FR01 al PORT06 intero (equal-weight, `master_corr`):
|
||||
|
||||
| Portafoglio | FULL Sharpe | OOS Sharpe | OOS DD | OOS ret |
|
||||
|-------------|:--:|:--:|:--:|:--:|
|
||||
| PORT06 (17 sleeve) | 6,62 | **8,89** | 1,2% | +175% |
|
||||
| PORT06 + FR01 (19) | 6,55 | **8,72** | 1,1% | +156% |
|
||||
|
||||
**FR01 NON migliora il PORT06: lo DILUISCE** (OOS Sharpe 8,89→8,72, OOS ret +175%→+156%; DD
|
||||
marginalmente meglio 1,2→1,1% ma a costo di Sharpe). Corr FR01 vs MASTER +0,18 (BTC)/+0,23 (ETH).
|
||||
|
||||
**Causa + nota di onestà metrica:** lo Sharpe "3,73" dei report del workflow è **per-trade/annuale**
|
||||
(`explore_lab`); quello rilevante per il portafoglio è lo **Sharpe daily-return** (`combine`), che per
|
||||
FR01 è solo **~1,85/1,53** — troppo basso per muovere un PORT06 a 8,89. È "ridondanza robusta":
|
||||
mean-reversion regime-gated che si sovrappone a ciò che il MASTER già fa.
|
||||
|
||||
**ESITO: il search a 100 agenti ha trovato strategie robuste e causali, ma NESSUNA migliora il
|
||||
PORT06.** Non deployare FR01 né i candidati gemelli. Valore del progetto resta nell'estendere
|
||||
fade/pairs validati. Tutto resta come RECORD DI RICERCA sul branch (non si merge in produzione).
|
||||
Wiring DVOL live e walk-forward: non necessari, deploy abbandonato.
|
||||
@@ -1,176 +0,0 @@
|
||||
# 2026-06-04 — EXIT LAB: ricerca massiva exit dinamiche (34 agenti) → EXIT-16 close-confirm SL PROMOSSO
|
||||
|
||||
## Obiettivo
|
||||
|
||||
Cercare exit migliori per le fade attive: TP dinamici, SL dinamici/protettivi,
|
||||
meccanismi per "cavalcare il prezzo". Mandato: ≥20 agenti con specifiche
|
||||
differenti, guardia anti-overfitting, test su tutto lo storico disponibile.
|
||||
|
||||
**Esito in una riga: "cavalcare" non esiste (17ª conferma), ma la ricerca ha
|
||||
trovato una cosa più grossa — LO STOP-LOSS INTRABAR FISSO È IL COMPONENTE CHE
|
||||
DISTRUGGE PIÙ VALORE NELLE FADE, e la forma robusta del fix (SL confermato in
|
||||
chiusura, EXIT-16) è PROMOSSA a livello PORT06: OOS Sharpe 8.82→10.06,
|
||||
FULL DD 4.10→2.60.**
|
||||
|
||||
## Infrastruttura (riusabile)
|
||||
|
||||
- `scripts/analysis/exit_lab.py` — harness CONDIVISO: cache segnali live-params
|
||||
delle 3 fade (`data/cache/exit_lab_signals.pkl`, 73.6k barre 1h 2018→2026-05,
|
||||
BTC+ETH), engine intrabar identico a `fade_base` (parità verificata al punto
|
||||
percentuale su tutti e 6 gli sleeve), contratto anti-look-ahead esplicito
|
||||
(`levels(j)` solo dati ≤ j-1; `after_bar(j)` sul close = eseguibile al poll),
|
||||
protocollo train/OOS (selezione parametri SOLO su pre-2023-11; OOS letto una
|
||||
volta), fill parziali, `ExitPolicy` pluggable.
|
||||
- `scripts/analysis/exit_policies/` — 23 policy + 10 script di verifica.
|
||||
- `scripts/analysis/exit16_port06_impact.py` — replay canonico `build_trades`/
|
||||
`fade_daily_equity` con parità ESATTA (corr 1.00000) + innesto EXIT-16 +
|
||||
ricalcolo PORT06 (cap pairs 0.33, leva 2x).
|
||||
|
||||
## Fase 1 — Explore: 23 agenti, una famiglia ciascuno
|
||||
|
||||
Tally: **3 PROMISING, 5 NEUTRAL, 15 REJECT.**
|
||||
|
||||
REJECT (la famiglia "cavalca il prezzo" è stata falcidiata): trail_atr_ride,
|
||||
trail_pct, breakeven, sar_trail, tp_decay, tp_extend_momentum, tp_moving_mean,
|
||||
partial_tp_trail, hurst_exit, giveback, loser_timestop, donchian_trail,
|
||||
ema_cross_exit, vol_rescale, sl_tp_ride. Autopsia ricorrente: **il TP delle
|
||||
fade sta ALLA MEDIA; lì il movimento è esaurito per costruzione → oltre quel
|
||||
punto non c'è coda da cavalcare** (il runner finiva oltre il TP ~3% delle
|
||||
volte). Caso da manuale `trail_atr_ride`: train 5/6 a favore, **OOS 0/6**
|
||||
(MR01 ETH ret 134%→1%) — senza l'embargo train/OOS l'avremmo promosso.
|
||||
|
||||
NEUTRAL: ratchet, sl_tighten, z_overshoot, wide_sl_trail, swing_stop
|
||||
(miglioramenti misti, mai 5/6).
|
||||
|
||||
PROMISING — tre meccanismi diversi, UNA stessa tesi ("gli stop intrabar da
|
||||
wick sono falsi negativi: l'overshoot che buca lo stop è esattamente ciò che
|
||||
la fade vuole fadare, e rientra"):
|
||||
- **EXIT-02 trail_atr_keep_tp** (chandelier k=1.5 + TP fisso): 6/6 train, 5/6 OOS.
|
||||
- **EXIT-16 close_confirm_sl** (SL solo se la barra CHIUDE oltre sl0±0.5·ATR):
|
||||
**6/6 train E 6/6 OOS**, plateau.
|
||||
- **EXIT-22 no_sl** (diagnostica: SL rimosso): 6/6+6/6, plateau monotono
|
||||
perfetto `SL stretto < base < SL 2x < niente SL`.
|
||||
|
||||
## Fase 2 — Verify: 10 avversari (leakage / overfit / stress × 3 + tail-risk)
|
||||
|
||||
- **EXIT-02 CONFUTATO (2/3).** (a) Overfit: è **Pareto-dominato da no_sl a
|
||||
ZERO parametri** su tutti i 6 sleeve OOS (Sharpe base→trail→noSL: MR01 BTC
|
||||
2.77→3.08→5.67; MR02 ETH 12.35→11.41→17.24 — il trail PEGGIORA lo sleeve di
|
||||
punta) → overfit di selezione: la forma parametrizzata sbagliata di una tesi
|
||||
giusta. (b) Leakage: codice pulito MA **scoperta di metodo: il 54% degli
|
||||
stop del trail è GAP-THROUGH** (l'open del bar è già oltre il livello;
|
||||
gap mediano 62-174 bps): l'engine che filla gli stop "al livello" SOVRASTIMA
|
||||
ogni policy a stop stretti; col fill realistico `worse(level, open)` il
|
||||
confronto si ribalta. **Da oggi ogni ricerca con stop tight deve modellare
|
||||
il gap-through.** Lo SL largo della base ne è quasi immune.
|
||||
- **EXIT-16 SUPERA 4/4.** Leakage: contratto pulito, robusto a 1-3 bar di lag
|
||||
e al fill a `open[j+1]` (esce deliberatamente tardi → il timing fine è
|
||||
irrilevante per costruzione). Overfit: plateau monotono su buffer 0.4→1.0
|
||||
FUORI griglia, il ponte SL-largo k=1.5→4 converge, 4 finestre temporali ok,
|
||||
e **indipendente dal loss-guard Hurst** (segnali rigenerati senza guard:
|
||||
la tesi regge anche nel regime trending). Stress: fee 2x 6/6, slippage
|
||||
20 bps simmetrico 6/6, bear 2021-22 ok.
|
||||
- **EXIT-22 invalidato SENZA mitigazione (tail-risk).** p99 MAE ~raddoppia
|
||||
(MR01 ETH −38.8→−59.7%); finestra FTX 2022-11: MR02 ETH **−39% (worst −48%,
|
||||
MAE −70%)** dove la base faceva +2.7% uscendo in 2-3 barre. E un fatto di
|
||||
wiring: con `sl=0` il worker cade nel ramo `elif max_bars` → **il fallback
|
||||
−2% è codice morto: no_sl live girerebbe SENZA ALCUNO stop**. Il disaster-SL
|
||||
4× tiene ~95% del ritorno ma il worst pooled resta −47%.
|
||||
- **Raccomandazione convergente del tail-auditor: EXIT-16** — neutralizza
|
||||
quasi tutta la coda DA SOLO (p99/worst ≈ base; FTX: +2.4%) mantenendo
|
||||
l'immunità ai wick. Mai usare uno stop stretto −2% come fallback (cappa
|
||||
l'edge insieme alla coda).
|
||||
|
||||
## Fase 3 — Test decisivo a livello PORT06 (path canonico)
|
||||
|
||||
Replay di `build_trades`/`fade_daily_equity` con **parità ESATTA** (corr
|
||||
1.00000, ritorni identici, PORT06 base == `Portfolio.backtest()` al centesimo:
|
||||
FULL 6.47/4.10%, OOS 8.82/1.30% — i numeri 6.07/8.19 citati in CLAUDE.md sono
|
||||
pre-refresh-dati). Poi SOLO il ramo SL sostituito col close-confirm 0.5·ATR:
|
||||
|
||||
| PORT06 | FULL Sharpe | FULL DD | FULL CAGR | OOS Sharpe | OOS DD | OOS CAGR |
|
||||
|--------|------------|---------|-----------|-----------|--------|----------|
|
||||
| base | 6.47 | 4.10% | 61% | 8.82 | 1.30% | 86% |
|
||||
| **EXIT-16** | **7.84** | **2.60%** | **79%** | **10.06** | **1.15%** | **102%** |
|
||||
|
||||
Gate (lo stesso del loss-guard Hurst): **PROMOSSO** — migliora OGNI metrica,
|
||||
FULL e OOS. Per-sleeve: ritorni FULL ~4-10x (MR01 BTC 299→1963%) e DD giù su
|
||||
5/6 (eccezione MR02 ETH +3.4pp, assorbita in aggregato).
|
||||
|
||||
## Verdetto e piano di deploy (DA FARE, non ancora implementato)
|
||||
|
||||
**EXIT-16 close_confirm_sl, buffer 0.5·ATR14, SOLO sulle 6 fade.**
|
||||
1. Param `sl_confirm_atr=0.5` nelle fade (default None = comportamento
|
||||
attuale, per non rompere i backtest canonici/regression-lock).
|
||||
2. `FadeStrategy.backtest` + `StrategyWorker.tick`: disattivare l'uscita
|
||||
intrabar a sl0; aggiungere il ramo sul CLOSE del bar (long: esci se
|
||||
`close < sl0 − 0.5·ATR14`; short speculare). TP intrabar e max_bars
|
||||
INVARIATI. ATR14 causale già disponibile.
|
||||
3. Shadow reale: nessun nuovo tipo d'ordine (il close-confirm esce al close
|
||||
del worker → market reduce-only come oggi; il limit resting al TP di
|
||||
v1.0.7 resta identico).
|
||||
4. DIP01/pairs/rotation/tsmom/shape NON toccati.
|
||||
|
||||
## Caveat onesti
|
||||
|
||||
- L'uscita al close può essere PEGGIO di sl0 sui veri sfondamenti (già nei
|
||||
numeri del backtest, ma la coda dipende dai gap: campione 1h crypto,
|
||||
stress estremi sottorappresentati).
|
||||
- Niente stop fisico sul book → rischio gap/disconnessione fra i poll
|
||||
(mitigazione possibile in futuro: disaster-SL intrabar a 4× come cintura,
|
||||
costa ~5% del guadagno).
|
||||
- avg_bars +~18% (esposizione su; già nei numeri via non-overlap).
|
||||
- I numeri per-sleeve FULL (ret 4-10x) vanno letti col solito sconto del
|
||||
compounding su 8 anni; la decisione è presa sul gate PORT06, non su quelli.
|
||||
|
||||
## Scoperte collaterali da NON perdere
|
||||
|
||||
1. **Gap-through fill**: l'engine intrabar filla gli stop al livello anche
|
||||
quando l'open è già oltre → bias sistematico PRO stop-stretti. Aggiungere
|
||||
il fill `worse(level, open)` all'harness prima di future ricerche su stop.
|
||||
2. **Wiring worker**: una strategia con `sl=0`+`max_bars` gira nel ramo
|
||||
`elif max_bars` → il fallback −2% non si applica. Oggi nessuna strategia
|
||||
attiva emette sl=0, ma il ramo va reso esplicito se mai si deployasse
|
||||
una policy senza SL.
|
||||
3. Il prior ladder di stamattina è confermato e generalizzato: 4 conferme
|
||||
indipendenti che oltre il TP non c'è nulla da cavalcare.
|
||||
|
||||
## Costi della ricerca
|
||||
|
||||
34 agenti (23 explore + 10 verify + 1 PORT06), ~1.65M token subagente,
|
||||
~70 minuti wall-clock su 2 core. Workflow: `exit-policy-explore`
|
||||
(wf_4b23e922-f48) + `exit-policy-verify` (wf_f2bb98df-c43).
|
||||
|
||||
## IMPLEMENTATO E DEPLOYATO (sera stessa, v1.1.0)
|
||||
|
||||
Param `sl_confirm_atr` (default None = comportamento storico):
|
||||
- `src/strategies/fade_base.py` `FadeStrategy.backtest` + `scripts/strategies/
|
||||
MR01_bollinger_fade.py` (ha un backtest proprio, duplicato storico — patch
|
||||
identica): ramo close-confirm al posto dell'SL intrabar; TP intrabar e
|
||||
max_bars invariati; in modalità confirm il TP ha priorità nel bar (come la
|
||||
policy validata in exit_lab).
|
||||
- `src/live/strategy_worker.py` `tick`: con `sl_confirm_atr` nei params dello
|
||||
sleeve, TP intrabar al livello come prima; stop SOLO se `close` sfonda
|
||||
`sl ∓ buf·ATR14(df)`, uscita al prezzo corrente (reason `stop_loss`
|
||||
invariata → il monitor stop-rate di `hourly_report` continua a funzionare).
|
||||
- `scripts/portfolios/_defs.py`: `SL_CONFIRM_ATR = 0.5` sulle 6 fade (path
|
||||
live, come `hurst_max`). Il backtest canonico resta NON filtrato.
|
||||
- Test: `tests/portfolio/test_close_confirm_sl.py` (wick non stoppa; breach
|
||||
sul close stoppa al close; TP intrabar resta; buffer regge; regressione
|
||||
senza param). 59/59 verdi.
|
||||
|
||||
**Nota onesta dal sanity-check sul path GREZZO (nessun filtro):** il ritorno
|
||||
esplode (MR02 ETH cap 366k→3.0M) ma il **DD per-sleeve SALE** (MR01 BTC
|
||||
32→52%): senza trend-filter/hurst il close-confirm tiene posizione anche nei
|
||||
trend profondi. La riduzione di DD vive nella config live (trend_max 3.0 +
|
||||
hurst 0.55) e nella diversificazione — esattamente ciò che il test PORT06
|
||||
canonico ha misurato (DD 4.10→2.60). Le tre protezioni sono COMPLEMENTARI:
|
||||
hurst toglie l'esposizione al regime tossico, il trend-filter gli ingressi
|
||||
sovra-estesi, il close-confirm i falsi stop da wick.
|
||||
|
||||
**Monitoraggio live:** lo stop-rate fade su `hourly_report` dovrebbe scendere
|
||||
sotto il ~38% atteso post-hurst; gli stop avranno exit leggermente oltre il
|
||||
livello (uscita al close), i TP restano al livello (e nello shadow reale al
|
||||
limit reduce-only di v1.0.7).
|
||||
|
||||
Deploy: commit `a2579d2` (+ research `ad65a0b`), release v1.1.0.
|
||||
@@ -1,63 +0,0 @@
|
||||
# 2026-06-04 — Exit ladder (80% del TP → esci 80%, runner con stop dinamico): SCARTATO
|
||||
|
||||
## La proposta
|
||||
|
||||
"E se all'80% del TP usciamo con l'80% della posizione, mettiamo uno SL dinamico
|
||||
su quella soglia (profitto lockato) e lasciamo correre il 20% restante?"
|
||||
|
||||
Idea: uscita scalare — bancare prima la maggior parte del profitto (la soglia
|
||||
all'80% viene toccata più spesso del TP pieno) e tenere un runner free-ride con
|
||||
worst-case alla soglia, best-case oltre il TP.
|
||||
|
||||
## Il test (onesto, stessi segnali)
|
||||
|
||||
`scripts/analysis/partial_tp_ladder.py`: replay intrabar degli STESSI segnali
|
||||
delle 3 fade (params live: `trend_max=3.0, ema_long=200, hurst_max=0.55,
|
||||
min_tp_frac=0.0015`), engine identico a `fade_base` (ingresso a `close[i]`,
|
||||
SL pieno prioritario nello stesso bar, fee 0.10% RT × leva 3 — il ladder NON
|
||||
paga fee extra: due uscite ma stesso notional). Convenzioni conservative: se il
|
||||
bar che tocca la soglia chiude oltre (rientro), il runner è stoppato subito.
|
||||
Griglia: base vs ladder (f=0.8 q=0.8 — la proposta —, f=0.8 q=0.5, f=0.5 q=0.5),
|
||||
FULL + OOS (nov 2023→), BTC+ETH.
|
||||
|
||||
## Risultati (proposta f0.8 q0.8)
|
||||
|
||||
| Sleeve | ret% FULL base→ladder | DD% | ret% OOS | win% OOS |
|
||||
|---|---|---|---|---|
|
||||
| MR01 BTC | 92 → 92 | 13.8 → 10.0 | 41 → 39 | 60 → 65 |
|
||||
| MR01 ETH | 194 → 195 | 16.5 → 15.3 | 134 → 147 | 70 → 75 |
|
||||
| MR02 BTC | 129 → 112 | 19.0 → 17.2 | 66 → 54 | 55 → 59 |
|
||||
| **MR02 ETH** | **2135 → 1319** | 16.2 → 12.7 | **893 → 651** | 75 → 80 |
|
||||
| MR07 BTC | 78 → 78 | 6.8 → 5.2 | 43 → 40 | 64 → 66 |
|
||||
| MR07 ETH | 115 → 96 | 10.6 → 10.6 | 68 → 64 | 66 → 70 |
|
||||
|
||||
## Verdetto: NO-GO (gate fallito)
|
||||
|
||||
1. **Il runner non corre.** Su centinaia di trade finisce oltre il TP quasi mai
|
||||
(~3% dei partial; 0-15 casi per sleeve) e viene **stoppato alla soglia nel
|
||||
~60% dei tocchi**. È la fisica mean-reversion: il TP delle fade sta ALLA
|
||||
MEDIA — lì il movimento è esaurito per costruzione. Il runner è un
|
||||
trend-follow della coda, e i breakout rientrano (lezione squeeze).
|
||||
2. **Il costo è concentrato sui winner migliori**: ogni TP pieno ora esce
|
||||
all'80% della strada sulla quota grossa → MR02 ETH (lo sleeve più forte)
|
||||
−38% ret FULL / −27% OOS. Sharpe per-trade ~piatto: non migliora il
|
||||
rischio/rendimento, scambia ritorno con DD.
|
||||
3. **Quello che compra** (win-rate +4-5pp, DD −1-4pp) è lo stesso profilo del
|
||||
**vol-target sizing già scartato** ("abbassa il DD ma sacrifica ritorno");
|
||||
il lavoro anti-DD lo fa già il loss-guard Hurst, che il gate l'ha passato
|
||||
perché taglia SOLO i loser.
|
||||
|
||||
Nota dal grid: `f0.5 q0.5` su MR07 ETH fa Sharpe OOS 6.58 / win 82%, ma
|
||||
distrugge MR02 (2135→531) → nessuna variante robusta su tutti gli sleeve,
|
||||
niente cherry-picking per-sleeve.
|
||||
|
||||
Argomento esecutivo in più: il ladder raddoppierebbe la complessità dello
|
||||
shadow appena deployato (v1.0.7: limit reduce-only al TP) — due resting order
|
||||
per posizione, due riconciliazioni, e lo stop dinamico avrebbe il problema dei
|
||||
trigger Deribit (nuovo order_id al trigger → fill non verificabile per
|
||||
order_id).
|
||||
|
||||
**Conferma della lezione di famiglia:** i tweak d'exit che toccano i winner
|
||||
falliscono il gate (time-stop, vol-target, ADX, vratio… e ora il ladder);
|
||||
l'unico anti-perdite che passa resta il loss-guard Hurst, che riduce
|
||||
l'esposizione nel regime tossico senza toccare le uscite.
|
||||
@@ -1,92 +0,0 @@
|
||||
# 2026-06-04 — Shadow execution: divergenza sim/reale misurata + TODO limit reduce-only
|
||||
|
||||
## Deploy v1.0.6
|
||||
|
||||
Fix float deployata (`74670da` + release): `_quantize_step` con `Decimal` in
|
||||
`src/live/execution.py` — `72*0.001 = 0.07200000000000001` causava `Invalid params`
|
||||
su Deribit (1 `REAL_OPEN_FAIL` su MR07 il 2026-06-03). Resume pulito al restart.
|
||||
|
||||
## Misura della divergenza sim vs reale (primi 7 close shadow)
|
||||
|
||||
**Bilancio: PnL sim +11.85 USD vs reale +0.62 USD → delta −11.22 USD.**
|
||||
Le fee NON sono il problema ($0.63 totali = 0.05%/lato, esattamente l'assunto del
|
||||
backtest). Il problema è tutto nel **timing delle uscite**.
|
||||
|
||||
- **Aperture allineate**: slippage da −8 a +27 bps, mediana ~±7 bps. OK.
|
||||
- **Chiusure take-profit: +235 bps di slippage medio** (MR07 ETH short: +257/+267/+283/+333 bps).
|
||||
Causa strutturale, non liquidità: il sim esce *al livello TP* intrabar (come il
|
||||
backtest), il reale chiude **a mercato solo al poll del tick**, quando il prezzo è
|
||||
già rientrato (TP toccato a ~1790, fill reale a ~1840). Sim +3 USD a trade, reale ~0.
|
||||
- **Stop-loss: stessa meccanica ma a favore** (MR02 SL: −0.68 reale vs −2.87 sim).
|
||||
Le fade però hanno più TP che SL → netto negativo.
|
||||
- **2 `REAL_CLOSE` non verificate** (order_id null, fallback su stima sim). Venue flat
|
||||
(`get_positions()=[]`), nessuna posizione orfana — ma sorvegliare i prossimi close.
|
||||
|
||||
**Implicazione onesta: l'edge di MR07 non sopravvive all'esecuzione market-on-poll.**
|
||||
Il backtest assume il fill al livello TP; il reale incassa il prezzo post-rimbalzo.
|
||||
|
||||
## TODO (richiesto, da implementare)
|
||||
|
||||
Nello shadow-execution (`src/live/execution.py` + `StrategyWorker`): all'apertura
|
||||
della posizione reale piazzare su Deribit un **LIMIT reduce-only appoggiato al
|
||||
livello TP** (e idealmente stop-market per lo SL), invece di chiudere a mercato al
|
||||
poll — così il fill reale replica l'assunzione intrabar del backtest.
|
||||
|
||||
Dettagli da considerare:
|
||||
- cancellare/aggiornare l'ordine resting se il sim esce per `max_bars` o al restart (resume);
|
||||
- i 3 fade BTC condividono lo strumento (posizioni nettate per conto): il limit
|
||||
reduce-only deve coprire la SOLA quota del worker, come già fa `close_amount`;
|
||||
- verificare il fill del resting order via `get_trade_history` (order_id), come per i market.
|
||||
|
||||
## IMPLEMENTATO (sera): LIMIT reduce-only al TP
|
||||
|
||||
**Flusso nuovo.** A ogni `REAL_OPEN` verificato il worker piazza subito un
|
||||
**limit reduce-only al livello TP** (lato opposto, stesso `amount` della SOLA
|
||||
quota del worker — strumento condiviso fra i 3 fade per coin) → evento
|
||||
`REAL_TP_RESTING` (o `REAL_TP_FAIL` → si resta sul vecchio market-on-poll).
|
||||
Alla chiusura sim, qualunque sia la ragione, `_real_close` ora:
|
||||
1. **cancella** il resting (innocuo se già fillato — e dopo il cancel nessun
|
||||
fill può più arrivare, niente race);
|
||||
2. **riconcilia i fill** (anche parziali) dal `get_trade_history` per order_id
|
||||
(stessa fonte autorevole dei market), con retry se il cancel risulta
|
||||
"già fillato" ma la history è in ritardo;
|
||||
3. chiude a **market reduce-only solo la quota residua** (exit non-TP:
|
||||
stop_loss/time_limit, o TP non raggiunto sullo strumento d'esecuzione);
|
||||
4. ledger reale su **prezzo d'uscita combinato** (media pesata fill-TP +
|
||||
market) e fee sommate. `REAL_CLOSE` logga `tp_order_id`,
|
||||
`tp_filled_amount`, `market_amount`.
|
||||
|
||||
**Dettagli del TODO coperti:**
|
||||
- `max_bars`/`stop_loss` → il cancel è il passo 1 di ogni chiusura;
|
||||
- restart → `real_tp_order_id` è **persistito** in `status.json`: al resume il
|
||||
resting resta in book e la prima chiusura lo riconcilia normalmente;
|
||||
- quota del worker → il limit usa lo stesso `amount` dell'apertura (mai
|
||||
`close_position`); il residuo è ri-quantizzato allo step (Decimal) dentro
|
||||
`close_amount` (niente artefatti float tipo `0.072-0.024`);
|
||||
- prezzi limit quantizzati al **tick** dello strumento (`quantize_price`,
|
||||
BTC_USDC 0.5 / ETH_USDC 0.05 — Deribit rifiuta prezzi off-tick).
|
||||
|
||||
**SL: niente stop-market, decisione deliberata.** (a) Su Deribit un trigger
|
||||
order, quando scatta, genera l'ordine eseguito con un **nuovo order_id** → il
|
||||
fill non sarebbe verificabile via `get_trade_history` per order_id (il
|
||||
requisito di verifica); (b) la misura di stamattina mostra che sul SL il
|
||||
market-on-poll lavora **a favore** (il rimbalzo riduce la perdita). Lo SL resta
|
||||
quindi market-on-poll.
|
||||
|
||||
**Bonus fee.** Quando il TP filla da resting il fill è **maker** (~0% su
|
||||
Deribit) invece di taker 0.05% — il reale farà meglio dell'assunto 0.10% RT
|
||||
sulle uscite TP.
|
||||
|
||||
**Verifica.** `live_shadow_smoke.py` esteso ai due percorsi e passato su
|
||||
testnet: (A) resting in book → exit `time_limit` → cancel + market fallback,
|
||||
conto flat; (B) TP già crossato → fill immediato del limit, chiusura
|
||||
riconciliata dalla history **senza ordine market** (`market_amount=0`),
|
||||
prezzo persino migliore del TP (+48 bps, taker sul cross). 54 test pytest OK.
|
||||
|
||||
**Caveat residuo onesto.** Se il processo muore DOPO il fill del resting e
|
||||
PRIMA della chiusura sim, il worker al resume riconcilia al prossimo exit sim
|
||||
(corretto); ma nell'intervallo la quota reale è già chiusa mentre il sim la
|
||||
crede aperta — finestra breve e solo contabile. Inoltre il TP del sim è sul
|
||||
feed (`BTC-PERPETUAL` inverse) mentre il limit vive sul lineare USDC: la base
|
||||
fra i due può far fillare/non fillare il limit a cavallo del livello — il
|
||||
fallback market copre il caso.
|
||||
@@ -1,67 +0,0 @@
|
||||
# Diario — 2026-06-05 — Fix EXIT-16 live: confirm sul close di barra COMPLETATA + alert STALE_FEED
|
||||
|
||||
## Innesco
|
||||
|
||||
Crash ETH 2026-06-05: gli stop MR01/MR02 ETH sono scattati molto sotto il livello
|
||||
nominale (MR02: sl 1636.28 → exit 1600.45; MR01: sl 1610.75 → exit 1594.35).
|
||||
Analisi delle due concause dichiarate:
|
||||
|
||||
1. **EXIT-16 close-confirm** (by design): uscita al close oltre `sl ∓ 0.5·ATR14`,
|
||||
non al livello — costo accettato e MODELLATO nel backtest validato (7.84/10.06).
|
||||
2. **Feed gappato**: ETH testnet flat ~2h (1656.80/1655.55, 13:00–14:50 UTC), poi
|
||||
una candela 14:55 da 1634 a 1600 — nessun prezzo esisteva tra SL ed exit. I fill
|
||||
REALI confermano (1600.2 / 1589.7, slippage −1.6/−29 bps): non è un bug, è il mercato.
|
||||
|
||||
## Scoperta: divergenza implementativa REALE nel worker
|
||||
|
||||
Audit dei 3 stop ETH del 2026-06-04/05 contro le candele:
|
||||
|
||||
| Stop live | Close barra COMPLETATA al momento | Confirm | Verdetto |
|
||||
|---|---|---|---|
|
||||
| MR02 06:03 @1672.9 | 1682.25 (05:00) | ~1675.4 | **wick-stop**: il backtest NON avrebbe stoppato lì |
|
||||
| MR02 15:00 @1600.45 | 1600.05 (14:00) | ~1621 | legittimo, fill ≈ backtest |
|
||||
| MR01 15:01 @1594.35 | 1600.05 (14:00) | ~1594.4 | **wick-stop**: il backtest NON avrebbe stoppato lì |
|
||||
|
||||
**2 su 3 erano valutazioni sulla barra IN FORMAZIONE**: `tick` confrontava
|
||||
`current_price` (close istantaneo della candela in corso al poll) con `sl − buf`.
|
||||
Il backtest (`fade_base`) valuta il confirm SOLO sul close di barra completata
|
||||
`c[j]`. La differenza reintroduce live esattamente la wick-sensitivity che EXIT-16
|
||||
elimina: un dip infrabarra sotto il confirm stoppava anche se la barra chiudeva
|
||||
sopra (e nei dip-che-rientrano la fade vince — è il suo edge). Live sarebbe stato
|
||||
strutturalmente PIÙ stop-prone del backtest validato.
|
||||
|
||||
## Fix (`strategy_worker.py`, ramo sl_confirm_atr)
|
||||
|
||||
- Il confirm è valutato sul **close dell'ultima barra COMPLETATA**: l'ultima riga
|
||||
del df è la candela in corso finché non è trascorsa la sua durata
|
||||
(`now_ms < ts[-1] + bar_ms`, `bar_ms` = mediana dei delta timestamp → regge 1h/4h/1d).
|
||||
- Il `buf` usa l'ATR14 alla stessa barra completata (prima: barra in formazione).
|
||||
- Il **fill resta al prezzo corrente** al poll (lag ≈ stress `lag_close_exit`,
|
||||
superato in exit-lab). TP intrabar sulla barra in corso INVARIATO (= backtest).
|
||||
- Test nuovi in `test_close_confirm_sl.py` (sezione FIX 2026-06-05): il dip della
|
||||
candela in corso non stoppa; il breach della completata stoppa anche se rimbalzato;
|
||||
TP intrabar invariato. NB fixture: timestamp in ms ESPLICITI
|
||||
(`Timestamp.now()` è risoluzione µs → `astype int64 // 10**6` darebbe secondi).
|
||||
|
||||
## Concausa feed: entry-guard TESTATA e BOCCIATA, solo osservabilità
|
||||
|
||||
Quantificato (1h, storico completo): segnali fade subito dopo barre flat = BTC
|
||||
0.2–0.9%, **ETH 3.4–11.8%**. Backtest con skip di quei segnali (config live,
|
||||
sl_confirm 0.5): **PEGGIORA tutti gli sleeve ETH** (MR01 +1344→+1256, MR02
|
||||
+2372→+2250, MR07 +740→+621; BTC ~invariato). La candela-gap post-flat è
|
||||
l'overshoot che la fade fada con profitto — e i fill reali post-crash lo
|
||||
confermano (riaperture a −1.9 bps di slippage). **Niente skip degli ingressi.**
|
||||
|
||||
Aggiunto invece **alert Telegram `STALE_FEED`** (`runner._check_stale_feed`):
|
||||
notifica quando un asset ha ≥2 barre 1h complete flat (worker ciechi) e al
|
||||
risveglio col **gap %** del primo prezzo reale. Una notifica per episodio
|
||||
(dedup per asset). Solo osservabilità, zero effetto sulle decisioni.
|
||||
|
||||
## Cosa NON è stato toccato (e perché)
|
||||
|
||||
- Il **costo del confirm** (uscita al close, non al livello nominale) resta: è il
|
||||
trade-off validato di EXIT-16 (FULL 6.47→7.84, OOS 8.82→10.06) — i wick-stop
|
||||
evitati pagano molto più dei close-stop più profondi.
|
||||
- Il **gap-through** non è mitigabile lato exit: nessun prezzo esisteva tra SL ed
|
||||
exit (fill reali ≈ sim). L'unica protezione strutturale resta la diversificazione
|
||||
(17 sleeve) + i cap di famiglia.
|
||||
@@ -1,99 +0,0 @@
|
||||
# Diario — 2026-06-05 — SL su SH01: ricerca multi-agente (verdetto: NO-SL, cap del peso)
|
||||
|
||||
## Innesco
|
||||
|
||||
Crash ETH del 2026-06-05 (1742→1546, −11%, con feed testnet FLAT ~2h e gap 1655→1600):
|
||||
SH01 ETH si è preso la coda intera, **−15.6% in un trade** (long 1727.8 → time_limit 1594.35,
|
||||
leva 2x) — il singolo trade peggiore del portafoglio live. SH01 non ha TP/SL per design
|
||||
(exit solo a orizzonte H=12). Domanda: esiste uno SL che taglia le code senza distruggere
|
||||
l'edge (win ~50%, edge tutto nell'asimmetria dei winner)?
|
||||
|
||||
## Numeri storici per anno (config live W24 H12 th0.58, netto fee 0.10% RT, leva 3x)
|
||||
|
||||
Somma per-trade in pp (leva 3x); equity-level ≈ ×0.15.
|
||||
|
||||
| Anno | BTC | ETH |
|
||||
|---|---:|---:|
|
||||
| 2018 | −65.8 | +73.7 |
|
||||
| 2019 | +87.7 | −19.3 |
|
||||
| 2020 | +194.0 | **−293.1** |
|
||||
| 2021 | +301.3 | +67.4 |
|
||||
| 2022 | +64.3 | +79.1 |
|
||||
| 2023 | +17.4 | +20.6 |
|
||||
| 2024 | +110.0 | +108.1 |
|
||||
| 2025 | +76.8 | +539.7 |
|
||||
| 2026 | +59.0 | −29.5 |
|
||||
|
||||
BTC = motore robusto (8/9 anni+). ETH = fragile (DD 61%, win 48.8%): la coda non
|
||||
protetta è un problema STRUTTURALE di ETH, non solo dell'episodio live.
|
||||
|
||||
## Infrastruttura (riusabile)
|
||||
|
||||
`scripts/analysis/sh01_exit_lab.py` — harness onesto stile exit-lab:
|
||||
- cache segnali walk-forward (`data/cache/sh01_exit_lab.pkl`, 7248 BTC + 7386 ETH entries);
|
||||
- engine intrabar con **fill GAP-AWARE**: stop fillato a `worse(livello, open[j])`, non
|
||||
"al livello" — chiude il bias PRO-stop-stretti documentato il 2026-06-04 (54% di fill
|
||||
ottimisti) e modella il caso reale del crash (gap 1655→1600 senza scambi intermedi);
|
||||
- modalità stop `intrabar` e `close` (close-confirm stile EXIT-16), `after_bar` per
|
||||
policy discrezionali, stress `lag_close_exit` (poll in ritardo);
|
||||
- parity ESATTA con `explore_lab.simulate` (BTC +218.50%/1531 trade, ETH +80.13%/1257);
|
||||
- protocollo: TRAIN fino 2023-11-01 (selezione SOLO lì, plateau ≥3 celle), OOS una volta.
|
||||
|
||||
Baseline (orizzonte puro): BTC TRAIN +127%/dd23/shrp2.09/worst−5.5 | OOS +41%/8/2.18/−3.1.
|
||||
ETH TRAIN **−26%/dd61/shrp−0.16/worst−14.9** | OOS +143%/7/**3.60**/−4.6.
|
||||
|
||||
## Esito: 11 famiglie testate, 0 sopravvissute
|
||||
|
||||
Policy in `scripts/analysis/sh01_exit_policies/` (01-10 dagli agenti + 11 dal
|
||||
completeness-probe della sintesi):
|
||||
|
||||
| # | Famiglia | Verdetto |
|
||||
|---|---|---|
|
||||
| 01 | ATR fisso intrabar (k 1–5) | NO: 0/7 celle migliorative sul train |
|
||||
| 02 | ATR fisso close-confirm (k 1–5) | NO: k=4 migliora ETH train (shrp −0.16→+0.62, DD 61→41, worst −8.4) MA ETH-OOS peggiora (shrp 3.60→2.32, worst −6.6) |
|
||||
| 03 | % fisso (1–5%, 2 modi) | NO: BTC↓, ETH-OOS ret 52% del baseline |
|
||||
| 04 | Chandelier trailing | NO: cella isolata; ETH-OOS tutto peggio (4ª bocciatura della famiglia trailing) |
|
||||
| 05 | Breakeven ratchet | NO: 0 celle migliorative |
|
||||
| 06 | Giveback (profit-protection) | NO: dormiente sulle code (worst invariato), taglia winner BTC |
|
||||
| 07 | Loser time-stop (m,x) | NO: ETH-OOS shrp↓ DD↑, BTC↓ |
|
||||
| 08 | Disaster-cap LARGO close-confirm (k 3–6) | NO: k=4 plateau sul train ma ETH-OOS DD 7→11-15%, ret 59-74%; FABBRICA short da stop a −44/−54% |
|
||||
| 09 | Swing strutturale | NO: 0/18 celle |
|
||||
| 10 | Stop condizionale vol-regime | NO: il migliore dei falliti (ETH-OOS shrp 3.28 vs 3.60) ma BTC train <95% |
|
||||
| 11 | Disaster-cap LARGO **intrabar** (k 5–12) | NO: k=10 cella isolata; BTC-OOS shrp 2.18→**0.92**, worst −3.1→−11.4 (il fill gap-aware rende lo stop più tossico del no-stop) |
|
||||
|
||||
**Pattern (5ª conferma della lezione exit-lab):** ogni stop abbastanza stretto da toccare
|
||||
la coda ETH intacca il motore BTC; ogni stop abbastanza largo da risparmiare BTC non
|
||||
arriva mai alla coda ETH. Per un segnale win~50% con edge nell'asimmetria dei winner,
|
||||
OGNI SL taglia i winner-in-drawdown insieme ai loser. In più il fill gap-aware mostra
|
||||
che proprio nei crash (quando lo stop servirebbe) il fill è al gap, non al livello:
|
||||
lo stop intrabar largo PEGGIORA la coda OOS di BTC invece di proteggerla.
|
||||
|
||||
## Decisione
|
||||
|
||||
- **NO SL su SH01** (né `sl` né `sl_confirm_atr` per SH_BTC/SH_ETH: corretto E sicuro —
|
||||
il fallback −2% del worker si applica solo se `sl` è presente).
|
||||
- **La leva giusta è il PESO**: cap della famiglia SHAPE nel weighting di PORT06
|
||||
(`weighting.py` supporta già `caps` per famiglia, come PAIRS 0.33). Dimezzare la quota
|
||||
SHAPE ≈ dimezza l'impatto della prossima coda −15% sul conto, a costo ~nullo di Sharpe
|
||||
(SH01 è un diversificatore, corr +0.08 col MASTER).
|
||||
- **APPLICATO E DEPLOYATO (stesso giorno):** `caps={"PAIRS": 0.33, "SHAPE": 0.0588}` in
|
||||
`_defs.py` (SHAPE 11.8%→5.9%, ≈ mezzo sleeve equal; SH_BTC=SH_ETH=0.0294, somma pesi 1.0,
|
||||
verificato). Quantificato sul backtest PORT06:
|
||||
|
||||
| Config | FULL Sharpe | FULL DD | CAGR | OOS Sharpe | OOS DD |
|
||||
|---|---:|---:|---:|---:|---:|
|
||||
| precedente (SHAPE 11.8%) | 6.47 | 4.10% | 61.2% | 8.82 | 1.30% |
|
||||
| **cap SHAPE 5.9% (scelto)** | 6.43 | 3.96% | 62.1% | 8.58 | 1.36% |
|
||||
| SHAPE rimosso | 6.30 | 3.88% | 63.0% | 8.26 | 1.41% |
|
||||
|
||||
Il costo (−0.24 OOS Sharpe) è il premio dell'assicurazione su una coda che il backtest
|
||||
daily NON modella (gap di feed, flat testnet). Rimuovere SHAPE costa troppo (8.26).
|
||||
|
||||
## Direzioni future (fuori scope SL, annotate dalla sintesi)
|
||||
|
||||
1. **Liquidity/staleness-gate sull'ENTRY** (skip ingressi dopo finestre di feed flat —
|
||||
il flat 2h ha preceduto il gap del 2026-06-05): la direzione più promettente per il
|
||||
gap-through specifico, merita uno studio dedicato.
|
||||
2. Vol-target sizing per-trade su SH01 (sulle fade fallì, su SH01 mai testato).
|
||||
3. SL solo-ETH: scartato anche concettualmente (il beneficio coda ETH è marginale/nullo
|
||||
OOS in TUTTE le famiglie — non è un problema di uniformità del meccanismo).
|
||||
@@ -1,71 +0,0 @@
|
||||
# 2026-06-06 — Improvement sweep multi-agente (review live PORT06)
|
||||
|
||||
> Ricerca multi-agente del 2026-06-06 (106 agenti, 196 finding grezzi, 60 verificati avversarialmente, 37 validi / 23 uccisi).
|
||||
> Workflow: port06-improvement-sweep (wf_56b7d4de-a06).
|
||||
|
||||
|
||||
## 1. Quadro d'insieme
|
||||
|
||||
Il sistema PORT06 gira correttamente nella struttura (17 sleeve, runner pool/ledger == backtest), ma la review ha trovato **due classi sistematiche di problemi**, non bug isolati.
|
||||
|
||||
**(a) Divergenze live-vs-backtest per omissione di protezione.** Il pattern documentato del progetto è "il live AGGIUNGE protezione che il backtest canonico non ha" (Hurst, EXIT-16) → il live fa meglio del backtest sul DD. Qui si trova il contrario in più punti: il filtro `trend_max=3.0` è ON nel backtest canonico ma **OFF in produzione su tutte e 6 le fade** (base.py:91 / _defs.py:35-38); il cap `SHAPE=0.0588` v1.1.2 è **inerte** (sovrascritto da portfolios.yml) → SH01 gira a **2x peso** senza stop-loss; EXIT-16 non è esteso a DIP01 (l'unico sleeve BTC che esegue davvero); la forming-bar lesson non è portata a TR01 né a PairsWorker. Diversi diari (2026-06-04-partial-tp-ladder.md:15, 2026-06-04-exit-lab.md) documentano config che il codice NON implementa.
|
||||
|
||||
**(b) Calibrazione/sizing che diverge dal validato.** SH01 fa fuoco sul 25% delle barre vs 2.9% validato (th0.58 inerte per train-window troppo corto); i pairs girano a `pos=0.5` mentre tutta la validazione PR01 è `pos=0.15` (DD ~3.3x); TR01 sotto-carica le fee 2x (manca il fattore leva).
|
||||
|
||||
Tema ricorrente onesto: **la maggior parte delle "scoperte" sono ripristini di config già validate, non nuovo alpha.** I bug di config (cap, trend_max) vanno corretti subito; ogni cambio di *strategia* deve passare il gate PORT06/OOS (precedente FR01: robusto-individualmente ≠ migliora PORT06).
|
||||
|
||||
## 2. P0 — Protezione capitale / gap live
|
||||
|
||||
| Titolo | Cosa fare | Evidenza | Effort |
|
||||
|---|---|---|---|
|
||||
| **Cap SHAPE 0.0588 inerte → SH01 a 2x peso** | `load_active_portfolio` deve fare **deep-merge** dei caps (partire da `p.caps` e aggiornare con `ov["caps"]`), oppure ridichiarare il dict completo in `portfolios.yml:7` come `{PAIRS:0.33, SHAPE:0.0588}`. Ri-snapshot pesi, confermare sum=1.0. SH01 non ha SL by-design e ha già subìto un −15.6% live: il cap è l'UNICA protezione coda. | `src/portfolio/base.py:91-93` setattr sovrascrive caps; `portfolios.yml:7` `{PAIRS:0.33}`; `scripts/portfolios/_defs.py:75` `{PAIRS:0.33,SHAPE:0.0588}`; live `data/portfolios/PORT06/status.json` SH_BTC=SH_ETH=0.0588 (totale 0.1176 = 2.0x intended). Backtest canonico usa il cap giusto (FULL 6.43/OOS 8.58) → è una rottura di parità. | low |
|
||||
|
||||
> Nota: la stessa correzione risolve anche il sotto-peso ~9% di tutti gli altri non-pairs (0.0588 live vs 0.0647 intended); il rischio materiale è solo SHAPE.
|
||||
|
||||
## 3. P1 — Alto valore, testabile subito
|
||||
|
||||
| Titolo | Cosa fare | Evidenza | Effort |
|
||||
|---|---|---|---|
|
||||
| **`trend_max=3.0` OFF in produzione su tutte le 6 fade** | Aggiungere `"trend_max":3.0, "ema_long":200` alla SleeveSpec FADE `_defs.py:36-37`. Ripristina la config del backtest canonico (look-ahead-free, EMA200 causale). MR02/MR07 lo onorano (non lo ignorano). Ri-validare a livello PORT06 (template `exit16_port06_impact.py`) perché Hurst+trend si sovrappongono. | `_defs.py:35-38` (no trend_max); `MR01_bollinger_fade.py:61` `get('trend_max')`→None; `combine_portfolio.py:47` canonico usa trend_max=3.0; `risk_management.py:242` lo applica a tutte e 3. Live: MR01_ETH/MR02_ETH hanno fadato il crash ETH 06-05 più volte (long@1658.9 poi long@1592.8 in caduta 1727→1517), tutti stoppati (trades.jsonl). Misurato (live-hurst-on, 3x): MR02_ETH DD 27.3%→16.2%, WR +8pp, Sharpe +1.34 (return ~dimezzato — trade-off DD/return). | low |
|
||||
| **Disaster-bracket on-book durante outage feed** | Il poll-loop intero è in un try/except: in un outage le posizioni REALI restano **senza stop sul book e senza valutazione exit**. Piazzare un bracket lontano (~−30%) su Deribit per i fade eseguiti [MR01,MR02,MR07,DIP01] via `cerbero_client.py:137 set_stop_loss` (esiste, non cablato). Non spara mai in operatività normale → 0 costo Sharpe; pura assicurazione. | `runner.py:246-298` (try/except unico, sleep su errore); ETH gap p99.9=996bps, max=3301bps, peggior 3h −3492bps (`data/raw/eth_1h.parquet`); REAL_OPEN 06-05 verificati; `docs/diary/2026-06-04-exit-lab.md:119-121` lo segnala, mai implementato. Caveat: nei crash il fill è al gap, non al livello → cappa ma non al trigger. | low-med |
|
||||
| **SH01 th0.58 inerte: fa fuoco sul 25% delle barre vs 2.9% validato** | **Ri-validare SH01 OOS con train-window pari al regime live (~8760 barre)** invece dell'expanding full-history. La LogReg su train piccolo è over-confident (mean max-proba 0.582 vs 0.536). NON limitarsi ad alzare th (la calibrazione resta sbagliata). Se l'edge non sopravvive nel regime live, riconsiderare SH01. | misurato: small-train frac≥0.58 = 44.8% vs full 3.8%; live-window 1197 entry (49.9% long) vs 139 (71.9% long), trade-rate 25.1% vs 2.9%. `SH01_shape_ml.py:60` th=0.58; tutta la validazione (`shape_ml_validate.py`) usa training expanding. È la causa meccanica del WR live 1/9. Blast radius limitato dal cap SHAPE (vedi P0). | low (test) |
|
||||
| **Pairs a pos=0.5 vs validazione pos=0.15 (DD ~3.3x)** | Introdurre un `position_size` per-famiglia (plumb `SleeveSpec`/`build_worker_for`, runner.py:43-89) e portare i pairs a **0.15-0.25**. Ri-eseguire `combine` alla pos live prima del deploy. I pairs sono la famiglia a DD-grezzo più alto (ETH/BTC 47.6%) e **senza stop** (exit solo |z|≤z_exit o max_bars). | `portfolios.yml:14` pos=0.5; `pairs_worker.py:157` pnl=cap*pos*net; `pairs_research.py:29` POS=0.15; live ADA/ETH 06-05 net −8.52% = −4.26% sleeve (sarebbe −1.28% a 0.15). Choice deliberata (commento yaml), ma diverge dal validato. | low-med |
|
||||
| **TR01: fee sotto-caricate 2x (manca leva)** | Moltiplicare il termine fee per `self.leverage` (basket_trend_worker.py:69) per allinearlo al return leveraged (riga 67) e al reference `fee=FEE_RT/2*LEV` (honest_improve2.py:150). | worker fee/flip 1.5e-05 vs corretto 3.0e-05 (POS0.15/LEV2/N5) = 2.0x. tsmom/rotation_worker sono consistenti → TR01 è l'unico difettoso. Drag assoluto piccolo (low turnover) ma bias ottimistico mono-direzionale che gonfia total_capital nel rebalance. | low |
|
||||
| **PairsWorker agisce sulla barra IN FORMAZIONE** | Portare la EXIT-16 forming-bar logic ai pairs: calcolare `bar_ms` da `median(diff(ts))` e valutare z sull'ultima barra COMPLETA (entry+exit), come `strategy_worker.py:445-447`. | `pairs_worker.py:185` i=len(m)-1, :195 exit, :204-207 entry su barra in formazione; backtest `pairs_research.py:69-75` solo close settled; `validate_worker_pairs.py` non esercita il path → divergenza non testata. | low |
|
||||
| **TR01 valuta crossover EMA sulla barra 4h in formazione** | In `tick` scartare la barra in formazione (`k=-1 if now_ms≥ts[-1]+bar_ms else -2`) e valutare il segnale sull'ultima 4h COMPLETA; correggere ANCHE il booking del return (riga 66 legge la finestra in formazione). | `basket_trend_worker.py:60-72` legge `[-1]` (forming); reference `honest_improve2.py:152` `range(n-1)` solo completi. Evidenza: SOL flip 0→1@85.66 poi 1→0@77.72 a 59min, stessa finestra 08-12 UTC (−9.3% intra-window glitch). Fix incompleto se si tocca solo il segnale. | low |
|
||||
| **DIP01 senza EXIT-16 (ed è l'unico sleeve BTC che esegue reale)** | Aggiungere `"sl_confirm_atr":0.5` (e valutare `hurst_max`) ai params DIP01 `_defs.py:41-42` (il worker lo legge già, zero codice). **Ri-validare sul grid OOS proprio di DIP01 + a livello PORT06 con engine gap-aware** prima del deploy (DD standalone sale BTC 23→37%). | `_defs.py:41-42` DIP01 ha solo {min_tp_frac}; worker gira il branch intrabar wick-sensitive (`strategy_worker.py:466`) invece del close-confirm (:429). Riproducibile: BTC FULL 299→726/OOS 60→168, ETH FULL 187→898/OOS 221→255. I 3 fade BTC sono flat (0 ordini reali); DIP01_BTC è l'UNICO BTC con round-trip reale → gap non teorico. | low (fix) / med (validazione) |
|
||||
| **TSM01 252d lookback: shortfall su un asset tronca l'inner-join sotto need=253, tick() esce in silenzio** | Aggiungere un WARN/Telegram quando `panel<need` (gated su "era già operativo" per evitare falsi positivi al cold-start). Coprire anche RotationWorker (stesso silent return). | `runner.py:37` 1d=440; `tsmom_worker.py:53-55` need=253, return muto; `rotation_worker._panel how='inner'` tronca al più corto; live margine 188 (OK ora) → latente, non attivo. | low |
|
||||
| **Osservabilità: TR01/ROT02/TSM01 invisibili in hourly_report** | `hourly_report.collect()` filtra su chiavi (`event`, `in_position`) che i worker multi-asset non emettono → 100% delle loro righe scartate. Aggiungere `in_position` ai `_save()` dei 3 worker e/o esporre `status_summary` (long correnti + giorni-dall'ultimo-flip). Distingue "flat in chop" da "wiring rotto". | TR01 2 record (entrambi 06-03, lo SOL whipsaw), flat da allora; ROT02/TSM01 0 trade (rispettivamente cash / risk-off da 06-01, by-design). `hourly_report.py:105,111`; worker `_log`/`_save` senza `event`/`in_position`. | low |
|
||||
| **MR07 reale: ripristino-fill non esercitato (short-side TP-resting mai testato)** | Smoke testnet `live_shadow_smoke.py` con `direction=-1` per esercitare il limit reduce-only BUY sotto mercato (può crossare subito → path `resting_fills`). MR07 (+ tutti i worker) ha 0 TP-resting filled finora → reconciliation completamente non testata in produzione. | MR07_ETH 5-6 REAL_OPEN tutti 06-03 PRE-fix (TP-resting 2026-06-04); +257/267/283/333bps slippage legacy (sunk, non ricorrente). Tutti i REAL_TP_RESTING verificati sono side=buy (long); il path short non è mai stato esercitato né in ledger né negli smoke. `strategy_worker.py:253` `_place_real_tp`. | low |
|
||||
|
||||
## 4. P2 — Filoni di ricerca
|
||||
|
||||
- **MR01 ETH k=2.0 vs k=2.5 deployato.** k=2.0 è uniformemente meglio OOS su ETH (no-filtro +1238% vs +487%; trend-filtrato +569% vs +196%) e neutro su BTC sotto filtro live. Non è nuovo overfit: è il config per-asset *documentato* (MR01:15-16) che il k=2.5 universale ha silenziosamente abbandonato. Da confermare a livello PORT06 con i param live (hurst/sl_confirm). `risk_management.py:40,44`.
|
||||
- **Limit-order maker entry sui fade — NO-GO confermato.** Strutturalmente infattibile: il segnale fade fa fuoco quando il close ha già bucato la banda (mediana 33bps sotto); un buy-limit al livello è marketable→taker; un limit più profondo manca i winner che rimbalzano in 1-4 min. Negativo-EV, non implementare. `MR01_bollinger_fade.py:84,93`; live MR07_ETH 5 open→TP in ~1.4min.
|
||||
|
||||
## 5. P3 / Scartati in verifica
|
||||
|
||||
- **Commento errato in `_defs.py:17-18`** ("MR02/MR07 ignorano min_tp_frac") — falso (lo leggono e applicano, MR02:46,72), ma il filtro è di fatto inerte su MR02/MR07 nel campione → solo igiene doc, no PnL.
|
||||
- **TSM01 inerte (0 trade da 06-03)** — corretto by-design (BTC sotto SMA100 dal 06-01 + tutti gli asset consensus negativo). Solo diagnostica; NON redistribuire il capitale (riduce la diversificazione quando il regime gira).
|
||||
- **Time-limit fade NON sono un leak** — myth-busting: il bucket max_bars è net-positivo OOS (+118÷+195bps, +154%/+335% totale); il vero loser è lo SL (già gestito). NON accorciare max_bars.
|
||||
- **Fill max_bars next-open vs close** — wash misurato (5/6 sleeve identici); il worker già filla ~next-open. Nessuna azione.
|
||||
- **SH01 H=12 fuori scope `exit_lab.py`** — routing: usare `sh01_exit_lab.py` (gap-aware) per qualsiasi studio orizzonte SH01. Clarificazione, non bug.
|
||||
- **PairsWorker bars_held conta poll-con-nuovo-ts non barre reali** — latente (0 time_limit su 9 close), bite solo dopo outage >2h con z ancora oltre soglia; rischio di introdurre exit-anticipato se bar_ms via median-diff su feed testnet flaky → usare bar_ms fisso. Igiene, bassa priorità.
|
||||
|
||||
## 6. Piano consigliato (2 settimane)
|
||||
|
||||
**Settimana 1 — protezione capitale e parità (config-only, niente cambio di strategia):**
|
||||
|
||||
1. **Giorno 1 — P0 cap SHAPE.** Deep-merge dei caps in `base.py:91`; ri-snapshot pesi PORT06, confermare SH totale=0.0588, sum=1.0, nessuno sleeve affamato. Verificare contro il backtest canonico (FULL 6.43/OOS 8.58). Questo dimezza l'esposizione SH01-no-SL già colpito dalla coda.
|
||||
2. **Giorno 1-2 — TR01 fee 2x + forming-bar (TR01 e Pairs).** Fix puramente di parità/contabilità, nessun gate OOS necessario (avvicinano il live al backtest validato). Coprire il silent-return TSM01/Rotation con WARN.
|
||||
3. **Giorno 2-3 — disaster-bracket on-book + osservabilità outage.** Cablare `set_stop_loss` lontano (~−30%) sui 4 fade eseguiti; aggiungere alert su N poll falliti consecutivi con `real_in_position=True` e log del gap% al risveglio. Smoke testnet (€0). Pura assicurazione coda, 0 costo Sharpe.
|
||||
4. **Giorno 3 — osservabilità report** (TR01/ROT02/TSM01 in hourly_report) + smoke MR07 short-side TP-resting.
|
||||
|
||||
**Settimana 2 — ripristini di config validata, ognuno dietro il gate PORT06/OOS:**
|
||||
|
||||
5. **Giorno 4-6 — `trend_max=3.0` sulle 6 fade.** Implementare in `_defs.py`, poi **ri-eseguire il gate PORT06** (template `exit16_port06_impact.py`) misurando trend-ON+hurst+EXIT-16 vs attuale trend-OFF: deploy SOLO se Sharpe OOS non peggiora e DD scende (sovrapposizione hurst+trend va quantificata).
|
||||
6. **Giorno 6-8 — pos pairs per-famiglia.** Plumbing `SleeveSpec.position_size`; ri-eseguire `combine` a pos live (target 0.15-0.25); scegliere il punto sul trade-off DD/ritorno; deploy.
|
||||
7. **Giorno 8-10 — DIP01 EXIT-16+hurst.** Validare sul grid OOS proprio di DIP01 (famiglia honest, meccanismi tarati su fade) **con engine gap-aware**, poi gate PORT06. Deploy solo se passa entrambi.
|
||||
8. **Giorno 10-12 — SH01 ri-validazione train-window.** Ri-eseguire validazione con train cap ~8760 barre (regime live). Se l'edge sopravvive → tarare th/calibrazione su slice held-out; se non sopravvive → riconsiderare SH01 (NON ri-tunare il th a forza). **Mai impostare sl/sl_confirm_atr su SH.**
|
||||
|
||||
Filoni P2 (MR01 k ETH) e cleanup P3 in coda, opportunistici. Regola trasversale: i punti 1-4 sono fix di bug/parità e vanno per primi; 5-8 toccano il comportamento di trading e **nessuno va in produzione senza superare il gate OOS + PORT06** (precedente FR01: robusto individualmente ≠ migliora il portafoglio).
|
||||
@@ -1,49 +0,0 @@
|
||||
# 2026-06-07 — DIP01 EXIT-16: PROMOSSO (gate gap-aware, il più netto della serie)
|
||||
|
||||
Punto 9 della roadmap sweep: DIP01 era l'unico sleeve BTC con esecuzione REALE
|
||||
round-trip e girava ancora sul branch SL intrabar wick-sensitive. EXIT-16 era
|
||||
validato SOLO sulle fade: estensione a una strategia honest dietro doppio gate
|
||||
(grid proprio di DIP01 + PORT06), con engine GAP-AWARE come da lezione exit-lab.
|
||||
|
||||
## Metodo (`scripts/analysis/dip01_exit16_impact.py`)
|
||||
|
||||
- Parità con la equity canonica: corr **1.00000**, ret +322% identico.
|
||||
- **Engine gap-aware**: nel ramo orig lo SL filla a `worse(livello, open[j])` —
|
||||
l'engine canonico filla "al livello" anche su gap-through (54% dei casi per stop
|
||||
tight) e regalerebbe al ramo intrabar un vantaggio fittizio.
|
||||
- Grid 3×3×2 (z_in × sl_atr × max_bars) su BTC (deployato) ed ETH (robustezza);
|
||||
train (pre 2024-10-12) e OOS separati. Buffer plateau {0.4, 0.5, 0.75, 1.0}.
|
||||
- NB `hurst_max` NON valutato su DIP01: il gate trendmax dello stesso giorno ha
|
||||
mostrato che è ridondante-dannoso post-EXIT-16.
|
||||
|
||||
### Trappola di metodo trovata: l'ancora bfill di `_daily_equity`
|
||||
|
||||
La prima parità falliva (corr 0.9956, −16pp) con **engine identici** (662 trade,
|
||||
stessi return, stesso capitale finale). Causa: la convenzione canonica
|
||||
`_daily_equity` (serie a punti trade-exit → `reindex(IDX).ffill().bfill()`)
|
||||
**ancora il primo valore della finestra al PRIMO trade dentro IDX** (es. 942.54
|
||||
dopo le perdite di gennaio 2021), non al capitale portato avanti dall'ultimo trade
|
||||
del 2020 (979.23). Il mio replay hourly era più "corretto" ma per parità va
|
||||
replicata la convenzione. **Finding aperto**: questo bias tocca le metriche
|
||||
canoniche di TUTTI gli sleeve a punti-trade (honest/pairs/tsm) — l'ancoraggio
|
||||
distorce leggermente il punto di partenza della finestra. Da valutare a parte se
|
||||
correggerlo OVUNQUE in un colpo solo (cambierebbe i numeri canonici di riferimento).
|
||||
|
||||
## Risultati
|
||||
|
||||
- **Grid BTC: 36/36** (EXIT-16 ≥ orig gap-aware in train E OOS in tutte le 18
|
||||
celle). OOS Sharpe ~2-4x (cella canonica 1.47→3.48), DD giù in 14/18 celle.
|
||||
- **Grid ETH: 35/36** (unica eccezione la cella estrema z3.0/sl3.0/mb48, marginale).
|
||||
- **Plateau buffer piatto**: OOS DD 6.4% identico da 0.4 a 1.0; scelto 0.5 (== fade).
|
||||
- **PORT06**: FULL Sharpe 6.43→6.61, DD 3.96→3.58 | OOS Sharpe 8.58→8.77, DD
|
||||
1.36→1.34. Migliora tutto. **PROMOSSO**.
|
||||
|
||||
È la 5ª conferma indipendente del principio EXIT-16: gli stop intrabar da wick
|
||||
sono falsi negativi per le strategie mean-reversion — l'overshoot che buca lo
|
||||
stop è il movimento che si sta comprando.
|
||||
|
||||
## Deploy
|
||||
|
||||
`_defs.py`: `"sl_confirm_atr": 0.5` nei params DIP01_BTC (il worker legge già il
|
||||
param — zero codice). Live path: TP intrabar invariato, SL solo su close confermato,
|
||||
disaster-bracket on-book già attivo per gli outage.
|
||||
@@ -1,46 +0,0 @@
|
||||
# 2026-06-07 — Gate position_size PAIRS: 0.5 → 0.20 (assicurazione, come il cap SHAPE)
|
||||
|
||||
Punto 8 della roadmap improvement-sweep: i pairs giravano col `position_size`
|
||||
GLOBALE 0.5 a leva 2 (esposizione 1.0 della fetta) mentre TUTTA la validazione PR01
|
||||
è a pos 0.15 lev 3 (esposizione 0.45) — ~2.2x il validato su una famiglia **senza
|
||||
stop** (exit solo |z|≤z_exit o max_bars). Scelta deliberata (commento yml) ma mai
|
||||
gateata. Evidenza live: ADA/ETH 2026-06-05 net −8.52% = −4.26% di sleeve in un trade.
|
||||
|
||||
## Metodo
|
||||
|
||||
`scripts/analysis/pairspos_port06_impact.py`: le 5 equity pairs ricostruite con
|
||||
`pairs_sim` alla **leva live (2x)** su griglia pos {0.50, 0.25, 0.20, 0.15},
|
||||
innestate nel PORT06 canonico (pesi cap PAIRS 0.33 + SHAPE 0.0588). Parità
|
||||
verificata: `pairs_sim(0.15, lev3)` == equity canoniche (corr 1.00000, 5/5).
|
||||
|
||||
## Risultati
|
||||
|
||||
| pos | esp. | FULL Sh / DD | CAGR | OOS Sh / DD | fam DD | worst pair DD grezzo |
|
||||
|---|---|---|---|---|---|---|
|
||||
| 0.50 (live) | 1.00 | 6.69 / 4.77% | 130% | 9.05 / 3.40% | 14.0% | ETH/BTC 78% |
|
||||
| 0.25 | 0.50 | 6.50 / 4.04% | 67% | 8.69 / 1.54% | 7.2% | 51% |
|
||||
| **0.20** | **0.40** | 6.33 / 3.90% | 57% | 8.43 / **1.26%** | 5.8% | 44% |
|
||||
| 0.15 | 0.30 | 6.03 / 3.78% | 47% | 7.99 / 1.33% | 4.3% | 35% |
|
||||
|
||||
Letture:
|
||||
- Il gate meccanico (OOS Sharpe non peggiora) **boccia ogni riduzione**: ovvio —
|
||||
ridurre l'esposizione di una famiglia che in-sample non è mai esplosa costa sempre
|
||||
Sharpe. Ma il +130% CAGR / +2.6e9% compounded di ETH/BTC a pos 0.5 è fantasia da
|
||||
compounding: dice solo che il tail event non è ancora successo in-sample.
|
||||
- **0.20 è il ginocchio**: OOS DD 1.26% batte anche 0.15 (1.33% — oltre il ginocchio
|
||||
si taglia ritorno senza guadagnare DD); esposizione 0.40 ≈ il validato 0.45.
|
||||
- Decisione di tipo assicurativo, identica al precedente cap SHAPE (adottato pagando
|
||||
−0.24 OOS Sharpe).
|
||||
|
||||
## Decisione (utente): pos PAIRS = 0.20
|
||||
|
||||
Implementazione:
|
||||
- `runner.pos_for_spec(sid, global_ps, family_overrides)` — override per-famiglia
|
||||
(chiave = `weighting.family_of`), plumbato in `build_worker_for`.
|
||||
- `portfolios.yml`: `position_size_family: {PAIRS: 0.20}` (globale 0.5 invariato
|
||||
per fade/dip/shape).
|
||||
- Test: `test_pos_for_spec_family_override`, `test_build_pairs_worker_position_size`.
|
||||
|
||||
Nota di transizione: la posizione LTC/ETH aperta al deploy (entrata a sizing 0.5)
|
||||
verrà chiusa col pos nuovo 0.20 → il pnl % sleeve di quel singolo trade è bookato
|
||||
alla taglia nuova (one-time, conservativo).
|
||||
@@ -1,51 +0,0 @@
|
||||
# 2026-06-07 — SH01 punto-10: il regime live (train 365g) NON è robusto → bootstrap full-history
|
||||
|
||||
Punto 10 della roadmap sweep: ri-validare SH01 col train-window del regime live
|
||||
(~8760 barre, il `_ML_LOOKBACK_DAYS=365` del runner) invece dell'expanding
|
||||
full-history usato da tutta la validazione storica.
|
||||
|
||||
## Ri-validazione (`scripts/analysis/sh01_trainwindow_validate.py`)
|
||||
|
||||
`ml_wf_entries(train_window=...)` rolling su storia piena ≈ il regime live.
|
||||
Protocollo explore_lab (FULL / OOS 30% / sweep fee / anni positivi), W24 H12 th0.58.
|
||||
|
||||
| BTC train | trade-rate | FULL / OOS | Sharpe | fee 0.2%: FULL/OOS | anni+ | robusto |
|
||||
|---|---|---|---|---|---|---|
|
||||
| 8760 (live) | **21.7%** | +82 / +74 | 1.31 | **−42** / +20 | 6/9 | ❌ |
|
||||
| 17520 (2y) | 15.4% | +166 / +96 | 2.05 | +9 / +47 | 6/9 | ❌ |
|
||||
| 26280 (3y) | 11.8% | +348 / +95 | 3.09 | +109 / +61 | 7/9 | ❌ |
|
||||
| EXPANDING | 9.8% | +219 / +42 | 2.72 | +60 / +26 | 8/9 | ✅ |
|
||||
|
||||
ETH a tw=8760: **FULL −33%, Sharpe −0.02** (lancio di moneta che paga fee).
|
||||
|
||||
Conferme: (a) la diagnosi del sweep era esatta (trade-rate 22-26% live vs 10%
|
||||
validato — soglia inerte per over-confidence su train piccolo); (b) la
|
||||
progressione è MONOTONA: l'edge di SH01 *è* la memoria lunga; (c) lo sweep della
|
||||
soglia nel regime corto dà risultati instabili e incoerenti fra asset → ri-tunare
|
||||
th sarebbe curve-fitting sul rumore di calibrazione (come da warning del piano).
|
||||
|
||||
## Decisione (utente): bootstrap full-history
|
||||
|
||||
Ripristinare in live ESATTAMENTE il regime validato (expanding full-history):
|
||||
|
||||
1. **`ml_wf_entries(last_block_only=True)`** — fitta/predice SOLO l'ultimo blocco
|
||||
del walk-forward. I confini dei blocchi sono deterministici (start + k·retrain)
|
||||
e al worker servono solo i segnali recenti → le entries dell'ultimo blocco sono
|
||||
**identiche per costruzione** al tail del WF completo (parity test esatto in
|
||||
`tests/portfolio/test_sh01_last_block.py`). Costo live: **0.6 s/tick** su 73k
|
||||
barre (1 fit LogReg) vs ~140 fit del WF completo.
|
||||
2. **Bootstrap storia nel runner**: per gli sleeve `ml` il tick riceve
|
||||
`concat(parquet_locale < feed_start, feed_live)` (`runner._with_history`).
|
||||
Gap-guard: se il parquet è stantio oltre il lookback del feed → solo feed +
|
||||
WARN una-tantum (meglio il regime corto dichiarato che una serie col buco).
|
||||
Manutenzione: tenere fresco il parquet con `download_all()` (oggi al 2026-05-28,
|
||||
il feed copre 365g → margine ~11 mesi).
|
||||
3. `_defs.py`: `params={"last_block_only": True}` sugli sleeve SHAPE (solo path
|
||||
live; il backtest canonico resta WF completo).
|
||||
|
||||
Effetto atteso live: trade-rate SH01 da ~25% a ~10% delle barre, selettività
|
||||
della soglia ripristinata, WR atteso ≈ validazione (acc OOS ~56% BTC).
|
||||
Il monitor naturale è il report orario (SH01 farà MENO trade).
|
||||
|
||||
Nota: `_ML_LOOKBACK_DAYS` resta 365 (il feed serve comunque per le barre recenti
|
||||
e come fallback se il parquet è stantio).
|
||||
@@ -1,101 +0,0 @@
|
||||
# 2026-06-07 — Implementazione fix improvement-sweep (P0 + punti 2-6, settimana 1)
|
||||
|
||||
Implementati e deployati i fix "settimana 1" del piano dello sweep 2026-06-06
|
||||
(tutti fix di parità/protezione/osservabilità, nessun cambio di strategia → nessun
|
||||
gate OOS richiesto). Versioni: v1.1.3 (punti 1-4), v1.1.4 (punti 5-6).
|
||||
|
||||
## P0 — cap SHAPE 0.0588 ripristinato (v1.1.3)
|
||||
|
||||
`portfolios.yml` ridichiara il dict caps COMPLETO `{PAIRS: 0.33, SHAPE: 0.0588}`
|
||||
(l'override sostituisce interamente i caps di `_defs.py` via setattr in
|
||||
`base.py:load_active_portfolio` — footgun ora commentato nel yml). Verificato live
|
||||
post-restart: SH_BTC+SH_ETH = 0.0588 totale (prima 0.1176 = 2x intended), non-cappati
|
||||
risaliti a 0.0647, sum = 1.0 — parità col backtest canonico (FULL 6.43 / OOS 8.58).
|
||||
|
||||
## Punti 2-4 — parità worker multi-asset (v1.1.3)
|
||||
|
||||
- **TR01 fee × leva**: `POS · LEV · fee_rt/2` per flip come il reference
|
||||
`honest_improve2._tr_basket_daily:150` (prima sotto-caricata 2x).
|
||||
- **TR01 forming-bar**: crossover EMA E booking del return solo su barre 4h COMPLETE
|
||||
(riga -1 = candela in corso finché non è trascorsa la sua durata, pattern EXIT-16).
|
||||
Evidenza live che non può più ripetersi: flip SOL 0→1→0 in 59min stessa finestra 4h.
|
||||
- **PairsWorker forming-bar**: entry ED exit sul close di barra COMPLETA, come il
|
||||
backtest `pairs_research` (close settled).
|
||||
- **TSM01/ROT02 silent-return**: WARN log + Telegram `PANEL_SHORT` quando il panel
|
||||
inner-join è sotto il lookback (helper condiviso `_warn_panel_short` in
|
||||
rotation_worker), gated su "era già operativo", una notifica per episodio.
|
||||
|
||||
Verifiche: 72 test (7 nuovi), `validate_worker_pairs` ESATTO, `validate_honest_workers`
|
||||
invariato. **Nota onesta**: TR01 replay worker −44% vs reference +42% è IDENTICO
|
||||
pre/post fix → divergenza di convenzione pre-esistente (capitale-unico con
|
||||
`mean(rets)` solo sugli asset in posizione vs media-equity 1/N del reference).
|
||||
Da rivisitare a parte: "stesso ordine di grandezza" oggi non regge più.
|
||||
|
||||
## Punto 5 — disaster-bracket on-book + alert outage (v1.1.4)
|
||||
|
||||
Durante un outage (poll-loop in except) le posizioni REALI restavano senza stop sul
|
||||
book e senza valutazione exit. Ora:
|
||||
|
||||
- **`ExecutionClient.place_disaster_sl`**: STOP_MARKET reduce-only a ~−30%
|
||||
dall'ingresso (trigger sul mark), piazzato a ogni REAL_OPEN sui fade eseguiti
|
||||
(MR01/MR02/MR07/DIP01) e cancellato in `_real_close` (prima del TP-reconcile).
|
||||
In operatività normale non scatta mai → 0 costo Sharpe; nei crash il fill è al
|
||||
gap (cappa la coda, non la elimina). Config: `overrides.execution.disaster_sl_pct`
|
||||
(default 0.30, 0 = off). `real_dsl_order_id` persistito (resume-safe).
|
||||
- **SCOPERTA**: il `set_stop_loss` di cerbero-mcp è un `private/edit` Deribit (solo
|
||||
ordini APERTI) → inutilizzabile su market già fillati; il bracket va piazzato come
|
||||
trigger order autonomo via `place_order(type="stop_market")` (già supportato).
|
||||
- **Semantica cancel trigger order** (verificata su testnet): la cancel risponde con
|
||||
lo stato AL MOMENTO della cancel (`untriggered` = successo; il re-cancel dà
|
||||
`order_not_found`); `error` = non più in book (probabile trigger scattato → il
|
||||
market a valle filla 0 e REAL_CLOSE esce verified=False).
|
||||
- **Alert `FEED_OUTAGE`**: dopo 5 poll falliti consecutivi (~5 min) Telegram con
|
||||
l'elenco delle posizioni reali aperte; notifica di ripresa con durata.
|
||||
|
||||
Smoke testnet (`live_shadow_smoke.py`, esteso): 4 scenari long+short — il path
|
||||
**short-side TP-resting** (BUY limit reduce-only) non era MAI stato esercitato.
|
||||
Tutti verdi: resting/cross-immediato due lati, DSL piazzato/cancellato (verificato
|
||||
zero ordini orfani sul book), conto flat a fine smoke.
|
||||
|
||||
## Punto 6 — osservabilità multi-asset (v1.1.4)
|
||||
|
||||
- `in_position` aggiunto ai `_save()` di TR01/ROT02/TSM01.
|
||||
- `hourly_report`: nuova sezione **MULTI-ASSET** (book corrente | ultimo flip |
|
||||
freschezza status) — prima i 3 worker erano invisibili nel report (collect()
|
||||
filtra su event/in_position che non emettevano): impossibile distinguere
|
||||
"flat/risk-off by-design" da "wiring rotto". I multi-asset sono esclusi dalla
|
||||
tabella IN CORSO (assume entry/bars single-leg).
|
||||
|
||||
## Code review multi-agente del giorno stesso (v1.1.7)
|
||||
|
||||
Review a 7 angoli su `8c4e1cd..HEAD` + check trades live. Il candidato top dei finder
|
||||
("stop_market senza trigger") è REFUTATO: cerbero-mcp traduce `price→trigger_price +
|
||||
trigger=mark_price` e in produzione 2 DSL erano armati + 1 ciclo completo pulito.
|
||||
Quattro fix applicati:
|
||||
|
||||
1. **Alert `REAL_DIVERGENCE`** (|slippage sim/reale| ≥ 100bps a open/close). Scoperta
|
||||
dal check trades: alle 10:37 uno **spike print testnet** (candela 10:00 H=65618 con
|
||||
O/C~62400) ha fatto shortare alle 3 fade BTC un close fantasma a 65266.5 — il reale
|
||||
ha fillato correttamente a ~62395 (−440bps) ma il sim ha bookato +2.26 mai esistiti
|
||||
(MR07 reale −0.13). Prima passava in silenzio.
|
||||
2. **`FEED_OUTAGE` anche su feed degradato senza eccezione** (HTTP 200 con candles
|
||||
vuote → i worker saltavano il tick in silenzio e lo streak restava 0). Helper unico
|
||||
`_outage_tick` (fix anche dell'incoerenza chiavi minuti/durata_min).
|
||||
3. **`src/live/bars.py`**: detection forming-bar UNIFICATA (era copiata in 4 punti,
|
||||
con `_check_stale_feed` che hardcodava 1h). È l'invariante di sicurezza di EXIT-16:
|
||||
ora vive in un posto solo, testato (`test_bars.py`).
|
||||
4. **DSL cancel hardening**: retry su errore transitorio + alert Telegram
|
||||
`REAL_DSL_CANCEL_FAIL` se lo stop resta forse ORFANO sul book (prima l'id veniva
|
||||
dimenticato in silenzio → lo stop stantio poteva colpire la posizione successiva);
|
||||
`order_not_found` = probabile trigger durante outage → solo log (il close a valle
|
||||
esce già verified=False). Test con executor finto (`test_real_close_dsl.py`).
|
||||
|
||||
Finding noti NON ancora fixati (in coda): ROT02/TSM01 valutano la candela 1d in
|
||||
formazione al primo poll dopo mezzanotte (stessa classe del fix TR01/Pairs, pre-esistente);
|
||||
engine dei gate copiato fra i 3 script `*_port06_impact.py`; epoche hourly_report hardcoded.
|
||||
|
||||
## Resta in roadmap (settimana 2, OGNUNO dietro gate PORT06/OOS)
|
||||
|
||||
trend_max=3.0 sulle 6 fade → pos pairs 0.15-0.25 per-famiglia → DIP01 EXIT-16
|
||||
(validazione gap-aware) → SH01 ri-validazione train-window ~8760 barre.
|
||||
Follow-up tecnico: divergenza convenzione TR01 worker vs reference (sopra).
|
||||
@@ -1,64 +0,0 @@
|
||||
# 2026-06-07 — Gate trend_max sulle fade live: BOCCIATA l'aggiunta, PROMOSSO lo swap hurst→trend
|
||||
|
||||
Punto 7 della roadmap improvement-sweep: ripristinare `trend_max=3.0`/`ema_long=200`
|
||||
sulle 6 fade live (ON nel backtest canonico, OFF in produzione). Il piano imponeva il
|
||||
gate PORT06 perché hurst e trend si sovrappongono. Esito sorprendente ma coerente.
|
||||
|
||||
## Metodo
|
||||
|
||||
`scripts/analysis/trendmax_port06_impact.py` — engine riusato da `exit16_port06_impact`
|
||||
(replay esatto del path canonico, parità verificata: corr 1.00000 e diff 0.00% su tutte
|
||||
e 6 le fade) + maschera Hurst IDENTICA al live (`fade_base.hurst_skip_mask`, close-only,
|
||||
w=100 step=6 — non la cache regime_lab). Tutte le varianti girano sul **path live**
|
||||
(EXIT-16 close-confirm 0.5 attivo); PORT06 con pesi cap canonici (PAIRS 0.33,
|
||||
SHAPE 0.0588), OOS da 2024-10-12.
|
||||
|
||||
Nota di metodo: il test PORT06 del loss-guard Hurst (`fade_lossguard_port_test`,
|
||||
2026-06-02) era su entries GIÀ trend-filtrate E sull'engine PRE-EXIT-16 (SL intrabar).
|
||||
La config live reale (hurst senza trend, con EXIT-16) non era MAI stata gateata.
|
||||
|
||||
## Risultati (PORT06, fade in path live EXIT-16)
|
||||
|
||||
| Variante | FULL Sh | FULL DD | FULL CAGR | OOS Sh | OOS DD | OOS CAGR |
|
||||
|---|---|---|---|---|---|---|
|
||||
| LIVE (hurst, no trend) | 7.23 | 2.68% | 68% | 9.35 | 1.68% | 92% |
|
||||
| CANDIDATO (hurst+trend) | 7.11 | 2.06% | 59% | 9.36 | 1.62% | 83% |
|
||||
| **TREND-ONLY 3.0** | 7.89 | 2.46% | 82% | **9.91** | **1.20%** | 103% |
|
||||
| NESSUNO (solo EXIT-16) | **8.07** | 3.35% | **105%** | 9.72 | 1.38% | 119% |
|
||||
| TREND-2.5 | 7.75 | 2.46% | 76% | 9.76 | 1.20% | 96% |
|
||||
| TREND-3.5 | 7.87 | 2.46% | 84% | 9.64 | 1.20% | 103% |
|
||||
|
||||
## Letture
|
||||
|
||||
1. **CANDIDATO BOCCIATO** (gate formale): il DD scende (2.68→2.06) ma FULL Sharpe
|
||||
−0.12 e CAGR −9pp — over-filtering, i due filtri tagliano lo stesso regime
|
||||
(n trade −50%, es. MR02_ETH 911→436).
|
||||
2. **Il loss-guard Hurst è ridondante-dannoso post-EXIT-16**: NESSUNO batte LIVE su
|
||||
Sharpe e ritorno ovunque. Spiegazione meccanica: hurst evitava i regimi stop-heavy
|
||||
saltando gli ingressi; EXIT-16 ha eliminato i wick-stop alla radice → gli ingressi
|
||||
che hurst salta sono in maggioranza tornati vincenti. Il 66% delle barre è oltre
|
||||
soglia hurst → il filtro toglieva metà dell'esposizione per un beneficio che ormai
|
||||
non c'è.
|
||||
3. **TREND-ONLY domina LIVE su tutte e 4 le metriche** ed è ESATTAMENTE la config che
|
||||
la ricerca EXIT-16 del 2026-06-04 aveva promosso (entries trend-filtrate, no hurst:
|
||||
FULL 7.84/2.60, OOS 10.06/1.15 — i 7.89/2.46 e 9.91/1.20 di oggi combaciano al
|
||||
netto di refresh dati e cap SHAPE). Il live non aveva mai eseguito quella config.
|
||||
4. **Plateau robusto**: trend_max 2.5/3.0/3.5 quasi indistinguibili (OOS DD 1.20
|
||||
identico su tutte) → non è una soglia tunata.
|
||||
5. Il trend filter vs NESSUNO è un trade-off deliberato: −23pp CAGR FULL per
|
||||
FULL DD 3.35→2.46 e OOS Sharpe 9.72→9.91. Coerente con la filosofia del progetto
|
||||
(DD control > ritorno marginale).
|
||||
|
||||
## Decisione (utente, 2026-06-07)
|
||||
|
||||
**SWAP hurst→trend nelle 6 fade live** (`_defs.py`): `trend_max=3.0, ema_long=200`,
|
||||
`hurst_max` rimosso. `hurst_skip_mask` resta in `fade_base` (param opzionale).
|
||||
Monitor live aggiornato: `hourly_report` ora traccia lo stop-rate per epoca
|
||||
PRE (nessun filtro) → HURST → TREND, verdetto a n≥30 nell'epoca TREND.
|
||||
|
||||
## Lezione
|
||||
|
||||
Ogni meccanismo anti-perdite va RI-gateato quando cambia l'exit engine: hurst era
|
||||
genuinamente il migliore sull'engine a SL intrabar (unico su ~10 candidati), ma
|
||||
EXIT-16 ne ha assorbito il lavoro. I filtri si valutano sul path live corrente,
|
||||
non sui numeri storici di promozione.
|
||||
@@ -1,76 +0,0 @@
|
||||
# 2026-06-08 — Ricerca multi-agente: dispersion / correlation index (165 agenti)
|
||||
|
||||
Workflow `dispersion-correlation-research` (run wf_72edef49-6d9): 60 celle esplorate
|
||||
(15 famiglie × 4 finestre di correlazione W=24/72/168/336), 165 agenti totali, ~10M
|
||||
token, verifica avversariale a 2 skeptic su ogni candidato robusto + sintesi.
|
||||
|
||||
Infrastruttura riusabile: `scripts/analysis/dispersion_lab.py` — feature REALIZED
|
||||
causali (avg pairwise correlation, dispersione cross-sectional, beta vs indice EW,
|
||||
componente idiosincratica `rel_A = ret_A − ret_idx`), universo 8-asset, finestra
|
||||
comune dal 2022-07-22, cache su disco, no-look-ahead verificato. NB: **niente
|
||||
implied** (opzioni non backtestabili — stesso muro ARGO/GEX).
|
||||
|
||||
## Esito: 2 edge confermati su 60, 13 famiglie su 15 sono RUMORE
|
||||
|
||||
Nessun look-ahead "hard" stile-squeeze (le feature hanno retto la perturbazione del
|
||||
futuro ovunque). Il fallimento dominante è **overfit/concentrazione di regime**, non
|
||||
leakage. Tre pattern ricorrenti di falso positivo:
|
||||
1. **OOS circolare**: le feature esistono solo dal 2022-07 → lo split OOS (ultimo 30%)
|
||||
cade nel bull/calm 2024-25 (il regime che il progetto documenta come ottimistico
|
||||
~50%); FULL≈OOS non era robustezza ma "quasi tutti i trade in OOS".
|
||||
2. **Il gate corr/disp non è quasi mai load-bearing**: in ablazione, togliere il gate
|
||||
spesso MIGLIORA i numeri → è un throttle di esposizione, non alpha (e Hurst-guard +
|
||||
EXIT-16 fanno già quel lavoro).
|
||||
3. **Riconferma del prior**: l'edge è sempre mean-reversion del residuo, mai
|
||||
momentum/continuation/breakout cross-sectional.
|
||||
|
||||
## I 2 edge reali (entrambi fade del residuo idiosincratico)
|
||||
|
||||
- **`index_comp_disp` W=168 (BTC)** — il vero "dispersion-trading realizzato": fade
|
||||
della componente idiosincratica estrema verso l'indice, **gated da alta dispersione**
|
||||
(`disp_168 ≥ quantile 0.7`). rel_len=12, z_thr=1.5, TP=1.0·ATR, SL=1.5·ATR, mb=24.
|
||||
FULL +63% / OOS +36% (fee0.2% +23%), win 66%, Sharpe 2.7-3.0, DD 7-9%, 5/5 anni.
|
||||
È l'UNICA famiglia dove il gate dispersione fa davvero qualcosa.
|
||||
- **`rel_idio_fade` W=24** — fade dello z-score di `rel_A` su 24h, exit a tempo (no
|
||||
TP/SL). Cella più pulita BTC z3.0 mb12: win 58.5%, Sharpe 4.40, DD 7%, OOS +98%.
|
||||
Più forte ma è quasi MR07 ri-etichettata in chiave cross-sectional.
|
||||
|
||||
Script preservati: `scripts/analysis/dispersion_edges/{index_comp_disp,rel_idio_fade}.py`.
|
||||
|
||||
## Raccomandazione: bassa priorità
|
||||
|
||||
**Entrambi sono fade-BTC mean-reversion → sovrapposti alle fade MR già deployate.**
|
||||
P(migliora PORT06): ~20-25% per index_comp_disp, ~15-20% per rel_idio_fade. Vale la
|
||||
**lezione FR01** (robusto-individualmente ≠ migliora-il-portafoglio: FR01 era robusto
|
||||
e causale ma diluiva PORT06 OOS Sharpe 8.89→8.72). index_comp_disp ha il profilo trade
|
||||
più distinto (win 66%, hold corto, TP vicino) → è l'unico che merita eventualmente un
|
||||
gate `combine_v2`/PORT06 formale, misurando corr col MASTER e ΔSharpe/ΔDD. Se non
|
||||
decorrela, scartare.
|
||||
|
||||
**13 famiglie rumore** (record in `_disp_scratch/`, gitignored): corr_gate_fade/pairs,
|
||||
disp_xs_reversal/momentum, corr_spike_btc, corr_meanrev, beta_disp, disp_regime_rot,
|
||||
corr_vol_interact, leadlag_corr, corr_trend, disp_compression_breakout, corr_disp_combo
|
||||
— tutte MR/fade ri-etichettate, concentrazione 2024-25, o artefatti di feed morto
|
||||
(ADA/LTC 97% candele flat). disp_compression_breakout riconferma la lezione squeeze
|
||||
(i breakout rientrano).
|
||||
|
||||
**Conclusione onesta: nessun nuovo motore di ritorno.** Il dispersion-trading realizzato
|
||||
funziona solo come l'ennesima faccia della mean-reversion già sfruttata.
|
||||
|
||||
## Gate PORT06 del candidato n.1 (2026-06-08) — PROMOSSO MARGINALE, NON deployato
|
||||
|
||||
`scripts/analysis/dispersion_edges/gate_index_comp_disp.py` (config W=168: rel_len=12,
|
||||
z_win=336, z_thr=1.5, disp_q=0.7, TP=1.0ATR, SL=1.5ATR, mb=24; equity daily innestata
|
||||
come 18° sleeve, pesi cap):
|
||||
|
||||
- **Sorpresa positiva**: decorrela DAVVERO. corr daily col candidato: MR01_BTC +0.01,
|
||||
MR02_BTC +0.05, MR07_BTC +0.06, DIP01_BTC +0.02, MASTER(EW) +0.06. Il timore di
|
||||
ridondanza con le fade BTC era infondato (gate dispersione + TP vicino = profilo trade
|
||||
distinto). Standalone 311 trade, FULL +67% / OOS +30%.
|
||||
- **Ma beneficio nel rumore**: PORT06 BASE→+DISP: FULL Sharpe 6.43→6.47, FULL DD
|
||||
3.96→3.73 (migliora), **OOS Sharpe 8.58→8.56 (−0.01), OOS DD 1.36→1.40 (+0.04)** —
|
||||
l'OOS è PIATTO. Passa il gate tecnico ma il guadagno è solo nel FULL (regime storico).
|
||||
- **Decisione (utente): documenta e rimanda.** NON deployato — wiring (nuova Strategy+worker,
|
||||
famiglia DISP, peso cap) + resterebbe simulato (no executor), per un beneficio OOS nullo.
|
||||
Gate script committato e pronto: riprendere SOLO se si costruisce una famiglia DISP più
|
||||
ampia (più asset/sleeve) che insieme sposti l'OOS. Esito ~20% previsto, confermato.
|
||||
@@ -1,130 +0,0 @@
|
||||
# 2026-06-08 — Ricerca sostituto/miglioria a MR02/ETH (127 strategie + opzioni)
|
||||
|
||||
## Contesto
|
||||
MR02/ETH è lo sleeve a DD più alto della famiglia fade ed è il maggior drag
|
||||
dell'esecuzione reale (testnet: −19€ su 7 trade, 0 win, faded un downtrend −14%
|
||||
in long poi shortato il rimbalzo — whipsaw classico). Obiettivo: trovare un
|
||||
sostituto o una miglioria con ≥100 agenti su strategie differenti, metodologia
|
||||
onesta (ingresso eseguibile, fee 0.10% RT, OOS, gate PORT06).
|
||||
|
||||
## Cosa è stato fatto
|
||||
- **Workflow 1 — 109 strategie ETH distinte** (`mr02eth_search.workflow.js`):
|
||||
gated-fade, mean-reversion alternative, exit, trend-following, volatilità,
|
||||
cross-asset, ML/shape, microstruttura, statistico-robusto. Harness onesto
|
||||
`explore_lab`. Poi **verifica avversariale** dei top-24 (audit look-ahead +
|
||||
re-implementazione indipendente + robustezza). → 26 survivor, **6 confermati**.
|
||||
- **Workflow 2 — 18 overlay di OPZIONI** (`mr02eth_options.workflow.js`) +
|
||||
sintesi con audit crash reali. Harness nuovo `option_overlay_lab.py`: opzioni
|
||||
prezzate Black-Scholes sulla **DVOL** reale di Deribit (storica/gratuita,
|
||||
`data/regime/eth_dvol.parquet`), premio dedotto, ipotesi **conservative**
|
||||
(skew_mult sui comprati, uscita anticipata solo a intrinseco).
|
||||
- **Gate PORT06** (`mr02eth_port06_gate.py`): swap di MR02_ETH col candidato,
|
||||
equity giornaliera su IDX 2021-2026, ri-misura FULL+OOS Sharpe/DD (cap
|
||||
weighting). Sanity check: MR02 ricostruito col mio engine == canonico (Δ 0.00).
|
||||
|
||||
## Risultato (gate PORT06; baseline canonico FULL 6.43/3.96, OOS 8.58/1.36)
|
||||
| variante (swap MR02/ETH) | FULL Sh | FULL DD | OOS Sh | OOS DD |
|
||||
|---|---|---|---|---|
|
||||
| EXIT-16 (config LIVE) | 6.73 | 3.67 | 8.80 | 1.23 |
|
||||
| no-SL nudo | 6.76 | 3.68 | 8.87 | 1.23 |
|
||||
| no-SL + put/call 10% OTM | 6.78 | 3.64 | 8.86 | 1.23 |
|
||||
| varratio_gate (PROMOSSO vs canonico) | 6.41 | 3.73 | 8.53 | 1.36 |
|
||||
| choppiness_donch | 6.37 | 3.35 | 8.47 | 1.32 |
|
||||
| vrp_neg_dvol_low | 6.36 | 3.22 | 8.37 | 1.43 |
|
||||
|
||||
## MIGLIORIA TROVATA (gate vs LIVE EXIT-16, non vs canonico)
|
||||
Riferimento onesto = config LIVE EXIT-16 (FULL 6.73/3.67 — OOS 8.80/1.23), non
|
||||
l'intrabar-SL canonico che nessuno gira.
|
||||
|
||||
| sleeve ETH | ΔFULL Sh | ΔFULL DD | ΔOOS Sh | ΔOOS DD | esito |
|
||||
|---|---|---|---|---|---|
|
||||
| **no-SL + put/call 10% OTM** | **+0.05** | **−0.03** | **+0.06** | 0.00 | ✅ MIGLIORIA deployabile |
|
||||
| no-SL nudo | +0.04 | +0.02 | +0.07 | 0.00 | ✅ migliora ma sl=0 NON deployabile |
|
||||
| EXIT16 + put10 | −0.01 | +0.03 | 0.00 | 0.00 | = pari (assicurazione gratis) |
|
||||
| varratio / vrp / chop / blend | negativi | | | | peggiorano vs EXIT-16 |
|
||||
|
||||
**La miglioria = MR02/ETH no-SL + floor a opzioni 10% OTM** (put sui long, call
|
||||
sugli short). Batte il live EXIT-16 in modo PARETO su 3/4 metriche PORT06 (4ª
|
||||
piatta). Meccanismo: **rimuovere lo stop** (intrabar/close-confirm su una fade
|
||||
mean-reverting sono falsi negativi — overshoot che rientra) e dare la funzione
|
||||
dello stop (cap della catastrofe) a un'**opzione comprata** = protezione a
|
||||
rischio-definito SENZA il costo whipsaw/falso-stop. Standalone il salto è grande
|
||||
(Sharpe 8.45→12.14, OOS DD 13%→7%); a portafoglio è modesto (+0.05/+0.06 Sharpe)
|
||||
perché è 1 sleeve su 17, ma è un miglioramento MISURATO e verificato (soglia
|
||||
gate +0.03, ottenuto +0.05/+0.06), non rumore.
|
||||
|
||||
## Conclusioni (oneste)
|
||||
1. **Sostituti/blend: tutti peggiorano vs il live EXIT-16.** I candidati gated
|
||||
(varratio/vrp/choppiness) e i blend within-sleeve battono solo lo strawman
|
||||
canonico, non il live; le loro basse esposizioni diluiscono il motore di
|
||||
ritorno (Sharpe −0.08/−0.44). Lo Sharpe ~20 nell'harness era artefatto di
|
||||
`sqrt(N_trade)` (onesto ~4.3). → **non sostituire né blendare.**
|
||||
2. **L'unica miglioria è la coppia no-SL + opzione.** Il no-SL recupera il drag
|
||||
dello stop; l'opzione cappa la coda da **gap-through** che EXIT-16 NON protegge
|
||||
(esce al close DOPO il buco → prende la perdita piena). Audit crash: FTX nov-22
|
||||
−48%→−30%, LUNA-era 2022-09 −63%→−31%, 2018/19 −65%→−30%. Premio ~break-even
|
||||
(paga 156% / incassa 149%). È ciò che rende deployabile il no-SL.
|
||||
|
||||
## Azione raccomandata
|
||||
- **Deployare MR02/ETH come no-SL + floor a opzioni 10% OTM** (put long / call
|
||||
short, per-trade o settimanale ammortizzato). Batte il live su 3/4 metriche +
|
||||
cappa esplicitamente la coda. **Prima del capitale**: validare prezzi/liquidità/
|
||||
skew per-strike REALI su Deribit testnet (qui pricing BS sintetico sulla DVOL =
|
||||
ATM-IV; stress skew ×1.5 gonfia il premio FULL ma l'OOS regge). Stesso muro
|
||||
non-backtestabile di ARGO/GEX sul per-strike, aggirato col proxy DVOL.
|
||||
- Step intermedio a costo zero: **aggiungere subito il floor opzione all'EXIT-16
|
||||
live** (= "pari" sui numeri, ma assicurazione gratis sul gap-through) mentre si
|
||||
valida la transizione a no-SL.
|
||||
|
||||
## Addendum 2026-06-09 — validazione su PREZZI REALI + integrazione cerbero-bite
|
||||
- Probe live Deribit mainnet (singolo snapshot): sembrava skew ×1.6 e liquidità
|
||||
pessima sul 10% OTM a 1g → l'overlay per-trade pareva bocciato.
|
||||
- **cerbero-bite** (container accanto) ha però **lo storico per-strike reale** in
|
||||
`option_chain_snapshots` (SQLite, dal 2026-05-01, ~110k righe/asset, bid/ask/IV/
|
||||
greche/OI, cadenza ~12min). Importato in `data/options/` via `options_fetcher.py`;
|
||||
loader `options_chain.py` (skew_curve/premium_levels/quote causale).
|
||||
- **Correzione dai dati reali (5.5 settimane):** skew put 10% OTM = **×1.1** (liquido,
|
||||
spread ~7%) — il ×1.6 del probe era un artefatto del deep-OTM a 1g illiquido. Premio
|
||||
reale 10% OTM ≈ **1.0%/mese**. → la miglioria no-SL+opzione **regge** sui prezzi veri.
|
||||
- **MA vincolo strutturale reale:** gli strike **10% OTM a 24h NON esistono** (n=0 in 5.5
|
||||
settimane; Deribit lista solo near-ATM sui tenor corti). L'overlay **per-trade a 24h è
|
||||
infattibile**; l'unica struttura eseguibile è una **put settimanale/mensile standing**
|
||||
(catastrofe-cap di sleeve), da gateare a parte coi premi reali.
|
||||
- **Infrastruttura sbloccata:** il muro ARGO/GEX ("opzioni non-backtestabili") è caduto
|
||||
per il periodo recente — d'ora in poi le tesi opzioni si validano su prezzi VERI.
|
||||
Importato anche il pannello `market_snapshots` (spot/VRP/funding/**net-GEX dealer**/
|
||||
gamma-flip/liquidation, dal 2026-03-26) → `data/options/`, loader `options_chain.load_market`.
|
||||
|
||||
## Addendum 2 — gate del COLLAR standing (catastrophe-cap auto-finanziato) — NO-GO
|
||||
Premi reali → collar = put −13% (1.0%/m) finanziata da call +10% (1.05%/m) ≈ premio netto 0.
|
||||
Gate PORT06 (`eth_collar_gate.py`, BS calibrato skew_put 1.12 / skew_call 1.0, sweep OTM/hedge_frac):
|
||||
- Il collar **PAGA nei crash** (ETH −40% dic-21 → +6.1%, −30% feb-25 → +6.6%): protezione reale.
|
||||
- MA **net-negativo a portafoglio**: taglia il FULL DD (−0.2/−0.3pp) ma **costa Sharpe** (FULL e OOS)
|
||||
e **ALZA l'OOS DD** (+0.18/+0.28pp) — nell'OOS (no crash profondo, qualche rally) la call corta
|
||||
perde e il premio erode. Peggiora il DD che doveva ridurre.
|
||||
- **Verdetto: il tail-hedge a opzioni NON conviene a PORT06** (né per-trade né collar). Strutturale:
|
||||
lo sleeve ETH pesa 6.5% → la **diversificazione è già la protezione di coda** (trade −65% =
|
||||
−4% aggregato). La cap auto-finanziata era giusta sul *costo* (~break-even) ma la protezione non
|
||||
vale il costo Sharpe/OOS-DD. Le opzioni si chiudono come **NO-GO empirico su prezzi reali**.
|
||||
|
||||
## Deploy della miglioria (2026-06-09): MR02/ETH stop-largo sl_atr 3.0
|
||||
Nessun SOSTITUTO batte il live; la MIGLIORIA deployabile e' allargare lo stop EXIT-16.
|
||||
Gate stop-width (EXIT-16 close-confirm, swap solo MR02_ETH):
|
||||
| sl_atr | FULL Sh | FULL DD | OOS Sh | OOS DD | worst-trade |
|
||||
|---|---|---|---|---|---|
|
||||
| 2.0 (LIVE) | 6.73 | 3.67 | 8.80 | 1.23 | -48% |
|
||||
| **3.0** | **6.77** | **3.30** | **8.82** | 1.23 | **-50%** |
|
||||
| 4.0 | 6.78 | 3.49 | 8.82 | 1.23 | -62% |
|
||||
| no-SL (sl=0) | 6.76 | 3.68 | 8.87 | 1.23 | -65% (vietato) |
|
||||
`sl_atr=3.0` domina il live (FULL DD -0.37pp, Sh +0.04/+0.02) e cattura il beneficio del no-SL
|
||||
(gli stop di meta'-discesa sono falsi negativi) MANTENENDO lo stop di catastrofe (worst -50%, non
|
||||
-65%) -> regola "mai sl=0" rispettata; 4.0 inizia a perdere la coda. Plateau 2.5-4.0 (tutti > live
|
||||
su Sharpe). Override SCOPED a MR02/ETH in `_defs.py` (`_fade_params`); gli altri 5 fade non
|
||||
ri-gateati -> invariati. 93/93 test passano. Deploy: `./scripts/deploy.sh` (cambio live).
|
||||
|
||||
## Artefatti riusabili
|
||||
- `scripts/analysis/option_overlay_lab.py` — overlay opzioni (pricing BS sintetico su DVOL).
|
||||
- `scripts/analysis/options_fetcher.py` — import storico opzioni reale da cerbero-bite → data/options/.
|
||||
- `scripts/analysis/options_chain.py` — loader + skew/premi reali + lookup causale (`OptionChain`).
|
||||
- `scripts/analysis/mr02eth_port06_gate.py` — gate swap-sleeve PORT06.
|
||||
- `scripts/analysis/mr02eth_search.workflow.js`, `mr02eth_options.workflow.js`.
|
||||
@@ -1,53 +0,0 @@
|
||||
# 2026-06-08 — Executor a 2 gambe per i pairs (PairsExecutionClient)
|
||||
|
||||
Implementato il pezzo di esecuzione reale più impegnativo rimasto: l'esecuzione
|
||||
shadow a 2 gambe per la famiglia PAIRS (29% del portafoglio, finora solo simulata).
|
||||
|
||||
## Cosa
|
||||
|
||||
- **`execution.PairsExecutionClient`**: compone l'`ExecutionClient` single-leg.
|
||||
- `open_pair(inst_a, inst_b, direction, notional)`: piazza le 2 gambe (long A/short B
|
||||
o viceversa) a market, verifica per-gamba sul trade; **LEG-RISK**: se UNA sola gamba
|
||||
filla → UNWIND (richiude la fillata reduce-only) per non restare direzionali →
|
||||
verified=False.
|
||||
- `close_pair(...)`: chiude entrambe reduce-only (solo `close_amount` della quota,
|
||||
MAI `close_position`), riconcilia fee/prezzi.
|
||||
- `register_contract`: fetch dinamico spec USDC da Deribit per strumenti non hardcodati.
|
||||
- Strumenti = lineari USDC (payoff lineare = matematica del backtest a 2 gambe).
|
||||
Aggiunti spec LTC/ADA/SOL_USDC (step 0.1/0.2/0.1).
|
||||
- **`PairsWorker` shadow**: ledger reale parallelo (`real_capital`, `real_dir`,
|
||||
`real_amount_a/b`, `real_entry_a/b`, `real_notional_a/b`, fee), persistito e resume-safe;
|
||||
`_real_open_pair`/`_real_close_pair` agganciati a `_open`/`_close`; PnL reale per gamba
|
||||
(dir A=+d, dir B=−d). Doppio arrotondamento → piccolo sbilanciamento notional, riportato.
|
||||
- **runner**: `pairs_executor` (PairsExecutionClient su stesso ExecutionClient dei fade),
|
||||
`_pairs_exec_for`, gate su `execution.pairs_enabled`. Config `portfolios.yml`:
|
||||
instruments estesi (LTC/ADA/SOL) + `pairs_enabled: false` (capability pronta, SPENTA).
|
||||
|
||||
## Validazione
|
||||
|
||||
- Test (executor finto): 92/92 — open/close a 2 gambe, **leg-risk unwind**, ledger reale
|
||||
persiste e resume.
|
||||
- **Smoke testnet end-to-end** (`live_pairs_smoke.py`, €0): open 2 gambe verificate
|
||||
(long ETH 0.011 @1666 / short BTC 0.0003 @63263, fee $0.019), close 2 gambe reduce-only,
|
||||
riconciliazione PnL reale −0.039 vs sim −0.036 (coerente), **conto flat dopo**.
|
||||
|
||||
## Incidente operativo (testnet, €0) — da ricordare
|
||||
|
||||
Durante la prima esecuzione, lo smoke è crashato (bug del test: prezzi sim=0 → divisione
|
||||
per zero nel ramo sim) lasciando una posizione aperta. Per pulirla ho usato a mano
|
||||
`ExecutionClient.close()` (= `close_position`) che **flatta l'intero strumento** → ho
|
||||
chiuso anche le 3 posizioni reali SHADOW dei fade del runner (BTC/ETH_USDC condivisi).
|
||||
Impatto: testnet, shadow (non guida le decisioni), €0; 3 worker fade con
|
||||
`real_in_position=True` su conto flat → si auto-riconciliano al prossimo close sim
|
||||
(close_amount su flat → verified=False, reset; "shadow pulito dalla prossima apertura").
|
||||
I TP resting erano già stati cancellati da close_position (cancel → order_not_found).
|
||||
|
||||
**Lezione (CLAUDE.md la documentava già)**: MAI `close_position` su strumenti condivisi.
|
||||
Fix permanente: lo smoke ora (a) usa solo `close_amount` della quota, (b) ABORTA se ci
|
||||
sono posizioni di produzione aperte sugli strumenti, (c) usa prezzi sim reali.
|
||||
|
||||
## Stato: PRONTO ma SPENTO (`pairs_enabled: false`)
|
||||
|
||||
L'executor è validato (test + smoke). NON attivato in produzione: accenderlo richiede
|
||||
una finestra a conto flat e un periodo di osservazione, dato il conto condiviso coi fade.
|
||||
Quando si accende: i 5 pairs eseguiranno reale a 2 gambe accanto al sim.
|
||||
@@ -1,42 +0,0 @@
|
||||
# 2026-06-08 — Portafoglio live REALE-only: i €2000 ai soli sleeve eseguiti
|
||||
|
||||
Decisione utente: il portafoglio live deve mostrare il **risultato reale puro**. I €2000
|
||||
si dividono SOLO tra i 14 sleeve che eseguono davvero (6 fade + DIP01 + 5 pairs + SH01);
|
||||
i 3 multi-asset (TR01/ROT02/TSM01), non eseguibili in reale (bloccati dal capitale),
|
||||
escono dal pool e girano **solo per statistica**.
|
||||
|
||||
## Implementazione (runner-level, non rompe le definizioni)
|
||||
|
||||
- `portfolios.yml`: `paper_sleeves: [TR01, ROT02, TSM01]`.
|
||||
- `runner`: separa `live_specs` (pool/pesi/ledger) da `paper_specs`. I paper:
|
||||
- capitale NOZIONALE fisso = `total_capital / N_sleeve_totali` (la fetta equal che
|
||||
avrebbero avuto), NON dal pool;
|
||||
- girano in `data/portfolio_paper_stats/` (binario separato);
|
||||
- ticcati per statistica ma MAI in `ledger.update_equity` → non toccano l'equity reale.
|
||||
- `hourly_report`: la sezione multi-asset ora legge `portfolio_paper_stats/` ed è
|
||||
etichettata "PAPER — solo statistica, FUORI dal conto reale".
|
||||
|
||||
## Pesi del portafoglio reale-only (14 sleeve, cap)
|
||||
|
||||
sum=1.0; non-cappati 0.0873 (erano 0.0647 su 17), PAIRS 0.33 (cap), SHAPE 0.0588 (cap,
|
||||
SH ciascuno 0.0294). Il cap SHAPE resta valido e protettivo anche su 14.
|
||||
|
||||
## Il costo, misurato e accettato
|
||||
|
||||
| | FULL Sh | FULL DD | OOS Sh | OOS DD |
|
||||
|---|---|---|---|---|
|
||||
| PORT06 completo (17, validato) | 6.43 | 3.96% | 8.58 | 1.36% |
|
||||
| **REALE-only (14, live ora)** | 6.49 | **5.34%** | 8.54 | **1.70%** |
|
||||
|
||||
Perdendo i 3 diversificatori PAPER (corr 0.07), il DD del portafoglio reale sale
|
||||
~3.96→5.34% FULL e 1.36→1.70% OOS, Sharpe sostanzialmente invariato. È il **prezzo di
|
||||
vedere il risultato reale puro** invece di una curva mista reale+paper: scelta
|
||||
consapevole dell'utente. I PAPER restano misurati per ri-integrarli quando saranno
|
||||
eseguibili (SH01 è già stato integrato oggi; i multi-asset attendono capitale ~€20k).
|
||||
|
||||
## Note di transizione
|
||||
|
||||
- Il ledger `PORT06` (code invariato) ora rappresenta i 14 reali: la curva equity ha
|
||||
una discontinuità di composizione da questo deploy (atteso).
|
||||
- I 3 paper ripartono puliti in `portfolio_paper_stats/` con capitale nozionale uniforme
|
||||
(statistica comparabile); i vecchi status in `portfolio_paper/` restano come storico.
|
||||
@@ -1,56 +0,0 @@
|
||||
# 2026-06-09 — Gioco "Blind Traders": 100 agenti ciechi
|
||||
|
||||
## Setup
|
||||
100 agenti LLM (haiku) ricevono due serie anonime **X** e **Y** — in realta'
|
||||
**BTC** e **ETH** 1h/15m/5m, mai etichettate — e devono proporre UNA regola che
|
||||
"anticipi" i movimenti per un PnL netto positivo (fee 0.10% RT) con **>=10
|
||||
trade/mese**. Non sanno cosa siano i dati. L'orchestratore (engine deterministico)
|
||||
valuta ogni strategia, assegna un punteggio su **PNL + %win**, da' **90 epoche di
|
||||
elaborazione** (hill-climb dei parametri) e **ogni 10 epoche blocca il 10% meno
|
||||
profittevole** -> restano i **10 piu' profittevoli**.
|
||||
|
||||
Infrastruttura in `scripts/games/`:
|
||||
- `engine.py` — dati anonimizzati, 6 famiglie segnale (zscore/breakout/ma_cross/
|
||||
rsi/momentum/pairs), backtester causale fee-aware, scoring (>=10 tpm o squalifica).
|
||||
- `agent_brief.py` — digest ANONIMO (stat aggregate + finestra normalizzata) + menu.
|
||||
- `arena.py` — torneo a **3 finestre**: TRAIN (hill-climb), VALID (cull+rank
|
||||
dell'orchestratore), TEST (OOS puro, mai ottimizzato). Anti-overfit.
|
||||
- `run_game.py` — carica le 100 spec degli agenti e lancia il torneo.
|
||||
|
||||
## Risultato emergente
|
||||
I 100 agenti ciechi, leggendo SOLO le statistiche anonime (autocorrelazione
|
||||
negativa, "after_big_move_continues_pct" ~30-40% => le mosse estreme rientrano),
|
||||
hanno **riscoperto da soli che il mercato e' mean-reverting**: 100/100 reversion,
|
||||
67 hanno scelto il detector pairs, 30 zscore. Esattamente la lezione storica del
|
||||
progetto (edge = reversione; pairs ETH/BTC il piu' robusto) — senza sapere che
|
||||
fosse crypto.
|
||||
|
||||
## Classifica finale (top 10) — tutti PAIRS su 15m
|
||||
Vincitore **agente #91** (15m, pairs market-neutral sul log-ratio X/Y):
|
||||
- TEST/OOS puro: **PnL +3126%**, **win 77%**, **108.9 trade/mese**, **Sharpe 20.3**
|
||||
- Full-period: PnL +8052%, win 70%, 94 tpm, Sharpe 12.2 (9604 trade)
|
||||
- params: lookback 66, entry 1.67σ, exit 1.0σ, max_bars 35
|
||||
- ipotesi (cieca): "Y altamente reversivo, X/Y log-ratio strong mean-reversion
|
||||
(-0.43 autocorr), bassa correlazione cross-asset -> pairs market-neutral".
|
||||
|
||||
Tutti i 10 finalisti: pairs 15m, TEST Sharpe medio 19.9, tpm 66-109 (>>10).
|
||||
|
||||
## Caveat onesti
|
||||
- Numeri OOS ottimistici: PnL additivo a notional fisso, **niente slippage sulle 2
|
||||
gambe**, finestra OOS calma, 15m molti trade. Coerente col caveat PR01 del
|
||||
progetto (Sharpe reale atteso ~4-5, non 20). Il valore del gioco e' il **metodo**
|
||||
(scoperta cieca + selezione anti-overfit), non il livello assoluto di Sharpe.
|
||||
- La convergenza su pairs conferma robustezza ma riduce la diversita': i 10 finalisti
|
||||
sono varianti della stessa idea (ETH/BTC spread). Per un portafoglio servirebbe
|
||||
diversificare (gia' fatto altrove: fade + honest + shape).
|
||||
|
||||
## Re-run "sobrio" con slippage (0.05%/lato)
|
||||
`GAME_SLIP=0.0005` -> i pairs pagano +0.20% RT extra (4 lati). Lo slippage spinge
|
||||
l'ottimizzatore verso **meno churn**: tpm dei finalisti 66-109 -> **40-47**, Sharpe
|
||||
top-10 ~20 -> ~13.5. Vincitore **#43** (15m pairs): TEST PnL **+2091%**, win 77%,
|
||||
**46.9 tpm**, Sharpe **15.6**. La gerarchia (pairs 15m domina) e la robustezza
|
||||
reggono lo stress; lo Sharpe reale atteso resta ~4-5 (OOS calmo + PnL additivo).
|
||||
Log: `data/games/game_slip.log`.
|
||||
|
||||
Artefatti: `data/games/tournament_result.json`, `data/games/specs/agent_*.json`,
|
||||
`engine.set_slippage()` (env `GAME_SLIP`).
|
||||
@@ -1,41 +0,0 @@
|
||||
# 2026-06-09 — Gioco "Blind Traders" sessione 2: timing diversi (30m/2h/4h)
|
||||
|
||||
Seconda sessione del gioco (vedi `2026-06-09-blind-traders-game.md`), stesso protocollo
|
||||
(100 agenti ciechi su BTC/ETH anonimi, scoring PNL+%win, ≥10 trade/mese, 90 epoche, cull
|
||||
10% ogni 10 epoche → 10 finalisti, split a 3 anti-overfit) ma su **timeframe diversi**:
|
||||
game 1 = 5m/15m/1h; **game 2 = 30m/2h/4h** (medio-lunghi). Engine con resampling aggiunto
|
||||
(`engine._RESAMPLE`: 30m←15m, 2h/4h←1h). Specs in `data/games/specs2/`, risultato
|
||||
`data/games/tournament_result2.json`.
|
||||
|
||||
## Diversita' proposte (di nuovo: riscoperta cieca della mean-reversion)
|
||||
100 agenti: **74 pairs, 25 zscore, 1 breakout; 100% reversion**; tf 34/33/33. Come nel
|
||||
game 1, leggendo solo le statistiche anonime (autocorrelazione negativa del log-ratio,
|
||||
continuazione post-mossa ~40%) gli agenti convergono sulla reversione senza sapere che
|
||||
sia crypto.
|
||||
|
||||
## Classifica finale — tutti 30m pairs
|
||||
Vincitore **agente #36** (30m, pairs ETH/BTC):
|
||||
- TEST/OOS: **PnL +1451%, win 77%, 43.4 trade/mese, Sharpe 12.3**.
|
||||
- I 10 finalisti sono TUTTI 30m pairs (TEST Sharpe ~12, win 76-77%, tpm 43-49).
|
||||
|
||||
## Finding chiave: la regola ≥10 trade/mese e' un FILTRO sul timeframe
|
||||
Quanti agenti per tf superano la soglia di attivita' + qualita':
|
||||
| tf | agenti | ≥10 trade/mese | positivi OOS | miglior OOS Sharpe (pnl/win/tpm) |
|
||||
|---|---|---|---|---|
|
||||
| 30m | 34 | **34 (100%)** | 26 | **11.6** (1405% 76% 56) |
|
||||
| 2h | 33 | 29 (88%) | 17 | 6.1 (512% 79% 17) |
|
||||
| 4h | 33 | **4 (12%)** | 6 | 1.4 (103% 68% 14) |
|
||||
|
||||
A 4h solo 4/33 agenti riescono a fare ≥10 trade/mese (le barre sono troppo rade per
|
||||
la reversione pairs); e l'edge cala col timeframe (Sharpe 11.6→6.1→1.4). Per questo i
|
||||
finalisti sono tutti 30m.
|
||||
|
||||
## Lezione cross-game (game 1 + game 2)
|
||||
Esiste una **frontiera frequenza-vs-edge**: la regola ≥10 trade/mese mette un *pavimento*
|
||||
sul timeframe (i lunghi non fanno abbastanza trade), il costo/edge mette un *soffitto* (i
|
||||
cortissimi sono cost-fragili). Il punto ottimo e' **il timeframe piu' corto con edge ancora
|
||||
robusto**: game 1 (con 15m disponibile) → vince 15m; game 2 (senza 15m) → vince 30m. Sempre
|
||||
**ETH/BTC spread reversion**. Coerente con l'analisi di robustezza del 15m
|
||||
(`2026-06-09-pairs15m-robustezza.md`): piu' corto = piu' trade = piu' edge di backtest, ma
|
||||
piu' fragile ai costi. Il gioco trova l'edge; la prudenza di deploy (mezza size) gestisce
|
||||
la fragilita'. Artefatti: `scripts/games/`, `data/games/tournament_result2.json`.
|
||||
@@ -1,47 +0,0 @@
|
||||
# 2026-06-09 — Validazione edge credit-spread cerbero-bite (prezzi reali)
|
||||
|
||||
## Contesto
|
||||
cerbero-bite (container accanto, `/opt/docker/cerbero-bite`) vende credit-spread su
|
||||
ETH (bull-put primario, short delta ~0.18, DTE 18, Quarter-Kelly 13%, PT 50% / stop
|
||||
2.5x credito / delta-breach 0.30 / vol-stop +10 DVOL / time-stop 7 DTE; testnet,
|
||||
propose-only). Tune "Profilo B" del 2026-06-09: short delta alzato a 0.18 (da 0.10-0.15)
|
||||
e `credit_to_width_ratio_min` 0.30->0.08 perche' a delta basso 0 spread erano eleggibili.
|
||||
Domanda: l'edge regge su un ciclo ETH completo, o e' profittevole solo nei campioni calmi?
|
||||
|
||||
Validato con l'infrastruttura opzioni REALE (data/options/, importata da cerbero-bite).
|
||||
Script riprendibile: `scripts/analysis/cerbero_bite_credit_spread.py`.
|
||||
|
||||
## Risultati
|
||||
1. **Economia d'ingresso reale** (chain, 3145 spread): cw a delta 0.18 = **0.106** (p25 0.085),
|
||||
eleggibilita' **65%**, short strike **~9.4% OTM** (NON 18% — quello era il vecchio delta basso),
|
||||
**max-loss/credito = 8.4x**.
|
||||
2. **Tail model-free** (8 anni ETH reali, cw 0.106, hold-to-expiry, niente modello opzioni):
|
||||
win-rate 74%, **EV -1.0 crediti/trade, 7/9 anni NEGATIVI**, ETH <-13.4% a 17g (max-loss) il
|
||||
**17.8%** delle volte. Un max-loss (-8.4cr) cancella 17 PT-winner. Gap 1g p5 = -25% (salta lo stop).
|
||||
3. **Managed (skew calibrato sulle IV reali)**: win-rate **37%** (delta-breach esce sul 62% dei
|
||||
trade a piccola perdita), **EV -0.02 cr/trade** (gia' a economia favorevole), worst -4.6 (2023).
|
||||
2021+ EV -0.022.
|
||||
|
||||
## Caveat di calibrazione (TODO aperto)
|
||||
Il mark mid+skew da **cw 0.228 vs 0.106 reale** -> sovrastima il credito ~2x (manca bid/ask
|
||||
incrociato sulle 2 gambe + griglia strike reale). Quindi l'EV managed mostrato (-0.02) e' a
|
||||
economia **2x troppo favorevole**: l'EV vero e' **<=**. Per il numero esatto: modellare bid/ask
|
||||
reale + griglia (entrambi nella chain) cosi' entry cw -> 0.106. RIPRENDERE da qui.
|
||||
|
||||
## Verdetto
|
||||
- **NON edge robusto su ciclo completo.** Il "+0.48%/mese netto" citato era **artefatto di
|
||||
finestra calma** (mag-giu 2026, nessun crash): li' il body vince (EV +0.6), ma su ciclo
|
||||
completo (mesi -13% al 18% di frequenza) e' breakeven-to-negativo in 2 stime indipendenti.
|
||||
- **L'82% PoP e' ingannevole**: o esci presto sul delta-breach (win 37%, grind di piccole
|
||||
perdite), o tieni e prendi la coda. Non c'e' la "macchina da 82% di vittorie".
|
||||
- **Il tune Profilo B PEGGIORA la coda** (vendere a 9.4% OTM mette il max-loss in zona di
|
||||
pullback ordinario). Strutturale: il mercato non paga per vendere lontano, vendere vicino
|
||||
espone alla coda.
|
||||
- **Coda CONCENTRATA con PythagorasGoal**: il gap che salta lo stop = il crash ETH, lo stesso
|
||||
evento che colpisce lo sleeve fade. I due sistemi non diversificano, concentrano.
|
||||
- **Azione**: cerbero-bite resta testnet/paper finche' non c'e' un campione che include un crash
|
||||
vero; valutare un long deep-OTM put (0.33%/mese reale) come cap della coda del bull-put-spread.
|
||||
|
||||
## Stato
|
||||
DA RIPRENDERE: calibrazione esatta credito (bid/ask + griglia) -> EV managed definitivo.
|
||||
Tutto il resto e' chiuso e documentato.
|
||||
@@ -1,82 +0,0 @@
|
||||
# 2026-06-09 — Percorso live 15m per ETH/BTC pairs: COSTRUITO e VALIDATO
|
||||
|
||||
Seguito di `2026-06-09-pairs15m-port06-gate.md` (il gate passa, edge reale e non
|
||||
artefatto flat). Qui si costruisce e VALIDA l'infrastruttura per eseguire il pairs
|
||||
ETH/BTC a 15m con flat-skip, alla pari del backtest (disciplina validate_worker_pairs).
|
||||
|
||||
## 1. Engine canonico (regression-locked)
|
||||
`scripts/analysis/pairs_research.py`: aggiunti `aligned_ohlc`, `is_flat_ohlc`,
|
||||
`pairs_sim_flat(..., flat_skip, scan_buffer)`. Regola di uscita **LIVE-REALIZABLE**:
|
||||
la condizione (|z|<=z_exit O bars>=max_bars) ARMA `exit_ready`; si esce al CLOSE della
|
||||
PRIMA barra PULITA successiva (mai a un prezzo passato come faceva il prototipo push-back).
|
||||
- **Regression-lock**: `pairs_sim_flat(flat_skip=False)` == `pairs_sim` ESATTO
|
||||
(ETH/BTC 1h 1756 trade, 15m 9388 trade, ret/dd/sharpe identici al bit).
|
||||
|
||||
## 2. PairsWorker esteso (retrocompatibile)
|
||||
`src/live/pairs_worker.py`: param `flat_skip`, stato `exit_ready` (persistito), tick
|
||||
ora fa merge OHLC e rileva le candele flat (O=H=L=C in UNA gamba). Entry saltato su barra
|
||||
stale; uscita con la stessa regola exit_ready dell'engine. **Default off = comportamento
|
||||
1h storico invariato** (se mancano le colonne OHLC, flat=False).
|
||||
|
||||
## 3. Runner: fetch sub-orario (inerte finche' non c'e' uno sleeve 15m)
|
||||
`src/portfolio/runner.py`: `_SUBHOURLY={5m,15m,30m}`, `_LOOKBACK_DAYS` esteso; il loop
|
||||
fetcha DIRETTO da Cerbero i timeframe sub-orari per (asset,tf) (non resamplabili dal 1h) e
|
||||
un router `_series_for` instrada la serie giusta a ogni worker. Zero impatto sul live
|
||||
attuale: nessuno sleeve e' 15m → `subhourly_needs` vuoto → ramo morto.
|
||||
|
||||
## 4. VALIDAZIONE (validate_worker_pairs.py) — TUTTO OK
|
||||
Replay bar-per-bar del worker == backtest:
|
||||
| caso | worker | backtest | match |
|
||||
|---|---|---|---|
|
||||
| ETH/BTC 1h | 1756 trd, cap 2.886.616 | 1756, 2.886.616 | **OK esatto** |
|
||||
| BTC/LTC 1h | 599 trd, cap 16.861 | 599, 16.861 | **OK esatto** |
|
||||
| **ETH/BTC 15m-flat** | **8452 trd** | **8453 trd** (cap entro 0.15%) | **OK** |
|
||||
(1 trade di differenza = posizione finale aperta non chiusa nel replay, atteso.)
|
||||
|
||||
## 5. Gate finale (engine == worker) — PROMOSSO
|
||||
`pairs15m_gate_final.py` (corr 1h vs 15m = 0.372, 3201 ingressi flat saltati):
|
||||
| variante ETH/BTC | FULL Sh | FULL DD | OOS Sh | OOS DD |
|
||||
|---|---|---|---|---|
|
||||
| baseline 1h | 6.43 | 3.96 | 8.58 | 1.36 |
|
||||
| **SWAP 15m-flat** | 7.31 | 3.55 | **9.95** | **1.26** |
|
||||
| **BLEND 1h+15m** | 7.03 | 3.66 | 9.57 | 1.24 |
|
||||
Entrambi PROMOSSI (a fee backtest). Caveat slippage del gate precedente invariato → il
|
||||
BLEND e' la forma raccomandata (meta' allocazione sul 1h pulito, slippage-robusto).
|
||||
|
||||
## Stato e attivazione (NON fatta — decisione di deploy)
|
||||
Tutto il PERCORSO e' pronto e validato, ma il 15m **non e' attivo nel portafoglio live**:
|
||||
attivarlo cambia il trading reale e va deciso esplicitamente. Per accenderlo:
|
||||
1. `_defs.py`: aggiungere SleeveSpec pairs ETH/BTC a 15m (tf="15m",
|
||||
params={n:66,z_in:1.674,z_exit:1.0,max_bars:35,flat_skip:True}) — come SWAP della 1h o
|
||||
come 2a sleeve (BLEND) sotto il cap PAIRS.
|
||||
2. `report_families.build_everything` / `sleeves`: l'equity del nuovo sleeve dal
|
||||
`pairs_sim_flat(tf=15m, flat_skip=True)` (per parita' backtest==report).
|
||||
3. Shadow smoke su testnet (come `live_smoke_pairs.py`) prima del paper reale.
|
||||
4. `deploy.sh` (bump+rebuild) — il runner gia' fetcha 15m e passa flat_skip via spec.params.
|
||||
|
||||
Test suite: nessuna regressione (1h byte-exact). Artefatti: pairs_research.py,
|
||||
pairs_worker.py, runner.py, validate_worker_pairs.py, pairs15m_gate_final.py.
|
||||
|
||||
## ATTIVAZIONE IN REALE (2026-06-09) — BLEND, mezza size
|
||||
Deciso: BLEND (sleeve 15m ACCANTO al 1h, non swap). Implementato:
|
||||
- `_defs.py`: SleeveSpec `PR_ETHBTC_15M` (tf=15m, flat_skip, params.position_size=0.10
|
||||
= meta' del family PAIRS 0.20) in PAIRS -> entra in PORT04/05/06.
|
||||
- `report_families.build_everything`: equity da `pairs_sim_flat(tf=15m, flat_skip=True, pos=0.075)`
|
||||
(mezza size, == intento live) con sid PR_ETHBTC_15M.
|
||||
- `runner.pos_for_spec`: override PER-SLEEVE (params.position_size) > famiglia > globale.
|
||||
- **Mezza size perche'** a peso pieno il 15m pesava il 25.8% del rischio PORT06 (vs 9.5% del
|
||||
1h): dimezzato -> 11.5% vs 10.6%, bilanciato. Disciplina come la cap SHAPE; rispetta il
|
||||
caveat slippage (il 15m non domina il book).
|
||||
|
||||
**PORT06 col BLEND (mezza size)**: FULL Sharpe **6.43->7.20** DD **3.96->3.68**,
|
||||
OOS Sharpe **8.58->9.66** DD **1.36->1.31**. Migliora tutto.
|
||||
|
||||
**Smoke live 15m** (`pairs15m_live_smoke.py`): Cerbero serve candele 15m FRESCHE per
|
||||
ETH e BTC (ultima barra 0 min fa, flat live 2-3%), worker flat-skip ticca OK. Esecuzione
|
||||
reale a 2 gambe gia' coperta da `live_pairs_smoke.py` (livello strumento, tf-indipendente).
|
||||
|
||||
**Regression-lock aggiornati** (miglioria attesa, non regressione): test_definitions
|
||||
(17->18 sleeve), test_backtest_parity_cap (FULL 6.47->7.20, OOS 8.82->9.66). Suite verde.
|
||||
|
||||
Live: il runner fetcha 15m diretto, costruisce il PairsWorker(flat_skip) col pos 0.10,
|
||||
e lo esegue reale a 2 gambe (pairs_enabled). Attivazione via deploy (bump+rebuild).
|
||||
@@ -1,89 +0,0 @@
|
||||
# 2026-06-09 — ETH/BTC pairs a 15m: gate PORT06 (dal gioco Blind Traders)
|
||||
|
||||
## Origine
|
||||
Il gioco "Blind Traders" (100 agenti ciechi) ha eletto come vincitore una variante
|
||||
ETH/BTC pairs su **15m** (config #43: n=66 z_in=1.67 z_exit=1.0 max_bars=35). Domanda:
|
||||
e' un vero miglioramento o un duplicato piu' veloce della sleeve PR01 ETH/BTC gia'
|
||||
deployata a 1h? Testato sul serio con l'engine di PRODUZIONE `pairs_sim` + gate PORT06.
|
||||
Script: `scripts/analysis/pairs15m_port06_gate.py`.
|
||||
|
||||
## Risultati
|
||||
- **Parita' OK** (corr 1.00000): l'harness riproduce esattamente il sleeve canonico
|
||||
PR_ETHBTC → gate affidabile.
|
||||
- **CORRELAZIONE 1h vs 15m = 0.349** (rendimenti giornalieri). **SMENTISCE la mia
|
||||
ipotesi iniziale "duplicato ridondante"**: a 15m cattura eventi di reversione DIVERSI
|
||||
→ e' un diversificatore reale, non una doppia scommessa sullo stesso spread.
|
||||
- **Robustezza 15m**: griglia n×z_in → **16/16 celle Sharpe>1** (9-12), plateau non picco.
|
||||
Non e' un punto overfit del gioco.
|
||||
- **Standalone**: 15m fa 9388 trade (vs 1756 a 1h), Sharpe 11.7 (vs 4.36), DD 54% (vs 48%),
|
||||
8/9 anni+ . (Le % FULL sono esplose dal compounding pos0.15·lev3 su 9k trade → guardare
|
||||
Sharpe/DD/anni, non il livello %.)
|
||||
|
||||
## Gate PORT06 (pos0.15 lev3 canonico, OOS da 2024-10-12)
|
||||
| variante ETH/BTC | FULL Sh | FULL DD | OOS Sh | OOS DD |
|
||||
|---|---|---|---|---|
|
||||
| **baseline 1h** | 6.43 | 3.96 | 8.58 | 1.36 |
|
||||
| **SWAP 15m** | 7.64 | 3.49 | **10.39** | **1.26** |
|
||||
| **BLEND 1h+15m** | 7.30 | 3.63 | 9.95 | 1.24 |
|
||||
|
||||
A fee di backtest (0.20% RT/coppia) **entrambe PROMOSSE**: Sharpe su e DD giu' ovunque.
|
||||
|
||||
## Stress slippage a livello PORT06 (il vero rischio: 15m = 5× i trade)
|
||||
| fee_rt | RT/coppia | PORT06 FULL Sh | FULL DD | OOS Sh | OOS DD | std Sh | std oDD |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| baseline 1h | 0.20% | 6.43 | 3.96 | 8.58 | 1.36 | 4.36 | 16% |
|
||||
| 15m | 0.20% | 7.64 | 3.49 | 10.39 | 1.26 | 11.7 | 13% |
|
||||
| 15m | 0.40% | 7.04 | 4.08 | 9.78 | 1.45 | 8.5 | 27% |
|
||||
| 15m | 0.60% | 6.43 | 4.67 | 9.15 | 1.66 | 5.3 | 47% |
|
||||
|
||||
**Degradazione graziosa ma reale**: il vantaggio di **Sharpe** sopravvive fino a slippage
|
||||
pessimista (OOS 9.15 > 8.58 anche a 0.60%), ma il vantaggio di **DD si perde gia' a 0.40%**
|
||||
(FULL DD 4.08 > 3.96 baseline; standalone oDD esplode 13→27→47%). La regola del progetto
|
||||
("ri-gateare ogni filtro quando cambiano i costi") qui taglia: la frequenza 5× rende la
|
||||
sleeve slippage-sensitive.
|
||||
|
||||
## Verdetto
|
||||
- **NON un duplicato** (corr 0.35) e **NON overfit** (16/16 robusto) → la mia liquidazione
|
||||
iniziale era SBAGLIATA, lo dico chiaro.
|
||||
- **Passa il gate a fee di backtest, marginale sotto slippage**: migliora Sharpe sempre, ma
|
||||
sotto slippage realistico (≥0.40% RT) peggiora leggermente il DD di portafoglio.
|
||||
- **Due rischi di produzione NON ancora quantificati**: (a) qualita' dati ETH 15m (14-30%/anno
|
||||
candele flat O=H=L=C → fill non eseguibili che gonfierebbero il backtest), (b) fill/liquidita'
|
||||
reale a 2 gambe a 15m (5× ordini). Il worker pairs e' validato a 1h, non a 15m.
|
||||
|
||||
**Raccomandazione**: NON swap diretto in live. Candidato promettente → percorso forward:
|
||||
preferire il **BLEND 1h+15m** (tiene il DD pulito del 1h e raccoglie il rendimento
|
||||
decorrelato del 15m) **dopo** un check sull'impatto delle candele flat 15m sui pairs.
|
||||
Allineato a come il progetto tratta FR01 (robusto ma non deployato finche' non domina pulito).
|
||||
Resta come record di ricerca; deploy solo se il check flat-candle e' pulito.
|
||||
|
||||
## CHECK FLAT-CANDLE (pairs15m_flatcheck.py) — PULITO
|
||||
Rischio: ETH 15m ha molte candele flat (O=H=L=C) → close stale che gonfia z-score →
|
||||
reversione FINTA non eseguibile. Test:
|
||||
- **Prevalenza**: ETH 15m **16.4% medio** (fino 30% nel 2022); BTC 15m solo 3.5%. Reale.
|
||||
- **Fill toccati**: 12.9% degli entry e 15.2% degli exit cadono su una barra flat.
|
||||
- **Test decisivo** (entry/exit SOLO su barre pulite, non-flat in entrambe le gambe):
|
||||
rimuove 11.2% dei trade, **Sharpe trattenuto all'83%** (11.74→9.70; OOS Sharpe 18.4).
|
||||
Se l'edge fosse un artefatto flat, filtrando crollerebbe → **NON crolla. NON e' artefatto.**
|
||||
- **Gate PORT06 col 15m FLAT-FILTRATO** (corr 1h vs 15m-flat = 0.366, ancora decorrelato):
|
||||
- SWAP 15m-flat: FULL 7.32/3.55, OOS **9.99/1.26** → PROMOSSO
|
||||
- BLEND 1h+15m-flat: FULL 7.05/3.66, OOS **9.60/1.24** → PROMOSSO
|
||||
|
||||
## Conclusione (3 box su 4 puliti)
|
||||
✅ NON duplicato (corr 0.35-0.37) ✅ robusto (16/16) ✅ NON artefatto flat (83% Sharpe)
|
||||
⚠️ slippage-sensitive: a fee backtest passa pulito; a slippage ≥0.40% RT il vantaggio di
|
||||
Sharpe regge ma il DD-edge si assottiglia. Il **BLEND** mitiga (meta' allocazione resta sul
|
||||
1h pulito e slippage-robusto) → e' la forma deployabile.
|
||||
|
||||
## Realta' del deploy (perche' NON tocco ancora il live)
|
||||
Il gate passa a livello BACKTEST. Ma il live NON puo' eseguire un sleeve 15m oggi:
|
||||
- la live pairs gira SOLO a 1h (`PairsWorker`, validato da `validate_worker_pairs` a 1h);
|
||||
il runner risampla a 1h/4h/1d, non gestisce un leg pairs a 15m.
|
||||
- un BLEND richiede DUE sotto-sleeve ETH/BTC (1h + 15m) dentro il cap PAIRS, e il
|
||||
**flat-skip va replicato nel worker live** (altrimenti il live tradera' le barre stale che
|
||||
il backtest esclude → divergenza backtest-vs-live, la classe di bug che il progetto teme).
|
||||
Editare `_defs.py` cambierebbe solo il backtest/report, NON il live → sarebbe ingannevole.
|
||||
**Percorso deploy corretto** (da confermare): (1) estendere `PairsWorker`/runner al 15m +
|
||||
flat-skip; (2) `validate_worker_pairs` a 15m (replay == backtest esatto); (3) aggiungere lo
|
||||
sleeve 15m sotto il cap PAIRS; (4) shadow su testnet prima del paper. Finche' (1)-(2) non
|
||||
sono fatti e validati, resta **record di ricerca PROMOSSO ma non live**.
|
||||
@@ -1,45 +0,0 @@
|
||||
# 2026-06-09 — ETH/BTC 15m: analisi di robustezza (il limite è il COSTO)
|
||||
|
||||
Domanda: lo sleeve `PR_ETHBTC_15M` (attivato in real, v1.1.16) è robusto? Risposta dai
|
||||
dati: **sì su parametri, tempo e qualità-dati; fragile sui COSTI** — e quel limite è
|
||||
strutturale (alta frequenza). Engine `pairs_research.pairs_sim_flat` (live-realizable).
|
||||
|
||||
## ✅ Robusto su parametri, tempo, dati
|
||||
- **Plateau parametrico**: griglia n×z_in (40-80 × 1.5-2.5) → **16/16 celle Sharpe>1**
|
||||
(range 9-12). Non un picco overfit. (`pairs15m_port06_gate.py`)
|
||||
- **Consistenza temporale**: 2018-2021 +1874% (3/4 anni+, solo 2018 negativo);
|
||||
2022-2026 +12958% (**5/5 anni+**); **OOS ultimo 30% Sharpe 17.6, DD 13%, +**. L'edge
|
||||
è distribuito, non un singolo regime.
|
||||
- **Non artefatto dei dati**: filtrando le candele flat ETH 15m (16% storico) resta
|
||||
l'**83% dello Sharpe** (`pairs15m_flatcheck.py`).
|
||||
- **Decorrelato dal 1h** (corr rendimenti giornalieri **0.37**): segnale diverso, non un relabel.
|
||||
|
||||
## ❌ Fragile sui COSTI — il vero tallone (frequenza 5× il 1h)
|
||||
Sharpe in funzione del costo all-in RT/coppia (fee + slippage):
|
||||
|
||||
| costo RT/coppia | **15m Sharpe** | 1h Sharpe |
|
||||
|---|---|---|
|
||||
| 0.20% (reale, 1×) | **9.34** | 4.36 |
|
||||
| 0.40% (2×) | 6.15 | 3.52 |
|
||||
| 0.60% (3×) | 2.95 | 2.68 |
|
||||
| 0.80% (4×) | **−0.24** | 1.84 |
|
||||
| 1.20% (6×) | −6.63 | 0.16 |
|
||||
|
||||
**Il 1h regge ~6× i costi; il 15m va negativo già a ~4×.** Tanti trade piccoli (8453 vs
|
||||
1756) → margine di costo sottile. Lo **Sharpe 9.34 è un numero a costo basso**: appena lo
|
||||
slippage reale a 2 gambe porta l'all-in verso 0.40-0.60%, scende a 3-6 (ancora positivo,
|
||||
ma l'edge enorme del backtest è in gran parte illusione da bassi costi).
|
||||
|
||||
## Implicazioni (coerenti con la config deployata)
|
||||
1. **La mezza size era giusta**: non si dà al 15m il peso che il backtest a costo basso
|
||||
suggerirebbe. È un blend-tilt, non una scommessa.
|
||||
2. **NO allo swap** (togliere il 1h, tenere solo 15m): sostituirebbe l'àncora cost-robust
|
||||
(1h, regge 6×) con la sleeve cost-fragile. Confronto PORT06: swap OOS 9.95 vs blend 9.66
|
||||
— +0.3 di Sharpe di backtest pagati in robustezza reale. Non vale.
|
||||
3. **Giudice finale = ledger reale shadow**: misurerà lo slippage vero a 15m. Soglia di
|
||||
lettura: all-in <0.40% (Sharpe ≥6) → ottimo diversificatore, valutare size piena;
|
||||
verso 0.60%+ → vale appena la mezza-size che ha (già protetto).
|
||||
|
||||
**In una riga**: robusto come *segnale*, fragile come *esecuzione* → sta nel portafoglio a
|
||||
metà size accanto al 1h, non al suo posto. Riproducibile: fee-sweep + sub-periodo +
|
||||
OOS via `pairs_sim_flat`; plateau/flat-check negli script `pairs15m_*.py`.
|
||||
@@ -1,73 +0,0 @@
|
||||
# 2026-06-09 — Statistiche per-anno di tutte le sleeve attive in REAL
|
||||
|
||||
Snapshot post-attivazione BLEND ETH/BTC 15m (v1.1.16). Breakdown per-anno delle **15
|
||||
sleeve che eseguono ordini reali** su Deribit testnet (escluse le 3 PAPER multi-asset
|
||||
TR01/ROT02/TSM01). Engine **path-live**: EXIT-16 + filtro trend 3.0 per le fade,
|
||||
walk-forward expanding per SH01, flat-skip per il pairs 15m. **PnL% = somma dei
|
||||
rendimenti netti per-trade levered ×3, fee 0.10-0.20% RT incluse** — NON il contributo
|
||||
al portafoglio (che applica sizing pos, cap-weighting, leva 2x, ribilancio 1D); serve a
|
||||
confrontare edge grezzo e DD per sleeve.
|
||||
|
||||
Riproducibile: famiglie pairs via `pairs_research.pairs_sim`/`pairs_sim_flat`; fade/DIP/SH01
|
||||
via le funzioni `stats_fades`/`stats_dip`/`stats_sh01` di `scripts/analysis/make_strategy_doc.py`.
|
||||
|
||||
## FADE (6) + DIP01 — PnL% per anno (n trade)
|
||||
| anno | MR01 BTC | MR01 ETH | MR02 BTC | MR02 ETH | MR07 BTC | MR07 ETH | DIP01 BTC |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 2018 | −78 (48) | −85 (42) | +69 (127) | +10 (127) | −12 (38) | +15 (25) | −78 (79) |
|
||||
| 2019 | −84 (57) | +21 (46) | +18 (118) | +120 (114) | +55 (52) | −40 (35) | −104 (62) |
|
||||
| 2020 | −29 (68) | −35 (55) | +100 (112) | −94 (135) | −11 (53) | +39 (43) | +67 (56) |
|
||||
| 2021 | +326 (82) | +238 (60) | +332 (136) | +160 (127) | +245 (45) | +72 (24) | +315 (69) |
|
||||
| 2022 | +567 (108) | +749 (76) | +728 (106) | +650 (91) | +446 (82) | +472 (58) | +407 (83) |
|
||||
| 2023 | +318 (122) | +248 (73) | +235 (96) | +524 (146) | +168 (67) | +337 (58) | +228 (83) |
|
||||
| 2024 | +413 (113) | +888 (126) | +868 (149) | +1952 (180) | +377 (75) | +645 (87) | +332 (81) |
|
||||
| 2025 | +368 (90) | +361 (86) | +386 (136) | +931 (151) | +190 (60) | +226 (55) | +303 (85) |
|
||||
| 2026* | +69 (29) | −9 (24) | +88 (37) | +25 (41) | +58 (17) | +40 (17) | +7 (29) |
|
||||
| **TOT** | +1870 (717) | +2376 (588) | +2823 (1017) | +4278 (1112) | +1517 (489) | +1806 (402) | +1476 (627) |
|
||||
| **maxDD%** | 32 | 23 | 19 | 31 | 12 | 23 | 37 |
|
||||
|
||||
## SHAPE SH01 (2) — PnL% per anno (n trade)
|
||||
| anno | SH01 BTC | SH01 ETH |
|
||||
|---|---|---|
|
||||
| 2018 | −66 (237) | +74 (239) |
|
||||
| 2019 | +88 (318) | −19 (365) |
|
||||
| 2020 | +194 (240) | −293 (219) |
|
||||
| 2021 | +301 (224) | +67 (146) |
|
||||
| 2022 | +64 (142) | +79 (91) |
|
||||
| 2023 | +17 (118) | +21 (17) |
|
||||
| 2024 | +110 (144) | +108 (47) |
|
||||
| 2025 | +77 (85) | +540 (108) |
|
||||
| 2026* | +59 (23) | −30 (25) |
|
||||
| **TOT** | +845 (1531) | +547 (1257) |
|
||||
| **maxDD%** | 23 | 61 |
|
||||
|
||||
## PAIRS (6) — PnL% per anno (n trade) | 15m a mezza size (pos 0.075)
|
||||
| anno | ETH/BTC 1h | LTC/ETH | ADA/ETH | BTC/LTC | ETH/SOL | ETH/BTC 15m |
|
||||
|---|---|---|---|---|---|---|
|
||||
| 2018 | −343 (177) | — | — | — | — | −492 (913) |
|
||||
| 2019 | +233 (198) | — | — | — | — | +792 (963) |
|
||||
| 2020 | +323 (211) | — | — | — | — | +452 (867) |
|
||||
| 2021 | +549 (202) | — | — | — | — | +1122 (949) |
|
||||
| 2022 | +1344 (206) | +292 (45) | +899 (157) | +328 (58) | +1243 (147) | +2136 (898) |
|
||||
| 2023 | +464 (213) | +56 (94) | +341 (173) | +61 (106) | +125 (168) | +689 (976) |
|
||||
| 2024 | +1661 (253) | +1024 (195) | +1078 (225) | +638 (186) | +1302 (199) | +6313 (1353) |
|
||||
| 2025 | +1173 (225) | +962 (196) | +1046 (187) | +686 (178) | +1264 (202) | +3664 (1123) |
|
||||
| 2026* | +61 (71) | +279 (76) | +140 (71) | +265 (71) | +270 (88) | +155 (411) |
|
||||
| **TOT** | +5464 (1756) | +2614 (606) | +3504 (813) | +1978 (599) | +4204 (804) | +14832 (8453) |
|
||||
| **maxDD%** | 48 | 14 | 19 | 21 | 24 | 34 |
|
||||
| **Sharpe** | 4.36 | 4.22 | 4.90 | 2.72 | 4.61 | 9.34 |
|
||||
|
||||
\* 2026 parziale (fino al 28 mag). Coppie alt (LTC/ADA/SOL) hanno storia solo dal 2022.
|
||||
|
||||
## Aggregato PORT06 (BLEND attivo, 18 sleeve def.)
|
||||
**FULL Sharpe 7.20 / DD 3.68% / CAGR 76% — OOS Sharpe 9.66 / DD 1.31%**. Per anno:
|
||||
2021 +19.0% · 2022 +73.3% · 2023 +39.8% · 2024 +220.1% · 2025 +110.5% · 2026* +7.7%.
|
||||
Nessun anno negativo dal 2021.
|
||||
|
||||
## Letture
|
||||
- Il PnL% grezzo del 15m e' grande perche' fa ~5x i trade del 1h (8453 vs 1756), non
|
||||
per-trade: il confronto equo e' Sharpe (9.34 vs 4.36) e DD (34% vs 48%). Nel portafoglio
|
||||
entra a mezza size -> ~11.5% del rischio (== il 1h).
|
||||
- MR02 ETH = singolo motore piu' forte (+4278%, 2024 +1952%); MR07 il piu' selettivo
|
||||
(DD 12-23%); SH01 ETH il piu' rischioso (DD 61%, coda 2020 −293%) -> mitigato dal cap SHAPE.
|
||||
- I 3 book multi-asset (TR01/ROT02/TSM01) restano PAPER, fuori da questo elenco.
|
||||
@@ -1,49 +0,0 @@
|
||||
# 2026-06-09 — XS01: reversione cross-sectional (famiglia nuova, trovata + deployata PAPER)
|
||||
|
||||
## Origine
|
||||
Dopo aver scartato (alla cieca, coi giochi) trend/breakout/seasonal/opzioni/funding come
|
||||
rumore o −EV, ho cercato io un meccanismo *diverso* dalla mean-reversion pairwise. Trovato:
|
||||
**XS01 — reversione CROSS-SECTIONAL** su 8 asset (BTC/ETH/LTC/ADA/SOL/BNB/XRP/DOGE).
|
||||
|
||||
## Meccanismo
|
||||
Ogni HOLD=12 ore: classifica gli 8 asset per rendimento su LB=48 ore, pesi
|
||||
w = −(ret − media_cross-section), normalizzati a gross 1 → **long i perdenti relativi /
|
||||
short i vincenti**, market-neutral. Roll non sovrapposto (entry-to-entry = hold+1 barre).
|
||||
Fee 0.10% RT/book. Cattura il FATTORE reversione trasversale, distinto dai pairs (pairwise).
|
||||
|
||||
## Verifica (engine canonico `scripts/strategies/XS01_cross_sectional.py`)
|
||||
- **No look-ahead** verificato (segnale invariato perturbando il futuro).
|
||||
- **Robusto**: plateau OOS Sharpe **2–3.9** su lb 12–72 × hold 6–24.
|
||||
- **Scorrelato**: corr **−0.006 / 0.035** da PR01 ETH/BTC, −0.028 dai fade → diversificatore.
|
||||
- Per-anno (entry): 2022 +34, 2023 +6, 2024 +21, **2025 +225**, 2026 +85 (5/5 anni+).
|
||||
- **Caveat**: edge concentrato sul 2025; cost-sensitive (muore ~0.35% RT/book); 8 gambe;
|
||||
storia dal 2022 (no 2018-2020).
|
||||
|
||||
## Worker validato (== backtest esatto)
|
||||
`src/live/xsec_worker.py` `CrossSectionalWorker`: book market-neutral che rolla ogni HOLD
|
||||
barre, stessa formula pesi e cadenza dell'engine. `validate_xsec_worker.py`: replay
|
||||
bar-per-bar == backtest **ESATTO** (worker 4993/1427 trade/49.8% == backtest 4993/1427/49.8%).
|
||||
Bug risolto: il primo prototipo rollava 1 barra troppo tardi (cooldown extra) → rimosso,
|
||||
guard a lb+1, entry-to-entry = hold+1.
|
||||
|
||||
## Gate PORT06 — PROMOSSO (con asterisco)
|
||||
| | corr | FULL Sh | FULL DD | OOS Sh | OOS DD |
|
||||
|---|---|---|---|---|---|
|
||||
| ATTUALE (19→ senza XS01) | — | 7.20 | 3.68 | 9.66 | 1.31 |
|
||||
| **+XS01** | −0.006 | **7.34** | **3.46** | **10.07** | 1.48 |
|
||||
|
||||
Migliora 3 metriche su 4 (OOS Sharpe **+0.41**, il salto più grande dal 15m; FULL DD giù).
|
||||
Unico neo: OOS DD +0.17pp. Risk-contrib XS01 solo **2.2%** (diversificatore a bassa vol).
|
||||
|
||||
## Deploy (v?, 2026-06-09) — PAPER
|
||||
8 gambe → niente esecuzione reale (come TR01/ROT02/TSM01) → XS01 gira **PAPER**
|
||||
(`paper_sleeves`), fuori dal pool, raccoglie statistica forward. Wiring: `_defs.XSEC` in
|
||||
PORT06 (19 sleeve, family XSEC via prefix "XS"), `build_everything` (equity da xsec_sim),
|
||||
`runner` kind="xsec" → CrossSectionalWorker, `asset_days` ora include i paper (fix: gli alt
|
||||
BNB/DOGE/XRP ora vengono fetchati anche per TR01/ROT02/TSM01). Regression-lock aggiornati
|
||||
(18→19 sleeve, FULL 7.20→7.34, OOS 9.66→10.07, DD 3.68→3.46). 93 test verdi.
|
||||
|
||||
**Direzione futura:** se la statistica forward conferma, costruire l'esecuzione reale a
|
||||
N gambe (oggi inesistente) per portarlo nel pool. Per ora: candidato validato che gira
|
||||
PAPER e si osserva. Artefatti: `scripts/strategies/XS01_cross_sectional.py`,
|
||||
`src/live/xsec_worker.py`, `scripts/analysis/{validate_xsec_worker,xsec_port06_gate}.py`.
|
||||
@@ -1,46 +0,0 @@
|
||||
# 2026-06-10 — FC01 funding-carry market-neutral: SCARTATA (il carry non paga le fee)
|
||||
|
||||
## Idea
|
||||
|
||||
Carry NEUTRALE sul funding Deribit (meccanismo mai esplorato: W12 era lo short
|
||||
direzionale su funding alto, bocciato): short della gamba col funding alto /
|
||||
long della gamba bassa (ETH vs BTC, dollar-neutral), incassando il differenziale
|
||||
di funding con esposizione residua = solo lo spread ETH/BTC.
|
||||
|
||||
Dati REALI: `data/regime/{btc,eth}_funding.parquet` — funding orario effettivo
|
||||
dic 2019 → giu 2026 (56.938 ore), `interest_1h` + index_price.
|
||||
Harness: `scripts/analysis/funding_carry_research.py` (causale: decisione al
|
||||
close t, accrual da t+1; fee 0.10% RT per gamba; TRAIN ≤2023-11-01 / OOS dopo).
|
||||
|
||||
## Numeri che uccidono l'idea (prima ancora del backtest)
|
||||
|
||||
- Funding annualizzato: BTC mean +7.2% / med +0.3%; ETH +5.2% / +0.05% —
|
||||
la MEDIANA è ~zero: il funding alto è episodico, non strutturale.
|
||||
- Spread ETH−BTC: p10 −19% / p90 +12.6% annualizzato, MA autocorr del
|
||||
24h-smooth a 72h = 0.20 → poca persistenza.
|
||||
- **Episodi |spread|>10% ann: durata mediana 19h** (p90 60h) → carry
|
||||
incassabile per episodio ≈ 10%/8760×19h ≈ **0.02-0.05%**, contro **0.20%**
|
||||
di fee (2 gambe). Strutturalmente morto: il carry è un ordine di grandezza
|
||||
sotto i costi, e il price-leg dello spread ETH/BTC (vol ben maggiore del
|
||||
carry) domina il PnL.
|
||||
|
||||
## Backtest (conferma)
|
||||
|
||||
- FC-A spread-carry, griglia smooth {24,72,168}h × thr {5,10,20}% ann:
|
||||
TRAIN quasi tutto negativo (Sharpe −0.6…+0.03), OOS negativo ovunque
|
||||
tranne una cella (s24 thr5: OOS +38% con TRAIN −45% = rumore/sign-flip).
|
||||
Sweep fee: negativa anche a 0.05% RT/gamba. Annuale: 2021 −93%, nessuna
|
||||
stabilità.
|
||||
- FC-B direzionale single-asset (confronto onesto): negativa ovunque,
|
||||
riconferma W12.
|
||||
|
||||
## Verdetto
|
||||
|
||||
SCARTATA. Su Deribit BTC/ETH il funding non è un carry harvestabile: troppo
|
||||
piccolo, troppo breve, e l'hedge cross-asset introduce più rischio del carry
|
||||
che raccoglie. Eventuale rivisita SOLO se: (a) si aggiungono alt ad alto
|
||||
funding cronico (Hyperliquid, registry già validato) dove i livelli sono
|
||||
5-10x, o (b) si usa il funding come FEATURE/gate di strategie esistenti
|
||||
(es. filtro sulle entry PR01) invece che come fonte di PnL.
|
||||
|
||||
Script: `scripts/analysis/funding_carry_research.py` (resta come record negativo).
|
||||
@@ -1,113 +0,0 @@
|
||||
# 2026-06-10 — Gioco "Blind Traders" sessione 3: GRID TRADERS (regola: STRATEGIA_GRIGLIA.md)
|
||||
|
||||
## Setup
|
||||
|
||||
Terza sessione del gioco dei trader ciechi, con una regola nuova: ogni agente deve
|
||||
implementare la strategia descritta in `STRATEGIA_GRIGLIA.md` (grid trading a griglia
|
||||
geometrica). 100 agenti (haiku, via Workflow) ricevono SOLO un digest anonimo di due
|
||||
serie X/Y (in realtà BTC/ETH, mai rivelato) sul loro timing assegnato
|
||||
(25×15m, 20×30m, 20×1h, 15×2h, 12×4h, 8×1d) + 5 archetipi di stile a rotazione
|
||||
(prudente / aggressivo / asimmetrico-rialzista / asimmetrico-ribassista / data-driven),
|
||||
e propongono la CONFIGURAZIONE della griglia: `range_down/up %`, `grid_levels`,
|
||||
`sl_buf`, `tp_buf`, `max_bars`, serie.
|
||||
|
||||
Infrastruttura nuova in `scripts/games/`:
|
||||
- **`grid_engine.py`** — backtest deterministico, causale, fee-aware della spec:
|
||||
griglia geometrica `ratio=((1+ru)/(1-rd))^(1/L)` costruita sul close di deploy,
|
||||
capitale 1/L per livello (§3.3), buy su attraversamento ↓ di un livello non
|
||||
riempito, sell del livello su attraversamento ↑ del successivo (§5.2), SL sotto
|
||||
il range e TP sopra che liquidano tutto (§6), redeploy a fine episodio
|
||||
(SL/TP/max_bars). **Vincolo break-even §4 implementato alla lettera**: passo
|
||||
≤ 1.5×costo RT → il motore si rifiuta di partire (`refused`, fitness −2e6);
|
||||
`_normalize` dell'arena riduce i livelli al massimo legale. Fill intrabar lungo
|
||||
il percorso O→L→H→C / O→H→L→C; fee 0.10% RT per round-trip + slippage opzionale.
|
||||
- **`grid_arena.py`** — torneo identico alle sessioni 1-2: split 60/20/20
|
||||
TRAIN/VALID/TEST, 90 epoche di hill-climb sul TRAIN, cull del 10% in VALID ogni
|
||||
10 epoche → 10 superstiti; TEST = OOS puro mai ottimizzato.
|
||||
- **`grid_brief.py`** — digest anonimo con statistiche per dimensionare una griglia:
|
||||
escursione max/min rolling (w100/500/2000, mediana e p90) e probabilità di fuga
|
||||
da un range ±5/10/20% entro 500 barre.
|
||||
|
||||
## Esito
|
||||
|
||||
`data/games/grid_result.json` (+ log `grid_tournament.log`). 100/100 spec da agenti
|
||||
reali (nessun sostituto random).
|
||||
|
||||
- **Alla proposta, 80/100 agenti scelgono X (=BTC)**: dai soli numeri anonimi capiscono
|
||||
che la griglia sopravvive meglio sulla serie meno volatile (escape ±20% in 500 barre:
|
||||
BTC 34.5% vs ETH 53.2% a 1h).
|
||||
- **L'evoluzione ribalta la scelta: tutti i 10 superstiti finiscono su Y (=ETH)** —
|
||||
nel periodo VALID/TEST la vol più alta di ETH paga di più i round-trip, e il rischio
|
||||
trend è gestito non dal range stretto ma dalla FORMA della griglia (sotto).
|
||||
- **Convergenza fortissima della forma** (9/10 superstiti): griglia **asimmetrica
|
||||
ribassista** — range profondo sotto (−13/−20%), corto sopra (+4/+8%), **livelli al
|
||||
minimo (4)** → passo largo ~4.5-5.5%, SL buffer profondo (5-15%), max_bars lunghi.
|
||||
Tradotto: **compra i dip di ETH in 4 tranche distanziate ~5%, rivendi ogni tranche
|
||||
al rimbalzo di un passo, stop catastrofale a ~−25/−30%**. Il gioco ha ri-scoperto
|
||||
per la terza volta la mean-reversion (qui in forma di dip-buying a tranche), e ha
|
||||
imparato da solo la lezione anti-fee: meglio pochi passi larghi che griglie fitte.
|
||||
|
||||
**Vincitore: agente #11, ETH 15m**, griglia −17.1%/+4.6% × 4 livelli, SL buf 12.4%,
|
||||
TP buf 4.8%, max 2143 barre. TEST(OOS): **PnL +891% (additivo), win 97%, 38.5
|
||||
trade/mese, Sharpe 10.1**. FULL 2018-2026 (include bear 2018 e 2022): +4284%, Sharpe 9.6.
|
||||
Stress slippage TEST: 0.05%/lato → 871%, 0.10%/lato → 850% (il passo ~5.4% ⋙ costi).
|
||||
|
||||
## Caveat onesti (perché NON è un candidato deploy così com'è)
|
||||
|
||||
1. **Il PnL è additivo per-trade e non misura il drawdown UNREALIZED**: l'engine
|
||||
somma i round-trip realizzati; mentre la griglia tiene 4 tranche dentro un
|
||||
drawdown −17%, l'equity vera è sott'acqua (fino a ~−15% di episodio + SL −25/30%
|
||||
quando scatta). Il win-rate 97% è il profilo classico della griglia: tante
|
||||
micro-vincite, perdite rare ma grandi (stessa famiglia di rischio del
|
||||
short-vol/martingala). Per un gate serio servirebbe l'equity curve mark-to-market.
|
||||
2. **Long-only su ETH con VALID/TEST 2023-2026** (regime rialzista/oscillante):
|
||||
l'asimmetria −17/+4.6 è anche un fit al regime. Il FULL positivo (bear inclusi)
|
||||
è incoraggiante ma il grosso del PnL resta nei periodi di reversione rialzista.
|
||||
3. Le candele flat ETH 15m (14-30%/anno) e i fill intrabar "al livello" condividono
|
||||
i caveat noti del progetto (bias pro-stop-stretti dell'engine intrabar; qui gli
|
||||
stop sono larghi, quindi l'effetto è minore).
|
||||
|
||||
## Lezioni
|
||||
|
||||
- La spec STRATEGIA_GRIGLIA.md è implementabile in modo causale e onesto; il suo
|
||||
vincolo break-even (§4) è esattamente la "lezione fee" del progetto, e il torneo
|
||||
l'ha confermato spingendo i livelli al minimo (passo massimo).
|
||||
- La griglia evoluta è un parente povero delle fade MR già in live: stesso edge
|
||||
(reversione ETH), ma incassato con inventory risk crescente invece che con
|
||||
TP/SL per-trade. Non sostituisce le MR; eventuale interesse solo come variante
|
||||
"a tranche" da gateare con equity mark-to-market (e confronto con MR01/MR02 a
|
||||
parità di rischio) PRIMA di pensarci per il PORT06.
|
||||
|
||||
## GATE "si puo' inserire?" (stessa sera) — NO-GO: edge = artefatto delle wick testnet
|
||||
|
||||
`scripts/analysis/grid_game_gate.py`: engine **mark-to-market** dedicato (equity
|
||||
per barra = capitale + inventario al close, SL gap-aware, flat-skip, fee 0.10% RT),
|
||||
metriche standard del progetto + gate PORT06. Primo passaggio ingannevole: standalone
|
||||
WINNER 15m FULL Sharpe 5.61 DD 15.8%, corr max coi sleeve 0.34, plateau 16/16,
|
||||
e il criterio formale promuoveva il half-size (OOS Sh 10.07->10.12, DD 1.48->1.36).
|
||||
MA il breakdown annuale mostrava **+4946% nel 2022** (ETH −70%): impossibile.
|
||||
|
||||
**Verifica avversariale decisiva**: il feed Deribit (testnet) e' pieno di **spike
|
||||
print** — ETH 15m ha 1064 barre con wick ≥6% sotto i close adiacenti che rientrano
|
||||
subito (fino a −19% in 15 minuti; BTC ha spike a −54% nel feb 2024). La griglia
|
||||
intrabar compra su quelle wick FINTE e rivende al rimbalzo: free money in sim,
|
||||
infillabile dal vivo. Stress **close-only** (fill solo su attraversamento del
|
||||
close): WINNER 15m CAGR 1544%->21%, Sharpe 5.61->0.92, OOS +2738%->+32%,
|
||||
trades 3803->1156; top3 1h CAGR -1.7%, OOS −18%. **~99% dell'edge vive nelle
|
||||
wick.** La versione onesta (Sharpe 0.92, DD 27%) e' molto sotto ogni sleeve
|
||||
deployato → **NON inseribile**, in nessuna size.
|
||||
|
||||
Lezioni aggiuntive:
|
||||
- Il torneo ha massimizzato esattamente l'artefatto: la convergenza su ETH 15m
|
||||
range profondo era la firma del **wick harvesting**, non di un edge.
|
||||
- I motori intrabar dei giochi (`grid_engine`, e in misura minore i TP intrabar
|
||||
di `engine.py`) vanno SEMPRE stressati con una variante close-only prima di
|
||||
promuovere qualunque vincitore: aggiungere il check ai prossimi giochi.
|
||||
- Gli sleeve in produzione NON sono toccati da questo artefatto nello stesso modo:
|
||||
pairs entra/esce sui close, le fade hanno EXIT-16 close-confirm sullo SL, e
|
||||
soprattutto il ledger REAL-TRUTH usa i fill reali (che gli spike non fillano).
|
||||
|
||||
Artefatti: `scripts/games/grid_{engine,arena,brief}.py`, spec agenti in
|
||||
`data/games/specs_grid/`, digest `data/games/grid_digests.json`, risultato
|
||||
`data/games/grid_result.json`, log `data/games/grid_tournament.log`, gate
|
||||
`scripts/analysis/grid_game_gate.py` (param `close_only` per lo stress anti-wick).
|
||||
@@ -1,57 +0,0 @@
|
||||
# 2026-06-10 — REAL-TRUTH: il ledger segue i fill reali (sim → diagnostica)
|
||||
|
||||
## Richiesta
|
||||
|
||||
L'utente vuole che sim e reale coincidano — o meglio, che il sim non esista come
|
||||
verità: «voglio vedere dati che hanno avuto movimento reale su exchange». La
|
||||
ricognizione dei 77 eventi reali (dal 2026-06-03) ha mostrato che il gap
|
||||
sim/reale NON era slippage (piccolo, es. −0.15 bps su un TP) ma **contabile**:
|
||||
|
||||
1. **Ledger separati.** Il `capital` che guida portafoglio/ribilanci/sizing era
|
||||
aggiornato dal PnL SIM; il PnL reale finiva in un `real_capital` parallelo che
|
||||
non guidava nulla. MR01 BTC: sim +28.93 vs reale +1.98 sugli stessi 4 trade.
|
||||
2. **Prezzi sim da candele testnet** (spike print, es. 2026-06-07 sim short BTC a
|
||||
65266.5 con mark reale 62395): il sim bookava PnL che il reale non vede. Con
|
||||
il ledger sim come verità, l'equity del portafoglio accumulava questa fantasia.
|
||||
|
||||
Nota: il *notional* reale era GIÀ derivato dalla formula sim
|
||||
(`capital·ps·lev` passato a `_real_open`/`_real_open_pair`) — il punto 1 della
|
||||
richiesta (sizing allineato) si chiude da solo una volta che `capital` è reale.
|
||||
|
||||
## Implementazione (REAL-TRUTH)
|
||||
|
||||
- `StrategyWorker` e `PairsWorker` accettano `real_truth: bool` (default False =
|
||||
shadow storico). Con flag attivo e esecuzione abilitata:
|
||||
- `_real_close`/`_real_close_pair` ritornano `(real_pnl, applied)`;
|
||||
`applied=True` se ci sono fill reali (o chiusura verificata).
|
||||
- `_close_position`/`_close` chiamano la chiusura reale PRIMA dell'update
|
||||
ledger: `capital += real_pnl` (fee reali incluse); `is_win = pnl_reale > 0`.
|
||||
- Il sim resta nel log CLOSE come diagnostica: `pnl_source` ("real" |
|
||||
"sim_fallback"), `sim_pnl`, `real_pnl`.
|
||||
- **Fallback al sim** SOLO se il trade reale non è mai esistito/fillato
|
||||
(REAL_OPEN_FAIL, fill zero) — dichiarato nel log, mai silenzioso.
|
||||
- Runner: `overrides.execution.real_truth` (yml) → `build_worker_for(...,
|
||||
real_truth=)`. `portfolios.yml`: **`real_truth: true`**.
|
||||
- Conseguenza a catena: equity ledger → pesi → allocazioni → notional dei
|
||||
prossimi ordini derivano ora dai soldi veri sul conto. Il `real_capital`
|
||||
parallelo resta come ledger puro-reale di confronto.
|
||||
|
||||
## Test
|
||||
|
||||
`tests/portfolio/test_real_truth.py` (6 test): capital segue i fill reali
|
||||
(single-leg e pairs), una divergenza sim-win/reale-loss viene contata come LOSS,
|
||||
fallback sim dichiarato su REAL_OPEN_FAIL/leg-fail, e modalità shadow invariata
|
||||
senza flag. Suite completa: 99 passed.
|
||||
|
||||
## Limiti onesti
|
||||
|
||||
- I multi-asset (TR01/ROT02/TSM01/XS01) restano sim per costruzione (paper
|
||||
sleeves fuori dal pool, capitale insufficiente per i book multi-leg).
|
||||
- La STORIA del ledger non è riscritta: l'equity attuale (~2154) ingloba il PnL
|
||||
sim accumulato fino a oggi (reale realizzato era ≈ −15.6 dal 3/6). Da ora la
|
||||
divergenza smette di accumularsi; se si vuole un azzeramento (reset equity al
|
||||
conto reale) è un'operazione separata e deliberata.
|
||||
- Le DECISIONI di trading (entry/exit) restano guidate dai prezzi del feed
|
||||
(candele testnet): real-truth corregge la contabilità, non i segnali. Gli
|
||||
spike print del feed possono ancora generare entry/exit subottimali — ma ora
|
||||
il loro effetto si misura in PnL reale, non in PnL immaginario.
|
||||
@@ -1,51 +0,0 @@
|
||||
# 2026-06-10 — XS01 dispersion-gate: PROMOSSO e LIVE (entry solo con dispersione da fare rientrare)
|
||||
|
||||
## Domanda
|
||||
|
||||
L'edge di XS01 (reversione cross-sectional 8 asset) era concentrato (2025 domina,
|
||||
2023 quasi piatto) e cost-sensitive. La reversione cross-sezionale va accesa solo
|
||||
quando c'e' dispersione da far rientrare?
|
||||
|
||||
## Metodo (anti multiple-testing): `scripts/analysis/xs01_dispersion_gate.py`
|
||||
|
||||
3 feature di regime CAUSALI calcolate dallo stesso panel closes (nessun feed
|
||||
esterno): `g_disp` = std cross-section del momentum lb (la grandezza che si fada),
|
||||
`g_corr` = correlazione media pairwise 72h (identita' della varianza dell'indice),
|
||||
`g_vol` = vol BTC 168h. Diagnostica per quintili (quintili dal TRAIN, 70/30) sul
|
||||
net per-trade dell'engine canonico NON gateato, TRAIN e OOS separati: si procede
|
||||
solo con relazione monotona e concorde nelle due finestre.
|
||||
|
||||
## Esito diagnostica
|
||||
|
||||
- **g_disp: monotona e concorde** — Q1 NEGATIVO (−10 bps TRAIN / −8 OOS) →
|
||||
Q5 +26/+280. Senza dispersione i trade sono solo fee. PROMOSSA.
|
||||
- g_corr e g_vol: non monotone / segno incoerente → BOCCIATE (niente fishing).
|
||||
|
||||
## Gate (sweep soglie = percentili TRAIN, side dal TRAIN)
|
||||
|
||||
Plateau pieno p30-p70, niente picco: TRAIN Sh 1.51 → 2.0-2.3, OOS Sh 5.73 →
|
||||
6.2-7.5. Scelta **p50 (disp_min = 0.0313)**, ~47% delle ore aperte:
|
||||
|
||||
- Standalone: trade 1427→859 (−40% turnover → meta' fee), win 50→53%,
|
||||
**Sharpe 2.50→3.46**, DD 16.2→15.8%. **Ogni anno migliora**: 2022 +34→+40,
|
||||
2023 +6→+28, 2024 +21→+44, 2025 +225→+237, 2026 +85→+108 — risolve la
|
||||
concentrazione, il punto debole della validazione originale.
|
||||
- Fee stress 2x (0.20% RT/book): OOS Sh 6.76 — la cost-sensitivity e' mitigata
|
||||
(il gate taglia proprio i trade che pagavano fee senza edge).
|
||||
- **Gate PORT06** (swap equity sleeve): FULL Sh 7.34→7.41 DD pari,
|
||||
**OOS Sh 10.07→10.37 DD 1.48→1.47** → PROMOSSO (criterio standard).
|
||||
|
||||
## Implementazione (solo path LIVE, come trend/hurst sulle fade)
|
||||
|
||||
- `src/live/xsec_worker.py`: param opzionale `disp_min` (None = off), check in
|
||||
`_open_book` su `nanstd(logC[i] − logC[i−lb])`. Default off → la validazione
|
||||
`validate_xsec_worker` (replay == backtest) resta esatta.
|
||||
- `src/portfolio/runner.py`: pass-through di `disp_min` (il runner costruiva il
|
||||
dict params esplicitamente e l'avrebbe perso).
|
||||
- `scripts/portfolios/_defs.py`: `disp_min: 0.0313` nella spec XS01.
|
||||
- Il backtest canonico (`build_everything`) resta NON filtrato → il live fara'
|
||||
meglio del backtest, coerente con le altre guardie.
|
||||
|
||||
Unit check: gate blocca panel piatto / apre panel disperso / default off invariato.
|
||||
99/99 test. Nota macro della giornata: FC01 funding-carry SCARTATA
|
||||
(diario separato) — il protocollo promuove ~1 idea su molte, come deve.
|
||||
@@ -1,86 +0,0 @@
|
||||
# 2026-06-11 — Sweep di stabilità su tutte le strategie (anti-overfit)
|
||||
|
||||
Obiettivo: analisi di tutte le 19 sleeve cercando miglioramenti/correzioni/protezioni che
|
||||
aumentino la STABILITÀ, con disciplina anti-overfit (ipotesi pre-registrate, griglie fissate
|
||||
prima di guardare i numeri, verdetti su TRAIN E OOS con plateau, gate PORT06; nessun re-test
|
||||
di idee già bocciate: ADX/vol-target/time-stop/hurst/stop SH01/multi-TF/entry-guard ecc.).
|
||||
|
||||
## Audit di drift (nessun fitting)
|
||||
|
||||
- `report_families` sui dati correnti: correlazioni cross-famiglia ancora ≈0 (pairs 0.03-0.11,
|
||||
XS01 0.01, SH 0.03-0.04 vs MASTER-9) → la diversificazione NON è driftata.
|
||||
- **Regression-lock trend_max** (`trendmax_port06_impact`) rieseguito su dati freschi:
|
||||
parità 1.00000 su tutte e 6 le fade (engine live-path integro) e **plateau trend_max
|
||||
2.5/3.0/3.5 confermato** (OOS Sh 11.14/11.24/10.98, DD 1.33 identico).
|
||||
- **Percentile del rolling-return PORT06** (cap weights, storia 2021+): finestra corrente
|
||||
60g al 19°, 120g al 21°, 160g al 28° percentile → periodo fiacco ma in variazione normale.
|
||||
- ⚠️ **FADE in coda storica**: il rolling 120g equal-weight delle 6 fade è a **−1.0% =
|
||||
2° percentile** della propria storia (p5 = +0.4%). È il tratto peggiore mai attraversato
|
||||
dalla famiglia. Decisione esplicita: NESSUN ritocco ai parametri (sarebbe fit sul regime
|
||||
corrente, l'errore che il progetto evita da sempre); la protezione è la diversificazione
|
||||
(già in atto: il portafoglio regge al 19-28° pct) + monitoraggio. Follow-up in TODO:
|
||||
alert di drift per-famiglia nel hourly_report (distribuzione storica precomputata).
|
||||
|
||||
## Correzione: bug contabile TR01 worker (FIXATO)
|
||||
|
||||
`BasketTrendWorker.tick` usava `mean(rets)` sui SOLI asset in posizione → con paniere
|
||||
parziale sovrappesa N/k (con 1 solo long: 0.45 del capitale invece di 0.09). Era l'origine
|
||||
della divergenza replay −44% vs reference +42% annotata nel TODO. La convenzione canonica
|
||||
(backtest PORT06 via `_tr_basket_daily`) è equal-weight 1/N sull'universo: fix 1 riga
|
||||
(`sum(rets)/len(universe)`). Replay post-fix: **TR01 +32% vs reference +42%** (stesso segno
|
||||
e ordine di grandezza = gate del validatore; il residuo è la differenza dichiarata
|
||||
capitale-unico vs media-equity). ROT02 +171%==ref, TSM01 +5%==ref invariati. Solo
|
||||
statistica PAPER: nessun effetto su pool/ordini. NB: il forming-bar su ROT02/TSM01 segnato
|
||||
nel TODO era GIÀ fixato (v1.1.10, `_panel` scarta la barra in formazione) — TODO aggiornato.
|
||||
|
||||
## Protezione 1 (pre-registrata): disaster-cap z sui pairs → **NO-GO**
|
||||
|
||||
Ipotesi: exit immediata se |z| ≥ z_stop dopo l'ingresso taglia la coda da structural-break
|
||||
senza toccare i trade normali. Griglia fissata: z_stop {3.0,3.5,4.0,5.0} × 5 coppie 1h +
|
||||
{2.5,3.0,3.5,4.0} sul 15m, train <2023-11-01 / OOS, engine con regression-lock ESATTO su
|
||||
`pairs_sim`/`pairs_sim_flat`. Esito (potere statistico AMPIO, centinaia di trigger):
|
||||
**bocciata su tutti e 3 i criteri** — il DD peggiora quasi ovunque, il worst-trade OOS
|
||||
peggiora su 4 coppie su 6 (ETH/BTC −62→−168%!), Sharpe OOS cala oltre il −10% relativo in
|
||||
TUTTE le celle, e il "plateau" esiste solo per il danno (monotono: più stretto, peggio).
|
||||
Meccanismi: (i) lo stop realizza la perdita al massimo overshoot — il movimento che la
|
||||
strategia fada (stessa lezione EXIT-16/SH01, **5ª conferma**); (ii) l'engine non-overlap
|
||||
rientra subito nello spread ancora divergente → churn di fee a 2 gambe e stop ripetuti.
|
||||
I pairs restano senza stop by design; la mitigazione resta la taglia
|
||||
(`position_size_family` PAIRS 0.20). Record: `scripts/analysis/pairs_zstop_research.py`.
|
||||
|
||||
## Protezione 2 (pre-registrata): phase-tranching XS01 → **PROMOSSA e LIVE**
|
||||
|
||||
Diagnosi: il roll non-sovrapposto di XS01 ha una FASE arbitraria (dipende da quando il
|
||||
worker parte) e l'esito ne dipende parecchio — sulle 12 fasi possibili: Sharpe daily FULL
|
||||
1.52-2.33, DD per-trade 13.8-33.1% (`xs01_tranche_research.py`). È timing-luck puro: il
|
||||
backtest canonico (fase 0) è una delle estrazioni FORTUNATE sul FULL (DD 15.4 vs mediana
|
||||
~21). Rimedio senza parametri fittati: **ensemble di fase** — K sub-book sfasati di hold/K
|
||||
barre su capitale comune (PnL/K). Gate onesto su equity daily (`xs01_tranche_gate.py`):
|
||||
|
||||
- standalone OOS: Sharpe 3.79→4.27 (K=2) →4.85 (K=3), DD 7.99→7.25→5.56;
|
||||
- FULL standalone: il DD sale verso la mediana di fase (~21%) — il "peggioramento" è la
|
||||
RIMOZIONE della fortuna della fase 0, non un costo;
|
||||
- PORT06 swap-sleeve: FULL invariato (7.33/3.46), OOS Sh 10.07→10.11 (K=2) →10.15 (K=3),
|
||||
OOS DD 1.48→1.43→1.38. **Plateau: K=2 E K=3 entrambi promossi** (non best-pick).
|
||||
|
||||
Implementazione: `CrossSectionalWorker` param `tranches` (default 1 = storico; live K=3 in
|
||||
`_defs.py`), books indipendenti con sfasamento iniziale `wait`, capitale comune, migrazione
|
||||
automatica dello status legacy (il vecchio book → tranche 0), `last_bar_ts` solo-avanti
|
||||
(robustezza ai panel accorciati da feed in ritardo). Solo path LIVE come `disp_min` (il
|
||||
backtest canonico resta single-phase → il confronto live/backtest va letto con la mediana
|
||||
di fase in mente). **Validatore esteso e PASSATO**: K=1 replay == `xsec_sim` ESATTO
|
||||
(1427 trade, cap 4993==4993); K=3 replay == unione fasi 0/4/8 ESATTO (4279 trade,
|
||||
4512==4512). Osservabilità: `hourly_report` aggrega i sub-book nel book medio.
|
||||
|
||||
## Non toccati (per evidenza, non per pigrizia)
|
||||
|
||||
- **Fade/DIP01**: exit-lab già esaustivo (23+11 famiglie); plateau e parità riconfermati oggi.
|
||||
- **SH01**: 11 famiglie di stop già bocciate; cap famiglia + monitor trade-rate in essere.
|
||||
- **ROT02/TSM01**: replay == reference; forming-bar già fixato.
|
||||
- **TR01 come sleeve** (3 anni negativi su 6): rimosso? NO — sarebbe una decisione guidata
|
||||
dal regime recente (recency bias); il suo ruolo è catturare i trend che le fade non
|
||||
prendono. Resta, con la statistica ora contabilizzata correttamente.
|
||||
|
||||
## Esito test
|
||||
|
||||
`pytest`: 99 passed. Validatori: honest workers OK, xsec K=1/K=3 OK, trendmax lock OK.
|
||||
@@ -1,92 +0,0 @@
|
||||
# 2026-06-11 — Audit di sistema + verità contabile sul netting (v1.1.24)
|
||||
|
||||
Seconda tornata della giornata (dopo lo sweep strategie): analisi del SISTEMA live
|
||||
(esecuzione, stato, feed, processo) con 3 indagini parallele + fix.
|
||||
|
||||
## Audit live (dal reset 2026-06-10T21:24Z)
|
||||
|
||||
- **Churn phantom-TP quantificato**: 20 round-trip fantasma sui fade ETH (2 finestre,
|
||||
13:06Z e 17:32-17:58Z, feed che stampava wick ~1640 con mercato a 1675-90 per 25 min).
|
||||
Somma real_pnl −2.35 USD vs sim_pnl +80 USD: il real-truth ledger ha contenuto, il gate
|
||||
TP_PHANTOM (v1.1.23) copre il pattern da stasera.
|
||||
- **Il conto NON quadrava coi libri**: short 0.027 ETH in più (l'hedge long ETH del pair
|
||||
ETH/SOL mangiato dai close reduce-only dei fade) e BTC flat con MR02_BTC convinto di
|
||||
essere short (TP resting fillato da uno spike REALE del book a −3.8%, +6.6$ non bookati,
|
||||
che il worker riconcilierà alla chiusura sim) col **disaster-SL residuo sul book a
|
||||
posizione flat**. Bonifica eseguita: DSL `USDC-SLMB-26521` cancellato, riallineo
|
||||
+0.027 ETH reduce-only (fill 1682.5) → conto == libri (verificato).
|
||||
|
||||
## Root-cause strutturale
|
||||
|
||||
Le **quote per-worker con ordini reduce-only su un conto a NETTING si rompono quando due
|
||||
worker hanno direzioni opposte sullo stesso strumento** (pairs long ETH vs fade short ETH):
|
||||
- un close reduce-only può essere **cappato** (Deribit riduce l'amount in silenzio) → il
|
||||
ledger bookava la chiusura PIENA perché `Fill.amount` era il richiesto, non il fillato;
|
||||
- un close reduce-only nel verso "sbagliato" rispetto al netto viene **respinto** → la
|
||||
gamba pairs resta orfana sul conto, ma il worker bookava il PnL al prezzo sim e azzerava
|
||||
lo stato (3 volte oggi: PnL fantasma nel ledger real-truth, ETH/SOL di fatto short nudo).
|
||||
|
||||
## Fix (v1.1.24) — verità, non workaround
|
||||
|
||||
1. **`Fill.filled_amount`** (da `order.filled_amount`, fallback trades/history): tutti i
|
||||
ledger usano il fillato; nota "FILL PARZIALE" nel Fill.
|
||||
2. **`REAL_CLOSE_PARTIAL`** (log + Telegram): close che filla meno del residuo → residuo
|
||||
orfano dichiarato, `REAL_CLOSE verified=false`.
|
||||
3. **Pairs per-gamba**: PnL bookato SOLO per gambe con fill verificato; gamba respinta →
|
||||
record in `orphan_legs` (persistito nello status) + alert `PAIR_LEG_ORPHAN`;
|
||||
`applied=True` (real-truth) solo con ENTRAMBE le gambe → altrimenti fallback sim
|
||||
DICHIARATO (meglio del numero mezzo-reale di prima).
|
||||
4. **`REAL_DIVERGENCE` anche su jsonl** (prima solo Telegram: l'audit ha dovuto
|
||||
ricostruire gli episodi dai REAL_CLOSE).
|
||||
5. **Runner: tick isolato per-worker** — un'eccezione in un worker non salta più gli
|
||||
altri né l'update equity; streak per-worker con alert `WORKER_ERROR_STREAK` a 5.
|
||||
|
||||
Test: 2 nuovi (partial-close, orphan-leg) + fixture aggiornate → 106 passed.
|
||||
|
||||
## Decisione di design APERTA (per l'utente)
|
||||
|
||||
Finché pairs e fade condividono strumenti in direzioni opposte, le chiusure possono
|
||||
orfanizzarsi: ora è VISIBILE e contabilizzato giusto, ma non eliminato. Opzioni:
|
||||
A) **Position-manager centrale per strumento** (il runner netta i delta di tutti i
|
||||
worker e manda UN ordine; ricostruisce le quote contabilmente) — corretto ma
|
||||
invasivo, da progettare con calma;
|
||||
B) **Sotto-conti Deribit separati** per famiglia (pairs vs fade) — pulito, richiede
|
||||
setup conto e client multi-token;
|
||||
C) **Status quo monitorato**: alert PAIR_LEG_ORPHAN + riallineo manuale (oggi: 1 giro
|
||||
in 2 minuti) — accettabile su testnet, NON per capitale vero.
|
||||
Raccomandazione: C ora, A prima di passare a capitale reale.
|
||||
|
||||
**Secondo passo — FATTO (v1.1.25): NETTING delle chiusure market.** `close_amount`
|
||||
tenta il reduce-only e riesegue il residuo cappato/respinto in market puro (= il
|
||||
netting contro le quote opposte: il conto si muove del delta esatto del libro).
|
||||
Un solo punto di fix (anche `close_pair` ci passa). Fill combinato per il chiamante
|
||||
(prezzo pesato, fee sommate), evento `NET_CLOSE` su log+Telegram a ogni fallback,
|
||||
4 test dedicati. Niente più orfani per costruzione; `orphan_legs` resta come ultima
|
||||
difesa se fallisce anche il market puro. Effetto collaterale benefico: la chiusura
|
||||
futura della gamba ETH di ETH_SOL#2 (che sarebbe stata respinta di nuovo) ora
|
||||
eseguirà correttamente. La scelta A-vs-B-vs-C resta aperta solo per la parte
|
||||
RESTING (TP/DSL su book condiviso) e per i multi-asset.
|
||||
|
||||
**Primo passo verso A — FATTO (sera stessa): reconciler read-only.**
|
||||
`scripts/analysis/reconcile_account.py`: per ogni strumento USDC confronta
|
||||
atteso (Σ quote reali dai status.json: single-leg + pairs 2 gambe + orphan_legs
|
||||
registrati = drift SPIEGATO) vs conto reale (`get_positions`, size/mark → coin),
|
||||
tolleranza 1.5×step, anti-race (ricontrollo a 10s prima di segnalare). In crontab
|
||||
host ORARIO (:40) con alert Telegram `ACCOUNT_DRIFT`. Al primo run ha beccato un
|
||||
vero positivo: BTC libro short 0.0028 vs conto flat (il TP di MR02_BTC fillato
|
||||
dallo spike reale delle 12:22Z, che il worker riconcilierà alla chiusura sim) —
|
||||
esattamente la classe di divergenza che prima restava invisibile per ore.
|
||||
|
||||
## Altri esiti della tornata
|
||||
|
||||
- **Dedup engine gate** (TODO chiuso): `_port06_gate_common.py`, output 3 gate
|
||||
byte-identici, nessun copy-drift trovato (la paura era fondata ma non ancora avverata).
|
||||
- **Bug bfill `_daily_equity` quantificato** (TODO aggiornato): NON materiale — OOS
|
||||
invariato per costruzione, FULL DD 3.46→3.67 col fix (l'attuale è lievemente ottimista),
|
||||
nessun verdetto di gate a rischio. Lasciato documentato.
|
||||
- **Drift monitor in produzione**: `drift_monitor.py` in crontab host (07:15 UTC,
|
||||
Telegram): rolling 60/120g per famiglia vs distribuzione storica propria, warn < p5.
|
||||
Oggi: FADE 120g al p2 (coda storica, nessun intervento), resto normale, XSEC p84.
|
||||
- **Dati cerbero-bite refreshati**: catena opzioni a ~153k righe/asset (fino a oggi
|
||||
19:30), pannello regime denso (net-GEX 644/673 ultimi 7g). Sempre un solo regime:
|
||||
niente validazione edge, valore forward.
|
||||
@@ -1,74 +0,0 @@
|
||||
# 2026-06-12 — ACCEL50: cosa accelera davvero verso €50/giorno
|
||||
|
||||
**Domanda.** Quali strategie/leve accorciano il tempo per arrivare a €50/g da ~€2k?
|
||||
Script: `scripts/analysis/accel50_research.py`.
|
||||
|
||||
## Il quadro onesto
|
||||
|
||||
A €2k, anche col CAGR OOS del PORT06 (~111% a lev 2), il PnL atteso è ~€4/g: il
|
||||
collo di bottiglia NON è l'edge (Sharpe OOS 10), è la **taglia**. Le vie testate,
|
||||
in ordine di impatto:
|
||||
|
||||
## 1. LEVA — l'acceleratore dominante (nessuna ricerca nuova)
|
||||
|
||||
Frontiera su daily return canonici PORT06 (scala lineare, fee pro-quota):
|
||||
|
||||
| lev | CAGR full | DD full | CAGR OOS | DD OOS | anni a €50/g da 2k |
|
||||
|-----|-----------|---------|----------|--------|--------------------|
|
||||
| 2 (attuale) | 74% | 3.5% | 111% | 1.5% | 3.3 |
|
||||
| 3 | 128% | 5.2% | 206% | 2.2% | 1.9 |
|
||||
| 4 | 200% | 6.9% | 343% | 2.9% | 1.2 |
|
||||
| 5 | 293% | 8.6% | 539% | 3.7% | 0.9 |
|
||||
|
||||
Anche scontando l'OOS del 50% (regime calmo, caveat noto), lev 3-4 dimezza i
|
||||
tempi tenendo il DD sotto il 10%. Caveat: il modello è lineare — non cattura
|
||||
margine, code grasse, slippage che cresce col notional, e gli sleeve senza stop
|
||||
(PAIRS/SH01) a leva alta hanno code peggiori del modello. Proposta sobria:
|
||||
**lev 2→3 subito** (DD full 5.2% = ancora metà del PORT02 storico), rivalutare
|
||||
4 dopo un mese di ledger reale pulito.
|
||||
|
||||
## 2. FADE 15m — la candidata nuova che PASSA il probe
|
||||
|
||||
MR01/02/07 a 15m, parametri live 1h non ri-tunati (anti-overfit), fee 0.10% RT:
|
||||
|
||||
- **Tutti e 6 gli sleeve positivi**, OOS 2025-26 positivo ovunque, fee 2x OK
|
||||
(Sh 1.6-2.9 — margine ampio).
|
||||
- **BTC 15m domina il suo 1h**: MR01 Sh 3.37 vs 2.76 con META' del DD
|
||||
(15.1% vs 31.7%); MR02 3.49 vs 3.29 (DD 10.8 vs 18.7).
|
||||
- ETH 15m leggermente sotto il 1h in Sharpe ma OOS molto più grande in valore
|
||||
assoluto (4x trade = compounding più veloce; MR02 +22052 vs +9560).
|
||||
- Infrastruttura live 15m GIA' esistente (fetch sub-orario del BLEND pairs).
|
||||
|
||||
**Prossimi passi obbligati prima del deploy** (metodologia standard):
|
||||
gate PORT06 con correlazione 15m↔1h (se ~1 sostituire, se bassa aggiungere),
|
||||
griglia parametri al 15m, validazione worker, caveat flat ETH 15m (14-30%
|
||||
storico — per le fade single-leg il fill flat è meno tossico che per i pairs,
|
||||
ma va guardato con flat-aware engine).
|
||||
|
||||
## 3. PAIRS nuove — BOCCIATE (stale-print illusion, di nuovo)
|
||||
|
||||
Sweep onesto delle 19 coppie mai testate (config universale pre-registrata
|
||||
n=50 z2.0/0.5 max72): 8 candidate con Sh 1.5-4.3... MA le gambe alt hanno
|
||||
88-98% barre flat (ADA 98%, LTC 97%, DOGE 91%, XRP 88%, BNB 88%) e con
|
||||
`flat_skip=True` muoiono quasi tutte (BTC/ADA 4.33→0.17, ETH/DOGE 3.79→0.46;
|
||||
migliore superstite ETH/XRP 1.34 < le 5 deployate). Identica classe di
|
||||
illusione del XEX su DOGE/SOL (stessa giornata, `xex_divergence_research.py`).
|
||||
**PAXG idem**: 92% flat su Deribit → chiuso anche il ramo "oro".
|
||||
|
||||
NB: questo getta anche una luce nuova sulle gambe alt dei pairs GIA' deployati
|
||||
(ADA/LTC/SOL hanno flat share altissime nel parquet) — il loro ledger reale
|
||||
shadow è il banco di prova giusto e finora regge, ma teniamolo d'occhio.
|
||||
|
||||
## 4. CAPITALE — domina tutto
|
||||
|
||||
A config attuale: €50/g ≈ €24k di capitale. Ogni € aggiunto accorcia
|
||||
linearmente; nessuna ricerca batte un deposito. In più, a ~€20k si sbloccano
|
||||
in esecuzione reale i 4 book multi-asset oggi solo paper (TR01/ROT02/TSM01/XS01).
|
||||
|
||||
## Sintesi operativa
|
||||
|
||||
Ordine d'impatto: **capitale > leva (2→3) > fade 15m (da gateare) >>** tutto il
|
||||
resto. Le vie "nuova strategia esotica" (pairs nuove, PAXG, XEX) sono tutte
|
||||
morte oggi sotto il test di esecuzione realistica — la lezione del giorno è che
|
||||
su questo testnet ogni edge va validato col **book/flat-aware engine** prima di
|
||||
crederci.
|
||||
@@ -1,57 +0,0 @@
|
||||
# 2026-06-12 — FADE TF SWEEP: 1m / 2m / 5m / 10m / 30m (post-swap 15m)
|
||||
|
||||
Richiesta utente: estendere l'analisi timeframe dei fade oltre il 15m appena
|
||||
deployato (v1.1.30). Script: `scripts/analysis/fade_tf_sweep.py`.
|
||||
Dati: parquet locale (5m/15m/30m full-history; 10m = resample dal 5m, unit-safe);
|
||||
1m/2m da Cerbero (120 giorni recenti — la storia 1m locale non esiste: esclusa
|
||||
dal refresh notturno per costo, 2m/10m non sono intervalli nativi del v2).
|
||||
|
||||
## A. Storia completa (engine canonico, OOS da 2024-10, fee 0.10% RT)
|
||||
|
||||
OOS Sharpe per timeframe (e OOS Sharpe a fee 2x del peggiore):
|
||||
|
||||
| tf | MR01_BTC | MR02_BTC | MR07_BTC | MR01_ETH | MR02_ETH | MR07_ETH | worst f2x |
|
||||
|----|---------|---------|---------|---------|---------|---------|-----------|
|
||||
| 5m | 3.66 | 1.90 | 4.12 | 5.31 | 6.54 | 5.52 | **MR02_BTC −1.70** |
|
||||
| 10m | 2.62 | 2.69 | 3.31 | 5.32 | 6.49 | 5.59 | MR02_BTC 0.32 |
|
||||
| 15m (live) | 1.94 | 2.30 | 2.37 | 4.94 | 6.40 | 4.44 | MR02_BTC 0.60 |
|
||||
| 30m | 1.35 | 2.32 | 1.56 | 3.25 | 5.23 | 2.81 | MR02_BTC 1.40 |
|
||||
|
||||
**La frontiera è monotona**: più il tf scende, più Sharpe sale (MR01/MR07)… e più
|
||||
il margine fee si assottiglia. A fee 2x MR02_BTC muore a 5m e resta fragile a 10m.
|
||||
MR02 (donchian) fa 3-6x i trade degli altri: è la strategia più esposta al churn.
|
||||
|
||||
## B. Finestra comune recente (2026-02-12 → 06-12, il regime CORRENTE)
|
||||
|
||||
- **MR02 sotto i 15m è un disastro**: 1m −64%, 2m −44%, 5m −22% (fee-death).
|
||||
- **MR01 a 1m brilla** (ETH +60.6%, Sh 5.7; BTC +33.5%) ma **muore a fee 2x**
|
||||
(unico sopravvissuto MR01_ETH +16.5%): margine troppo sottile per fidarsi.
|
||||
- Flat share a 1m: ETH 25.6%, BTC 13.3% → rischio stale-print alto (la lezione
|
||||
del giorno: pairs-alt/XEX/PAXG).
|
||||
- Il regime recente è CALMO: anche il 5m vi è fiacco (+4.8/−22.9/+3.7 BTC).
|
||||
I tf veloci pagano nella volatilità, non nella calma — il loro vantaggio
|
||||
full-history viene dai regimi mossi (2021-22, 2024).
|
||||
|
||||
## C. Correlazione col 15m live (daily, storia completa)
|
||||
|
||||
5m↔15m media **0.46**, 10m↔15m media **0.53** (range 0.28-0.81). Diversificazione
|
||||
parziale: un eventuale ADD del 10m avrebbe senso ma è meno pulito del salto
|
||||
1h→15m (che era a 0.26).
|
||||
|
||||
## Verdetto
|
||||
|
||||
- **1m / 2m: CHIUSI.** Fee-margin nullo a stress, microstruttura flat pesante,
|
||||
validazione full-history impraticabile. Non deployare mai MR02 sotto i 15m.
|
||||
- **5m: no-swap.** L'edge c'è ma MR02_BTC muore a fee 2x — viola il criterio di
|
||||
robustezza fee che tutte le strategie deployate rispettano.
|
||||
- **10m: in WATCHLIST.** Quasi l'edge del 5m con più margine (f2x 0.32 resta
|
||||
sotto la soglia di comfort per MR02_BTC; MR01/MR07 reggono bene). Possibile
|
||||
ADD selettivo (solo MR01/MR07?) da gateare su PORT06 più avanti — NON ora:
|
||||
il 15m è live da poche ore, un cambio alla volta e si lascia parlare il
|
||||
ledger reale.
|
||||
- **15m: confermato** come ginocchio della frontiera margine-fee/rendimento.
|
||||
|
||||
Collaterale tecnico: bug di resample scoperto e fixato nello sweep — pandas 2.x
|
||||
conserva `datetime64[ms]` da `to_datetime(unit="ms")`, quindi `.view(int64)//10**6`
|
||||
divide due volte e manda i timestamp nel 1970 (equity piatta silenziosa). Usare
|
||||
`(index - EPOCH) // pd.Timedelta(milliseconds=1)`.
|
||||
@@ -1,78 +0,0 @@
|
||||
# 2026-06-12 — GATE PORT06: fade 15m PROMOSSI (tutte e tre le varianti)
|
||||
|
||||
Seguito del probe ACCEL50: i 6 sleeve fade (MR01/02/07 × BTC/ETH) a 15m,
|
||||
parametri live 1h NON ri-tunati, engine canonico `build_trades`/`fade_daily_equity`
|
||||
parametrizzato sul timeframe. Script: `scripts/analysis/fade15m_port06_gate.py`.
|
||||
|
||||
## Risultati
|
||||
|
||||
**[1] Parità.** Builder locale a 1h == sleeve canonico, diff 0.00 esatto su tutti e 6.
|
||||
|
||||
**[2] Standalone (daily, pos 0.15 lev 3, fee 0.10% RT).** Il 15m batte il twin 1h
|
||||
quasi ovunque; OOS Sharpe: MR01_ETH 4.94 (vs 1.10), MR02_ETH 6.40 (vs 4.72),
|
||||
MR07_ETH 4.44 (vs 1.97), MR07_BTC 2.37 (vs 1.59). Fee 2x: regge ovunque tranne
|
||||
MR02_BTC (OOS 0.60 — il piu' fee-sensitive, ma a fee reali e' il migliore BTC).
|
||||
|
||||
**[3] Correlazione 15m↔1h: media 0.26** (range 0.16-0.41) — più decorrelato del
|
||||
pairs 15m promosso a 0.37. NON è la stessa scommessa più veloce: è un edge a
|
||||
orizzonte diverso.
|
||||
|
||||
**[4] Gate PORT06** (cap PAIRS 0.33 / SHAPE 0.0588):
|
||||
|
||||
| variante | FULL CAGR | FULL DD | FULL Sh | OOS CAGR | OOS DD | OOS Sh |
|
||||
|----------|-----------|---------|---------|----------|--------|--------|
|
||||
| BASELINE (1h) | 74% | 3.46% | 7.34 | 111% | 1.48% | 10.07 |
|
||||
| **ADD (+6 sleeve 15m)** | 85% | **2.73%** | 8.02 | 125% | **1.38%** | **10.48** |
|
||||
| SWAP (15m al posto 1h) | **101%** | 2.47% | 8.13 | **163%** | 2.09% | 10.86 |
|
||||
| BLEND 50/50 | 87% | 2.31% | 8.06 | 136% | 1.77% | 10.82 |
|
||||
|
||||
Tutte e tre PROMOSSE dal criterio standard (OOS Sharpe non peggiora E DD scende).
|
||||
|
||||
**[5] Anti-illusione flat (il check che ha ucciso pairs-alt e XEX/DOGE).**
|
||||
ETH 15m ha 14-30%/anno di candele flat. Con flat-entry-skip l'edge SOPRAVVIVE:
|
||||
MR01_ETH Sh 3.11→2.85 (OOS 4.94→4.60), MR02_ETH 4.72→4.63, MR07_ETH 3.76→3.55;
|
||||
BTC invariato (≤0.01). Coerente col finding registrato 2026-05-28. La quota di
|
||||
ritorno persa (~30-40% del FULL ETH) è il caveat slippage onesto: il ledger
|
||||
reale shadow sarà il giudice, come per il pairs 15m.
|
||||
|
||||
## Raccomandazione
|
||||
|
||||
**ADD** è la promozione più pulita: migliora TUTTE le metriche senza buttare il
|
||||
track record live dei 6 sleeve 1h (SWAP rinuncia alla config validata dal vivo;
|
||||
il suo OOS DD peggiora 1.48→2.09). In subordine BLEND (miglior FULL DD 2.31%).
|
||||
|
||||
## Per il deploy (non fatto qui)
|
||||
|
||||
1. `_defs.py`: 6 SleeveSpec nuovi `MR0x_{asset}_15M` con `tf: 15m` nei params.
|
||||
2. Runner: estendere il fetch sub-orario (già esistente per PR_ETHBTC_15M) ai
|
||||
fade 15m; verificare lookback (EMA200 a 15m = 50h → bastano ~2200 barre).
|
||||
3. Validazione worker a 15m (replay == backtest, come validate_worker_pairs).
|
||||
4. Sizing: a peso pieno i 6 sleeve 15m raddoppiano la famiglia FADE; valutare
|
||||
position_size ridotto come il blend pairs (il gate ADD qui è già a peso pieno
|
||||
e migliora comunque, ma il caveat slippage 15m suggerisce prudenza).
|
||||
5. MR02_BTC 15m è il più fee-sensitive (fee2x OOS 0.60): monitorare le fee reali.
|
||||
|
||||
## Addendum — DEPLOY: SWAP SECCO (stessa giornata, scelta utente)
|
||||
|
||||
L'utente ha scelto **SWAP** (la variante a CAGR più alto), consapevole dei due
|
||||
costi discussi: OOS DD 1.48→2.09% e perdita della maturità operativa 1h (la
|
||||
meccanica live — EXIT-16 confirm, TP_PHANTOM, TP resting — gira 4x più veloce
|
||||
su un feed testnet con wick anomali; il gate misura l'edge, non la robustezza
|
||||
operativa). Proposta alternativa staged (ADD temporaneo 1-2 settimane, poi
|
||||
spegnere il 1h) declinata: "swap secco".
|
||||
|
||||
Implementazione (deliberatamente minima, sid INVARIATI → pesi/alloc/epoche
|
||||
intatti):
|
||||
- `_defs.py`: FADE specs → `tf="15m"` (DIP01 resta 1h: non era nel gate).
|
||||
- `combine_portfolio.py`: `FADE_TF="15m"` nel builder canonico → le due facce
|
||||
(backtest/live) restano sulla STESSA definizione; il lock di parità
|
||||
(`test_backtest_parity`) confronta le facce fra loro e resta verde.
|
||||
- Runner: NESSUNA modifica (il fetch sub-orario BTC/ETH 15m esisteva già per il
|
||||
blend pairs; `_spec_assets_tf`/`_series_for` sono generici).
|
||||
- Worker: nuove dir `*__15m` (stato 1h preservato in `*__1h`, worker flat al
|
||||
momento dello switch). Esecuzione reale invariata (match per nome MR01/02/07).
|
||||
- max_bars=24 barre ora = 6h; EXIT-16 confirm sulla barra 15m completata.
|
||||
|
||||
Monitor post-deploy: stop-rate e divergenza sim/reale dei fade 15m
|
||||
nell'hourly report; fee reali su MR02_BTC; STALE_FEED (le barre flat 15m
|
||||
sono più frequenti che a 1h).
|
||||
@@ -1,51 +0,0 @@
|
||||
# 2026-06-12 — Sweep migliorie/strategie nuove (sera, post-swap 15m)
|
||||
|
||||
Richiesta: cercare altre migliorie da implementare o strategie nuove. Tre
|
||||
esperimenti + una miglioria di codice.
|
||||
|
||||
## 1. INIT_LINEAGE — eredità capitale al cambio timeframe (IMPLEMENTATO)
|
||||
|
||||
`StrategyWorker._inherit_lineage_capital`: al primo avvio (niente status.json)
|
||||
il worker eredita `capital`/`real_capital` dal worker più recente di stessa
|
||||
strategia+asset su altro tf (glob `{strategy}__{asset}__*`). MAI la posizione.
|
||||
Nato dallo swap 1h→15m di oggi: i worker nuovi partivano dall'allocazione del
|
||||
pool scartando il PnL del gemello (−16.8 di equity fantasma, riallineata a mano
|
||||
col seed). Il prossimo swap non avrà bisogno di seed manuale.
|
||||
Test: `tests/portfolio/test_capital_lineage.py` (eredita / no-sibling / resume).
|
||||
|
||||
## 2. Gate 10m ADD selettivo (MR01/MR07) — BOCCIATO, watchlist chiusa
|
||||
|
||||
Baseline aggiornata al PORT06 post-swap (fade 15m): ADD di 4 sleeve 10m
|
||||
(MR01/MR07 × BTC/ETH, MR02 escluso perché fee-fragile) dà FULL Sh 8.13→8.33 e
|
||||
DD 2.47→2.28, ma **OOS Sharpe 10.86→10.76** → fallisce il criterio standard.
|
||||
Il 15m cattura già quasi tutto l'alpha veloce (corr 10m↔15m 0.53). Chiuso.
|
||||
|
||||
## 3. XSEC breadth (universo 8 → 14/15) — direzione GIUSTA, venue SBAGLIATO
|
||||
|
||||
La breadth è la leva classica delle strategie cross-sectional. Due banchi:
|
||||
|
||||
- **Hyperliquid 15 coin** (dati REALI, ma profondità v2 limitata a ~207 giorni,
|
||||
regime calmo recente): CORE-8 **−6.2%** (Sh −1.38, coerente col
|
||||
dispersion-gate live che tiene XS01 fuori in questo regime) vs FULL-15
|
||||
**+9.4%** (Sh 1.58, WR 41→51%). La breadth trasforma un book perdente in
|
||||
vincente — **sui prezzi veri**.
|
||||
- **Deribit 14 coin** (storia piena 2022-10→2026-06, +AVAX/DOT/TRX/LINK/BCH/UNI,
|
||||
parity del sim verificata ESATTA vs `xsec_sim`): FULL Sh 1.48→**1.22**, OOS
|
||||
4.66→**3.41**, fee 2x da −0.33 a **−1.45**. PEGGIO dell'8: le 6 gambe nuove
|
||||
hanno chiusure flat al **91-99%** e il loro "momentum" è rumore stale che
|
||||
corrompe il ranking cross-section (3ª conferma della lezione del giorno:
|
||||
pairs-alt, XEX/DOGE, ora XSEC).
|
||||
|
||||
**Conclusione:** l'espansione dell'universo XS01 è promettente ma bloccata dalla
|
||||
qualità dati del venue. Sblocco strategico: **routing dati Hyperliquid** nel
|
||||
runner (il client v2 già supporta `exchange="hyperliquid"`) + accumulo storia
|
||||
HL in avanti. Rivalutare quando HL avrà ≥12-18 mesi di storia utile.
|
||||
|
||||
## Direzioni aperte residue (non attaccate oggi)
|
||||
|
||||
- **Put settimanale standing** (catastrofe-cap): unica struttura opzioni
|
||||
eseguibile, da gateare coi premi reali cerbero-bite (~1%/mese il 10% OTM).
|
||||
Harness `option_overlay_lab.py` pronto.
|
||||
- **Hyperliquid come venue di esecuzione** (oltre che dati): aprirebbe fades su
|
||||
alt liquidi con fill realistici; lavoro infrastrutturale grosso.
|
||||
- 10m fade: chiuso oggi. 1m/2m/5m: chiusi oggi. Pairs nuove/PAXG/XEX: chiusi oggi.
|
||||
@@ -1,108 +0,0 @@
|
||||
# 2026-06-12 — Reconcile resting + guard feed↔book + epoca report (v1.1.27)
|
||||
|
||||
## Contesto: la notte ha validato (di nuovo) il tema osservabilità
|
||||
|
||||
Due eventi nelle 24h hanno motivato la tornata:
|
||||
|
||||
1. **MR02_BTC (06:00):** il TP resting LIMIT ha fillato sul **book reale** a 60481
|
||||
nella notte (+6.55 USD reali) mentre il **feed sim** non è mai sceso sotto 63285
|
||||
(−443 bps di divergenza, sim chiuso a time_limit con −1.25). Il disaster-SL è
|
||||
risultato `order_not_found` alla cancel (probabile auto-cancel a posizione flat).
|
||||
Caso SPECULARE del TP_PHANTOM: lì il feed stampa wick che il book non ha; qui il
|
||||
book si muove e il feed non lo vede. Real-truth ha bookato il reale (corretto),
|
||||
ma il sistema se n'è accorto solo ORE dopo, al close sim.
|
||||
2. **Incidente venue (dalle ~09:47):** il conto Deribit testnet ha iniziato a
|
||||
rifiutare ordini (`locked_by_admin`, `invalid_reduce_only_order`) e le posizioni
|
||||
sul conto sono cambiate da sole (ETH LONG 0.141 con avg 1849.5 — prezzo vecchio
|
||||
di settimane): **rollback/reset admin del testnet**, non un nostro bug. Difese OK:
|
||||
`REAL_CLOSE_PARTIAL`, leg-fail con unwind, orfani registrati (ETH −0.026,
|
||||
SOL +0.7), `sim_fallback` dichiarato. MA: il reconciler delle 11:40 è **morto in
|
||||
silenzio** su un 502 — il guardiano che non suona è indistinguibile dal tutto-ok.
|
||||
|
||||
## Fatto
|
||||
|
||||
### 1. Reconcile degli ordini RESTING (cron :40, read-only)
|
||||
|
||||
- **cerbero-mcp 9a74052:** nuovo endpoint Deribit `get_open_orders`
|
||||
(`private/get_open_orders_by_currency`; per i trigger untriggered interrogare
|
||||
anche `type='trigger_all'` e merge per order_id). Pattern già presente per
|
||||
Hyperliquid/IBKR. Rebuild + smoke su testnet (book vuoto == stato atteso).
|
||||
- **`books.expected_resting()`:** TP/DSL attesi dai libri dei worker single-leg
|
||||
in posizione reale (i pairs non hanno resting).
|
||||
- **`reconcile_account.compute_resting_drift()`** — tre classi:
|
||||
`FILLED_UNBOOKED` (atteso non in book + fill nel trade history col worker ancora
|
||||
in posizione = il caso MR02), `MISSING` (atteso, non in book, zero fill — per il
|
||||
DSL triggered il fill ha order_id NUOVO → appare qui e il drift posizioni
|
||||
completa), `STALE` (in book con label di un nostro worker ma nessun libro:
|
||||
fillerebbe a sorpresa). Anti-race come per le posizioni; alert `RESTING_DRIFT`.
|
||||
- **`RECONCILE_FAIL`:** il main è ora guardato — su eccezione alert Telegram +
|
||||
exit 2 (fix del crash silenzioso delle 11:40).
|
||||
|
||||
### 2. Guard FEED_BOOK_GAP nel runner
|
||||
|
||||
`_check_feed_book_gap`: ad ogni poll confronta il close della candela in corso col
|
||||
**mark dello strumento d'ESECUZIONE** (USDC, `get_ticker_batch`, 1 chiamata);
|
||||
oltre soglia (`overrides.feed_book_gap_bps`, default 150) → alert per episodio,
|
||||
recovery con isteresi a soglia/2, fail-open su errori di rete. Le decisioni
|
||||
restano sul feed (il sim è la verità che guida): questo dice solo QUANDO i fill
|
||||
reali possono divergere dal sim. Avrebbe segnalato il caso MR02 in tempo reale.
|
||||
|
||||
### 3. Epoca v1.1.26 nell'hourly_report
|
||||
|
||||
I conteggi CHIUSI cumulativi erano inquinati dal churn TP-fantasma dell'11-06
|
||||
17:32–17:58 (~24 giri pre-fix). Nuova riga `epoca v1.1.26+ (TP_PHANTOM attivo)`
|
||||
da `EPOCH_V1126 = 2026-06-11T21:40` (deploy del gate): oggi legge **7/1** contro
|
||||
il 18/17 storico — è il numero da confrontare col backtest da qui in poi.
|
||||
|
||||
## Test e deploy
|
||||
|
||||
`pytest` 121 passed (114 + 7 nuovi: `test_reconcile_resting.py`,
|
||||
`test_feed_book_gap.py`). Deploy **v1.1.27** (runner nel container; reconciler e
|
||||
hourly_report girano da host → già attivi). cerbero-mcp rebuildato (endpoint).
|
||||
|
||||
## Aperto / lezioni
|
||||
|
||||
- **Drift ETH +0.167 non spiegato** dal rollback testnet: quando il conto si
|
||||
sblocca serve `reset_flatten` + riallineamento ledger (decisione utente).
|
||||
- I **residui dei close single-leg falliti** (`REAL_CLOSE_PARTIAL`, es. MR07
|
||||
0.102) NON finiscono in `orphan_legs` → il reconciler li vede come drift NON
|
||||
spiegato. Estendere la registrazione orfani anche al single-leg è il naturale
|
||||
passo successivo (punto in analisi sviluppi).
|
||||
- Il testnet può **riscrivere il conto sotto i piedi** (lock + rollback): nessuna
|
||||
invariante "il conto cambia solo per nostri ordini" è affidabile. Il reconciler
|
||||
orario è l'unico rilevatore; valutare cadenza più fitta in presenza di
|
||||
posizioni reali aperte.
|
||||
|
||||
## Addendum (pomeriggio, v1.1.28): orfani single-leg + circuit-breaker venue-lock
|
||||
|
||||
I due punti promossi dall'analisi sviluppi, entrambi figli dell'incidente di oggi:
|
||||
|
||||
1. **Orfani anche per i close single-leg.** `REAL_CLOSE_PARTIAL` ora registra la
|
||||
quota residua in `StrategyWorker.orphan_legs` (stessa semantica dei pairs,
|
||||
persistita in status.json, letta da `books.real_books`) → il reconciler vede
|
||||
il drift come SPIEGATO invece che anomalo (il caso MR07 0.102 ETH delle 09:47
|
||||
restava invisibile ai libri). Inoltre `_close_position` ora persiste lo stato
|
||||
a fine booking (prima solo al save del tick: un crash li' in mezzo perdeva
|
||||
capital e orfano). NB: nessun save a meta' chiusura — con `real_in_position`
|
||||
ancora true l'orfano conterebbe doppio nei libri.
|
||||
2. **Circuit-breaker venue-lock in `ExecutionClient`.** Dopo `lock_trip=3` reject
|
||||
'locked' consecutivi (es. `locked_by_admin` di oggi) le APERTURE sono sospese
|
||||
senza toccare l'API (Fill failed → path REAL_OPEN_FAIL/sim_fallback esistente;
|
||||
per i pairs entrambe le gambe rifiutate localmente → niente leg parziali da
|
||||
unwindare, niente fee sprecate). Le CHIUSURE si tentano SEMPRE (path gia'
|
||||
sicuro: partial/orphan/netting) e un loro reject 'locked' rinfresca il
|
||||
cooldown. Riarmo: dopo `lock_cooldown_s=900` la prossima apertura fa da probe.
|
||||
Alert `VENUE_LOCK` al trip + RIENTRATO al primo ordine accettato.
|
||||
|
||||
Test: `test_single_leg_orphan.py`, `test_venue_lock_breaker.py` (126 passed).
|
||||
|
||||
## Chiusura incidente (13:05): testnet sbloccato, conto riallineato
|
||||
|
||||
Sequenza eseguita a venue sbloccato: stop runner → `reset_flatten` (chiusi i due
|
||||
artefatti del rollback: ETH long 0.141 @1664.25, SOL long 0.7 @66.651, conto FLAT)
|
||||
→ svuotati gli `orphan_legs` di ETH_SOL (le quote orfane non esistono piu' sul
|
||||
conto post-flatten; edit a container fermo, altrimenti il worker li riscrive
|
||||
dalla memoria) → restart. **Reconciler: OK — conto allineato ai libri** (posizioni
|
||||
e resting), runner healthy, log puliti. Il ledger NON e' stato toccato: i booking
|
||||
dell'incidente erano gia' dichiarati (`sim_fallback`/real) e l'equity (€2020.82)
|
||||
resta la verita' contabile del paper.
|
||||
@@ -1,64 +0,0 @@
|
||||
# 2026-06-12 — XEX: discordanze Deribit testnet vs Hyperliquid
|
||||
|
||||
**Domanda.** I prezzi Deribit (testnet, dove eseguiamo) e Hyperliquid (feed
|
||||
realistico, proxy della realtà) divergono? La divergenza è usabile per fare trade?
|
||||
|
||||
**Strumenti comuni validati:** 9 base-coin (ADA, AVAX, BNB, BTC, DOGE, ETH, PAXG,
|
||||
SOL, TRUMP). Analisi su BTC/ETH (inverse, liquidi) + SOL/DOGE (lineari USDC).
|
||||
Script: `scripts/analysis/xex_divergence_research.py`.
|
||||
|
||||
## Misure (1h, 2026-03-01 → 2026-06-12, ~2470 barre)
|
||||
|
||||
| Coin | spread medio | std | half-life | flat Deribit | Δbook−HL live |
|
||||
|------|--------------|-----|-----------|--------------|----------------|
|
||||
| BTC | −0.29% | 1.25% | 7.3h | 6% | **−0.97%** |
|
||||
| ETH | −0.55% | 1.33% | 5.1h | 9% | **−1.54…−2.16%** |
|
||||
| SOL | −0.38% | 3.60% | 5.2h | 35% | −0.05% (allineato) |
|
||||
| DOGE | +0.34% | 1.88% | 4.2h | 87% | +0.16% (allineato) |
|
||||
|
||||
Per standard mainnet questi spread sono enormi (reale <0.05%): la divergenza è
|
||||
l'artefatto del feed testnet che periodicamente si stacca dalla realtà e rientra.
|
||||
|
||||
## Findings
|
||||
|
||||
1. **Lo spread è mean-reverting e il gap viene chiuso ANCHE da Deribit** (il lato
|
||||
che possiamo tradare): beta del ritorno futuro Deribit sullo spread negativo e
|
||||
crescente con l'orizzonte (ETH −0.36, BTC −0.23 a 24h). Non è solo HL che si
|
||||
muove.
|
||||
2. **Trappola smascherata — stale print arb.** Il backtest su DOGE dava Sharpe
|
||||
6.7 (OOS 9.1!) e SOL 2.7, MA il book live di entrambi sta attaccato a HL
|
||||
(±0.16%) mentre i print restano vecchi (DOGE 87% barre flat): l'edge era
|
||||
**finzione** — i fill reali avverrebbero al prezzo vero, non al print stantio.
|
||||
Stessa classe di illusione del look-ahead squeeze: il backtest compra un
|
||||
prezzo a cui nessuno fa fill.
|
||||
3. **Su BTC/ETH inverse la dislocazione è REALE: è il book stesso a essere
|
||||
spostato** (misurato live: bid/ask −0.97% / −1.54…−2.16% sotto HL con depth
|
||||
>$1M sui primi 5 livelli, spread bid/ask 1-3 bps). Lì si può davvero comprare
|
||||
sotto/vendere sopra la realtà.
|
||||
4. **Edge netto moderato e timing-sensitive** (fee 0.10% RT, entry |s|≥1%, exit
|
||||
|s|≤0.25% o 24 barre): BTC FULL Sh 1.0 / OOS 2.05; ETH FULL 2.28 / OOS 1.37.
|
||||
Con entry ritardato di 1 barra (stress staleness) BTC FULL→0, ETH OOS→0.1:
|
||||
con half-life di 3-7 ore, un'ora di ritardo erode quasi tutto. Un'eventuale
|
||||
implementazione live deve leggere il **book in tempo reale** (non il close 1h)
|
||||
— a quel punto il lag reale è minuti, non un'ora, e l'edge eseguibile sta fra
|
||||
lag0 e lag1.
|
||||
|
||||
## Segnale live al momento dell'analisi
|
||||
|
||||
ETH book Deribit **−2.16%** sotto HL (z=−1.7, 6.7° percentile storico), BTC
|
||||
−0.97%: entrambi in zona "long Deribit" per il fade dello spread. (Solo
|
||||
osservazione: nessun deploy senza gate.)
|
||||
|
||||
## Verdetto e prossimi passi
|
||||
|
||||
- Discordanza tradabile trovata: **fade dello spread D/H su BTC/ETH-PERPETUAL,
|
||||
segnale dal book, soglia ~1%, exit a convergenza o 24h**. Da NON estendere a
|
||||
DOGE/SOL (illusione stale-print).
|
||||
- È un **edge di testnet** (non trasferibile a mainnet): legittimo per il
|
||||
paper/shadow corrente, ma va dichiarato per quello che è.
|
||||
- Prima di qualsiasi deploy, metodologia standard: gate PORT06 (correlazione con
|
||||
le fade esistenti, che già fadano in parte questi stessi spike testnet —
|
||||
rischio doppio conteggio), robustezza griglia, validazione worker.
|
||||
|
||||
Script: `scripts/analysis/xex_divergence_research.py` (fetch v2 due exchange,
|
||||
tabella convergenza, backtest lag0/lag1, book reality-check live).
|
||||
@@ -1,40 +0,0 @@
|
||||
# 2026-06-13 — Dashboard web PORT06 (stato live + PnL + grafici + trade)
|
||||
|
||||
Richiesta utente: frontend per visualizzare lo stato con PnL totale e per-strategia,
|
||||
grafici, e liste trade (attivi in tempo reale + chiusi).
|
||||
|
||||
## Cosa
|
||||
|
||||
`src/live/dashboard.py` — server **stdlib `http.server`** (zero nuove dipendenze),
|
||||
legge i file `data/` e serve:
|
||||
- `GET /api/state` → JSON con tutto lo stato calcolato
|
||||
- `GET /` → single-page HTML (vanilla JS, polling ogni 5s)
|
||||
|
||||
Contenuto della pagina:
|
||||
- **KPI**: equity, PnL totale (€ e %), max DD, peak
|
||||
- **Grafico equity** (Chart.js da CDN, fallback testuale se offline) dalla
|
||||
`equity.jsonl` del ledger (downsample a 400 punti)
|
||||
- **PnL per strategia** (barre verdi/rosse): realizzato netto fee = Σ `pnl` reali
|
||||
dai CLOSE (REAL-TRUTH), n trade, win-rate, capitale; tag `paper` per i
|
||||
multi-asset non eseguiti, `•aperta` se in posizione
|
||||
- **Trade attivi in tempo reale**: lato, entry, **mark corrente** (Cerbero
|
||||
best-effort, cache 20s), **PnL non realizzato** (€ e %, da `real_entry_notional`),
|
||||
barre/max_bars, distanza al TP, età dello status (⚠ se >15min = stantio)
|
||||
- **Trade chiusi** (ultimi 50): ora, strategia, motivo, PnL reale, sim, esito
|
||||
|
||||
## Deploy
|
||||
|
||||
Servizio docker-compose `dashboard` (stessa immagine del runner, monta gli stessi
|
||||
`data/`, porta **8787**), `restart: unless-stopped` + healthcheck sull'API.
|
||||
Accesso: `http://<host>:8787`. **Nessuna auth** → solo rete interna/VPN, non
|
||||
esporre pubblicamente. Avvio: `docker compose up -d --build dashboard` (il runner
|
||||
non viene toccato).
|
||||
|
||||
uv run python -m src.live.dashboard --port 8787 # anche standalone su host
|
||||
|
||||
## Note
|
||||
|
||||
- Il PnL per-strategia usa il PnL REALE (real_truth), coerente col report orario.
|
||||
- I 6 fade 1h ritirati dallo swap restano in lista (hanno storico CLOSE): flat,
|
||||
mostrano il loro PnL realizzato storico accanto ai gemelli 15m attivi.
|
||||
- Unrealized € sui pairs non mostrato (posizione a 2 gambe, z-based) → "pairs (z)".
|
||||
@@ -1,49 +0,0 @@
|
||||
# 2026-06-13 — Report ricorrente LEDGER REALE vs BACKTEST (il gate per scalare)
|
||||
|
||||
## Perché
|
||||
|
||||
Domanda dell'utente: "come cresco il capitale a 12k". Risposta: il prerequisito
|
||||
prima di mettere soldi veri è che il **ledger reale combaci col backtest** —
|
||||
soprattutto lo slippage del 15m appena deployato. Questo report rende quel gate
|
||||
un dato osservabile, non un'opinione.
|
||||
|
||||
Insight chiave: per gli sleeve eseguiti (6 fade 15m, DIP01, 6 pairs, SH01) il
|
||||
**sim del worker == backtest canonico PER COSTRUZIONE** (validato). Quindi
|
||||
"reale vs backtest" = "reale vs sim" = la **fuga di esecuzione**: slippage +
|
||||
fee reali vs assunte + effetti netting/phantom/sim_fallback.
|
||||
|
||||
## Cosa misura
|
||||
|
||||
`scripts/analysis/ledger_vs_backtest.py` (read-only: solo trades.jsonl +
|
||||
status.json, nessuna rete → affidabile in cron):
|
||||
- PnL realizzato sim vs reale (Σ e per-trade) → **LEAKAGE** € e per-trade (bottom line)
|
||||
- slippage ingressi (REAL_OPEN) e uscite-a-mercato (REAL_CLOSE; escluse le uscite
|
||||
da TP resting, fill maker al livello = no slippage)
|
||||
- fee reali vs assunte (0.10% RT)
|
||||
- trade `sim_fallback` (reale mai eseguito/fillato) = quota NON coperta dal reale
|
||||
- ledger per-sleeve: real_capital vs capital (sim)
|
||||
- **verdetto** 🟢/🟡/🔴: <10 trade = campione piccolo; leakage basso+slippage ≤15bps
|
||||
= verde (si può pensare a scalare); slippage >40bps = rosso (edge erode, NON scalare)
|
||||
|
||||
## Clean-start (importante)
|
||||
|
||||
Una finestra mobile pura includerebbe l'**incidente testnet pre-fix**: a 7g il
|
||||
report dà sim +82 vs reale +5 (🔴) — ma è gonfiato dai +4% FANTASMA che il sim
|
||||
bookava e il reale no, prima di TP_PHANTOM (v1.1.23), netting (v1.1.25) e
|
||||
ribilancio-conservativo (v1.1.31). Lo scheduler usa **`--since 2026-06-13`** →
|
||||
accumula SOLO dati post-fix, e diventa statisticamente significativo coi giorni.
|
||||
Finestra pulita oggi: 1 trade, leakage +0.07, slippage ingresso 12-29 bps.
|
||||
|
||||
## Scheduling
|
||||
|
||||
Cron host (come reconcile/hourly_report), **giornaliero 08:30 UTC**:
|
||||
`ledger_vs_backtest.py --since 2026-06-13 --telegram` → Telegram + log in
|
||||
`~/port06_ledger_vs_backtest.log`. Invio verificato.
|
||||
|
||||
## Come usarlo
|
||||
|
||||
Quando il campione supera ~10-20 trade reali e il verdetto è 🟢 stabile per
|
||||
qualche giorno (leakage per-trade piccolo, slippage medio ≤15 bps), allora il
|
||||
15m regge l'esecuzione e si può passare da testnet a piccolo reale → poi scalare.
|
||||
Se resta 🔴/🟡, l'edge si erode sui fill e NON va scalato: prima si capisce dove
|
||||
perde (slippage ingressi? uscite a mercato? sim_fallback frequenti?).
|
||||
@@ -1,41 +0,0 @@
|
||||
# 2026-06-13 — Orfano da swap: incidente + guard nel reconciler
|
||||
|
||||
## Incidente
|
||||
|
||||
Lo `stato trades` del mattino ha scoperto una **posizione reale orfana**: il
|
||||
worker fade **MR02_BTC 1h** aveva aperto uno short reale (0.0028 BTC @ 64135.5)
|
||||
ieri alle 15:01; lo **swap a 15m (v1.1.30, ~20:48) lo ha rimosso dal config
|
||||
mentre era ancora in posizione** → da allora nessun runner lo gestiva. Stato:
|
||||
|
||||
- conto Deribit: short 0.0028 BTC (il long di apertura del gemello 15m aveva
|
||||
aperto e chiuso nettando via il resto)
|
||||
- il **TP limit (63387.75) era sparito** dal book (cancellato durante il netting
|
||||
della chiusura 15m) → short NUDO, protetto solo dal disaster-SL a +30%
|
||||
- il **reconciler NON allarmava**: lo `status.json` del worker morto dichiarava
|
||||
ancora `real_in_position: true` → conto == libri. Punto cieco: il reconciler
|
||||
leggeva i libri dagli status ma non sapeva quali worker fossero VIVI.
|
||||
|
||||
Chiusura manuale (testnet): buy 0.0028 reduce-only @63766.5 (~+$0.85 netto sullo
|
||||
short), cancel disaster-SL, worker marcato flat, PnL bookato (real_capital
|
||||
181.18→182.03). Conto verificato flat su BTC; SH01_ETH short intatto.
|
||||
|
||||
## Guard implementato
|
||||
|
||||
`reconcile_account.compute_stale_real_positions(max_age_min=15)`: segnala i
|
||||
worker che dichiarano `real_in_position` ma il cui `status.json` è fermo da
|
||||
oltre 15 min. Un worker vivo riscrive lo status a ogni poll (~60s) → la
|
||||
**staleness** è il discriminante robusto e venue-agnostico (cattura
|
||||
ritirati-da-swap, crashati, worker rimossi dal config). Alert Telegram
|
||||
`STALE_REAL_POSITION` (con `--telegram`), incluso nell'exit code e nel verdetto.
|
||||
Gira già al prossimo cron host (:40) — nessun rebuild (lo script gira dal
|
||||
working tree). Test: `tests/portfolio/test_reconcile_resting.py` (stantio
|
||||
flaggato / fresco no / flat-vecchio no).
|
||||
|
||||
## Causa radice e direzione
|
||||
|
||||
La feature `INIT_LINEAGE` di ieri trasferisce il *capitale* al gemello del nuovo
|
||||
timeframe, ma non la *posizione*. Il guard di oggi è la **rete di sicurezza**
|
||||
(rileva e allarma entro un'ora). La **prevenzione** vera — flattare/consegnare la
|
||||
posizione reale del worker ritirato al boot del runner — resta da implementare
|
||||
(va fatta lato runner, con cautela: piazza ordini reali all'avvio). Per ora:
|
||||
swap a conto fade-flat quando possibile, e il reconciler copre il resto.
|
||||
@@ -1,56 +0,0 @@
|
||||
# 2026-06-13 — Equity gonfiata dal ribilancio: +4.77 fantasma (causa + fix)
|
||||
|
||||
## Sintomo
|
||||
|
||||
Report "dall'ultimo reset": equity 2020.53 → 2025.80 (+5.27), ma un solo trade
|
||||
chiuso (MR02_BTC 15m, reale +0.50). Il +4.77 residuo è comparso di colpo a
|
||||
00:01:52 (primo poll dopo mezzanotte UTC = ribilancio giornaliero), senza alcuna
|
||||
chiusura dietro.
|
||||
|
||||
## Causa — doppio conteggio del capitale degli in-position al ribilancio
|
||||
|
||||
`rebalance_allocations` faceva:
|
||||
1. `total_capital = Σ capital di tutti i worker`
|
||||
2. `alloc[sid] = peso × total_capital` per OGNI sid
|
||||
3. ai worker in posizione NON applicava l'alloc (la posizione tiene il suo notional)
|
||||
4. ai flat: `capital = alloc[sid]`
|
||||
|
||||
`update_equity` (ogni poll) = Σ capital. Dopo il ribilancio la somma diventa:
|
||||
|
||||
Σcapital = Σ(peso_i × total) [flat] + Σ(capital_j) [in-pos]
|
||||
= total − Σalloc_j + Σcapital_j
|
||||
= total + Σ(capital_j − alloc_j) ← inflazione
|
||||
|
||||
Cioè i flat si dividevano l'INTERO total (che includeva anche il capitale degli
|
||||
in-position), e gli in-position lo tenevano in più → doppio conteggio.
|
||||
|
||||
Al ribilancio delle 00:01, **MR02_BTC 15m era in posizione** col capitale seedato
|
||||
**181.19** (eredità del gemello 1h, INIT_LINEAGE di ieri) mentre la sua allocazione
|
||||
era ~176.42 → **+4.77** di equity dal nulla. Lo scatenante è stato il seed (capitale
|
||||
ben sopra l'allocazione media) combinato con la posizione aperta al ribilancio; ma
|
||||
il bug era latente da sempre (ogni worker in-pos che devia dall'alloc gonfiava/sgonfiava
|
||||
l'equity al ribilancio successivo).
|
||||
|
||||
## Fix — conservazione (ledger.allocate `reserved`)
|
||||
|
||||
`allocate(weights, reserved={sid: capitale})`: i worker in posizione TRATTENGONO il
|
||||
loro capitale (deployato, non spostabile); i flat si dividono `total − Σreserved`
|
||||
per peso **rinormalizzato sui soli flat**. Così `Σalloc == total_capital` sempre →
|
||||
**l'equity è conservata dal ribilancio** (un ribilancio sposta capitale fra sleeve,
|
||||
non crea valore). `runner.rebalance_allocations` calcola `reserved` dai worker
|
||||
`in_position` e lo passa. Senza `reserved` (default) = comportamento storico
|
||||
(corretto solo a worker tutti flat, es. allocazione iniziale).
|
||||
Test: `tests/portfolio/test_ledger.py::test_alloc_conserves_total_with_reserved`.
|
||||
|
||||
## Correzione dello stato (rimozione del +4.77 già accumulato)
|
||||
|
||||
Equity riportata a **2021.03** = baseline post-seed verificata (2020.53) + unico
|
||||
trade reale (MR02_BTC 15m +0.50). Capitali dei worker del pool scalati ×
|
||||
(2021.03/2025.79) e peak del ledger resettato a 2021.03 (il 2025.80 non è mai
|
||||
stato un massimo legittimo → niente DD fantasma). L'orfano MR02_BTC 1h chiuso a
|
||||
parte (+0.85) resta sul worker ritirato, fuori dal pool.
|
||||
|
||||
## Esito
|
||||
|
||||
Equity = soldi veri: dal reset il trading ha prodotto **+0.50** (1 trade), non +5.27.
|
||||
Deploy con codice fixato (rebuild) così il prossimo ribilancio conserva.
|
||||
@@ -1,149 +0,0 @@
|
||||
# 2026-06-14 — Timing sweep: PAIRS & HONEST su 5/10/15/30m (vs live)
|
||||
|
||||
## Domanda (goal utente)
|
||||
|
||||
Dopo lo swap fade 1h→15m (v1.1.30), i **pairs** e le **honest** beneficiano dello stesso
|
||||
trattamento — girare su timeframe più veloci (5/10/15/30 min)?
|
||||
|
||||
Script: `scripts/analysis/timing_sweep_pairs_honest.py` (riusa i motori canonici
|
||||
`pairs_sim_flat`, replica DIP intrabar verificata == `dip_market_gated(market_n=0)`, gate
|
||||
PORT06 == `pairs30m_gate`/`dip01`). Niente re-tuning dei parametri al cambio TF (anti-overfit,
|
||||
come lo swap fade). Tutto netto, leva 3x, OOS held-out (da 2024-10).
|
||||
|
||||
## Vincolo dati (hard — definisce lo scope)
|
||||
|
||||
Solo **BTC/ETH** hanno 5m/15m/30m in locale (10m = resample causale da 5m). **TUTTI gli alt**
|
||||
(ADA/BNB/DOGE/LTC/SOL/XRP) sono **SOLO 1h**. Quindi:
|
||||
- **PAIRS:** solo **ETH/BTC** è sweepabile sub-orario. Gli altri 4 pair (gambe alt: LTC/ETH,
|
||||
ADA/ETH, BTC/LTC, ETH/SOL) restano 1h per sempre senza dati alt sub-orari.
|
||||
- **HONEST:** solo **DIP01** (BTC, mean-reversion) ha senso + dati. **TR01** (trend EMA20/100 su
|
||||
4h, basket alt) e **ROT02** (rotazione dual-momentum 1d, momentum 60g, universo alt) sono lente
|
||||
(orizzonte multi-giorno/mese) E multi-asset-su-alt → sub-orario **infattibile** (dati) e
|
||||
**insensato** (momentum a 60 giorni su barre da 5 min). Nessuno sweep.
|
||||
|
||||
## Flat-share (print stale O=H=L=C, = rischio fill) — sale al scendere del TF
|
||||
|
||||
| asset | 5m | 10m | 15m | 30m | 1h |
|
||||
|-------|----|-----|-----|-----|-----|
|
||||
| BTC | 10.0% | 4.8% | 3.5% | 1.5% | 0.9% |
|
||||
| ETH | **29.0%** | 17.3% | 16.4% | 9.0% | 6.7% |
|
||||
|
||||
ETH 5m al 29% è un allarme operativo serio. Nota: **30m ETH (9%) < 15m (16.4%)** → il 30m ha
|
||||
*meno* rischio stale-print del 15m già live.
|
||||
|
||||
## PAIRS ETH/BTC — il vero free-lunch
|
||||
|
||||
Config UNIVERSALE 1h (n=50, z_in=2.0, z_exit=0.75, max_bars=72), flat_skip live-realizable:
|
||||
|
||||
| tf | Sharpe FULL | OOS Sh | OOS Sh fee2x | CAGR | win% |
|
||||
|----|-------------|--------|--------------|------|------|
|
||||
| 5m | 9.54 | 17.19 | 11.98 | 2071% | 56.0 |
|
||||
| 10m | 9.26 | 16.54 | **13.03** | 1214% | 64.1 |
|
||||
| 15m (live) | 8.10 | 14.40 | 11.74 | 673% | 66.7 |
|
||||
| 30m | 6.20 | 11.17 | 9.59 | 312% | 71.7 |
|
||||
| 1h (live) | 3.74 | 7.11 | 6.19 | 119% | 72.4 |
|
||||
|
||||
(I CAGR a quattro cifre sono compounding leva su singolo sleeve, irrealistici — il portafoglio
|
||||
normalizza/cappa; il segnale robusto è lo **Sharpe** e il **gate PORT06**.)
|
||||
|
||||
- Sharpe **monotono** al scendere del TF, e **regge le fee 2x** (a differenza delle fade, dove
|
||||
MR02 muore a 5m). Pairs market-neutral: lo spread rientra più spesso ad alta frequenza, e
|
||||
ETH/BTC è la coppia più liquida.
|
||||
- Corr daily fra TF: 5m↔1h 0.28, 10m↔1h 0.32, 30m↔1h 0.51; 10m↔15m 0.67 → i TF veloci sono
|
||||
**fasi diverse dello stesso edge**, diversificanti, non duplicati.
|
||||
|
||||
**Gate PORT06 (add half-size al BLEND 1h+15m, OOS da 2024-10):**
|
||||
|
||||
| config | FULL Sh | FULL DD% | OOS Sh | OOS DD% | verdetto |
|
||||
|--------|---------|----------|--------|---------|----------|
|
||||
| ATTUALE (1h+15m) | 8.13 | 2.47 | 10.86 | 2.09 | — |
|
||||
| +30m | 8.24 | 2.28 | 10.87 | 1.97 | **MIGLIORA** (già `pairs30m_gate`, mai deployato) |
|
||||
| +10m | 8.44 | 2.28 | 11.04 | **1.92** | **MIGLIORA** (domina tutto) |
|
||||
| +5m | 8.52 | 2.30 | 11.00 | 1.95 | **MIGLIORA** (FULL Sh max) |
|
||||
|
||||
Tutte e tre dominano su FULL Sh, FULL DD, OOS Sh, OOS DD. **10m** è il candidato più pulito
|
||||
(miglior OOS DD, flat-share moderato 17%); **30m** è il più sicuro (flat-share 9% < 15m live).
|
||||
|
||||
## DIP01 (BTC) — più veloce, ma lo swap NON domina
|
||||
|
||||
Engine canonico (n=50, z_in=2.5, sl_atr=2.5, max_bars=24), parità 1h verificata:
|
||||
|
||||
| tf | OOS Sh BTC | OOS Sh fee2x BTC | corr↔1h | OOS Sh ETH |
|
||||
|----|------------|------------------|---------|------------|
|
||||
| 5m | 4.91 | 2.41 | 0.13 | 8.43 |
|
||||
| 10m | 3.47 | 1.99 | 0.17 | 6.51 |
|
||||
| 15m | 2.40 | 1.40 | 0.22 | 4.49 |
|
||||
| 30m | 1.34 | **0.77** | 0.41 | 3.54 |
|
||||
| 1h (live) | 1.69 | 1.36 | — | 2.68 |
|
||||
|
||||
Standalone Sharpe sale al scendere del TF e i TF veloci sono **fortemente diversificanti**
|
||||
(corr 0.13–0.22 con l'1h). MA: **BTC fee-fragile** (30m f2x 0.77), e il **gate-swap non domina**:
|
||||
|
||||
| config | FULL Sh | FULL DD% | OOS Sh | OOS DD% |
|
||||
|--------|---------|----------|--------|---------|
|
||||
| DIP01 1h (live) | 8.13 | 2.47 | 10.86 | 2.09 |
|
||||
| DIP01 30m | 8.16 | 2.27 | 10.78 | 2.03 |
|
||||
| DIP01 15m | 8.16 | 2.30 | 10.82 | 2.14 |
|
||||
| DIP01 10m | 8.31 | 2.49 | 10.85 | 2.15 |
|
||||
| DIP01 5m | 8.46 | 2.27 | 11.02 | 2.16 |
|
||||
|
||||
Tutti migliorano i FULL ma **alzano l'OOS DD** (e 30m abbassa l'OOS Sharpe) → nessuno domina
|
||||
sui 4 criteri. DIP01 5m dà il miglior OOS Sharpe (11.02) ma OOS DD 2.16 vs 2.09. La bassa corr
|
||||
suggerirebbe un **ADD** (DIP01 5m come secondo sleeve diversificante) più che uno swap, ma
|
||||
aumenta la concentrazione BTC-rev e non è il free-lunch netto che sono i pairs.
|
||||
|
||||
## Caveat (perché backtest ≠ via libera a scalare)
|
||||
|
||||
1. **Slippage su feed flat-alto** = il vero banco di prova, già flaggato per il 15m blend
|
||||
("il vero banco di prova è il ledger reale shadow"). A 5m/10m è peggio (ETH 5m 29% flat).
|
||||
Il backtest usa flat_skip (timing live-realizable) ma NON modella lo slippage attorno ai
|
||||
print stali. → gateare via shadow ledger PRIMA di sizing, specie il 5m.
|
||||
2. **OOS = un solo regime** (2024-10→, calmo). Lo Sharpe monotono-col-TF può essere in parte
|
||||
un artefatto di regime calmo (la MR veloce prospera nel range a bassa vol; lo sweep fade
|
||||
trovò "i tf veloci pagano nella volatilità, non nella calma"). I pairs sono market-neutral
|
||||
→ meno esposti dei fade ai crash direzionali, ma il caveat resta.
|
||||
|
||||
## Verdetto del backtest (gate full + OOS 2024→)
|
||||
|
||||
- **PAIRS ETH/BTC: il gate diceva SÌ.** Estendere il BLEND con TF più veloci migliorava PORT06
|
||||
su tutte le metriche (10m domina, 30m il più sicuro, 5m FULL Sh max), fee-2x robusto.
|
||||
- **DIP01: marginale.** Più veloce è diversificante ma lo swap non domina e BTC è fee-fragile.
|
||||
- **TR01/ROT02: NO.** Dati alt 1h-only + orizzonte lento → fuori scope per costruzione.
|
||||
|
||||
## Tentativo di deploy → due muri, NESSUN deploy (2026-06-14)
|
||||
|
||||
L'utente ha scelto di deployare un blend pairs ETH/BTC più veloce. Il wiring è stato fatto e
|
||||
validato (sleeve def, backtest face, worker replay == backtest esatto, regression-lock
|
||||
aggiornato) PRIMA di scoprire due blocchi che hanno ribaltato la decisione:
|
||||
|
||||
1. **MURO FEED (30m e 10m).** Il feed live **Cerbero v2 (`/mcp/tools/get_historical`) serve
|
||||
solo 5m/15m/1h** — il 30m e il 10m danno 400 in OGNI formato (30m/30/30min/1800), e
|
||||
l'endpoint legacy è 404 (rimosso). La voce `"30m"` in `runner._SUBHOURLY` era **speculativa,
|
||||
mai testata live**. → un blend 30m/10m NON è drop-in: richiede di derivarlo resamplando il
|
||||
feed 15m/5m nel runner (modifica al data-path live condiviso). **Lezione: il _SUBHOURLY del
|
||||
runner ≠ ciò che il feed serve davvero — smoke-testare il fetch prima di promettere un TF.**
|
||||
|
||||
2. **MURO REGIME (5m).** Il 5m è l'unico TF veloce nativo (drop-in), ma il gate full-history
|
||||
(Sharpe 9.54) è un **relitto dei regimi volatili vecchi**. Nel regime ATTUALE è il PEGGIORE
|
||||
(ETH/BTC pairs half-size, ret%/Sharpe/DD):
|
||||
|
||||
| tf | ultimi 30g | ultimi 90g | ultimi 180g |
|
||||
|----|-----------|-----------|------------|
|
||||
| 5m | −10.5% / −11.5 / 11.6% | −2.0% / −0.2 / 14.1% | +78% / 2.93 / **19.5%** |
|
||||
| 15m | −4.4% / −6.2 / 5.8% | −3.1% / −0.9 / 5.8% | +56% / 3.80 / 7.9% |
|
||||
| 1h | −1.0% / −1.1 / 3.0% | +3.0% / +1.3 / 3.0% | +25% / **3.95** / 3.0% |
|
||||
|
||||
Il 5m perde su ogni finestra recente e ha **DD 3-6× il 1h**; persino sui 180g il suo Sharpe
|
||||
(2.93) è SOTTO 15m/1h. Sommato al **flat-share ETH 5m 29%** (slippage reale, non modellato
|
||||
dal backtest) e al fatto che girerebbe **reale**, il guadagno modesto di backtest (FULL
|
||||
Sharpe +0.39) non vale il rischio. **5m: non conviene.**
|
||||
|
||||
**ESITO: nessun deploy. Config live invariata (19 sleeve, pairs 1h+15m).** I file tracciati
|
||||
ripristinati a HEAD; restano solo questo diario + `timing_sweep_pairs_honest.py` come record.
|
||||
|
||||
**Lezione di metodo:** il gate PORT06 full+OOS è necessario ma non sufficiente — va incrociato
|
||||
con (a) la fattibilità del FEED live e (b) il regime RECENTE. Un edge full-history può essere
|
||||
un relitto di volatilità passata; "più veloce = più Sharpe storico" si rovescia in "più veloce
|
||||
= più DD nel regime calmo attuale". Se in futuro si vorrà un blend più veloce: il **30m** resta
|
||||
il migliore on-paper (flat 9%), ma serve prima derivarlo dal 15m nel runner + ri-verificarlo
|
||||
nel regime del momento.
|
||||
@@ -1,85 +0,0 @@
|
||||
# 2026-06-15 — Gate del feed CONGELATO (freeze gate)
|
||||
|
||||
## Problema (da "stato ordini")
|
||||
|
||||
Audit degli ordini live: 5 sleeve in posizione reale, **4-5 contaminati dal feed ETH
|
||||
congelato**. `ETH-PERPETUAL` (inverse, il feed di DECISIONE del runner) è fermo a
|
||||
**1661.95 da 36h+** (100% barre flat, 57/57 nel windows 2g, **1 solo valore distinto**),
|
||||
mentre il book reale dove si ESEGUE (`ETH_USDC-PERPETUAL`, lineare) si muove ~1717-1722.
|
||||
|
||||
Effetto misurato sui soldi reali (log container):
|
||||
- **SH01_ETH** ha aperto short a sim 1661.95 / real 1717.10 (slippage 332 bps), chiuso a
|
||||
time_limit con `sim_exit 1661.95` ma `real_fill 1719.21` → **−2.83 USD reali vs −0.09 sim**
|
||||
→ e ha **riaperto subito** lo stesso short sulla trappola.
|
||||
- I 4 pairs con gamba ETH (ETH/BTC 1h+15m, ETH/SOL, LTC/ETH, ADA/ETH) sono entrati con
|
||||
z-score **estremi** (−3.10, −2.96, +5.58, −2.56): artefatto MECCANICO del log-ratio con
|
||||
ETH pinnato a 1661.95 mentre gli alt si muovono → falsa divergenza → carico di spread long-ETH.
|
||||
|
||||
È un GUASTO testnet, non di strategia: in mainnet l'arbitraggio tiene inverse ≈ lineare ≈ realtà.
|
||||
|
||||
## Decisione utente
|
||||
|
||||
> "congela gli sleeve ETH-leg finché il feed non si sblocca"
|
||||
|
||||
## Soluzione: gate del feed congelato nel runner (auto-guarente)
|
||||
|
||||
`src/portfolio/runner.py`: quando il feed di decisione 1h di un asset è **congelato**, gli
|
||||
sleeve CONCENTRATI (single/ml/pairs) che ne dipendono **saltano il tick** (entry E exit)
|
||||
finché il feed non si sblocca. Come un outage (i worker non valutano gli exit, protezione =
|
||||
disaster-SL on-book). Si rilascia DA SOLO alla prima barra completa non-flat.
|
||||
|
||||
### Distinguere il GUASTO dall'ILLIQUIDITÀ (il punto critico)
|
||||
|
||||
Un detector flat-bar ingenuo sarebbe SBAGLIATO: sul feed reale (2026-06-15) gli alt sono
|
||||
flat ma VIVI. Firma misurata (run finale di close invariate / valori distinti in 48h):
|
||||
|
||||
| Asset | run | distinti/48h | natura |
|
||||
|-------|-----|--------------|--------|
|
||||
| ETH | 64 | **1** | MORTO (guasto) |
|
||||
| BNB | 64 | 2 | MORTO (testnet, solo paper) |
|
||||
| DOGE | 42 | 4 | MORTO (testnet, solo paper) |
|
||||
| XRP | 12 | 3 | illiquido |
|
||||
| ADA | 11 | 5 | illiquido ma VIVO |
|
||||
| LTC | 10 | 5 | illiquido ma VIVO |
|
||||
| SOL | 1 | 31 | VIVO |
|
||||
|
||||
→ il detector conta la **run di close INVARIATE** (prezzo che non cambia MAI), non le barre
|
||||
flat. Soglia **24** (`feed_freeze_gate_bars`, configurabile, 0=off): un giorno intero di
|
||||
prezzo immobile separa nettamente le due popolazioni. ETH/BNB/DOGE (run 40-64) gateati,
|
||||
ADA/LTC/XRP/SOL (run ≤12) no. **PR_BTCLTC resta attivo** (BTC vivo + LTC solo illiquido NON
|
||||
deve sospendere il pair: si perderebbero segnali reali sulla gamba BTC).
|
||||
|
||||
### NON è l'entry-guard post-flat (BOCCIATA)
|
||||
|
||||
Si gatea **DURANTE** il freeze (ultima barra completa ferma). La barra di RIPRESA è non-flat
|
||||
→ la run si azzera → il tick riprende SU di essa. NON si salta la candela-gap di ripresa
|
||||
(quella è l'overshoot che la fade fada con profitto — l'entry-guard post-flat è bocciata,
|
||||
CLAUDE.md / 2026-06-05). Rilascio solo su barra **completata** non-flat (la forming non basta,
|
||||
coerente con EXIT-16).
|
||||
|
||||
### Scope
|
||||
|
||||
Solo sleeve `single`/`ml`/`pairs`. I multi-asset (basket/rotation/tsmom/xsec, tutti PAPER)
|
||||
NON sono gateati: diversificati su 8 asset, un feed fermo non li compromette (e ROT02 ha ETH
|
||||
nell'universo ma resta attivo). Osservabilità: log `FEED_FROZEN_GATE` + alert Telegram
|
||||
GATED/RIPRESO, dedup per episodio.
|
||||
|
||||
## Esito (smoke feed reale, soglia 24)
|
||||
|
||||
- CONGELATI: ETH, BNB, DOGE.
|
||||
- **GATEATI: le 9 gambe ETH esatte** — MR01/MR02/MR07_ETH, SH_ETH, PR_ETHBTC, PR_ETHBTC_15M,
|
||||
PR_LTCETH, PR_ADAETH, PR_ETHSOL. BTC-only, PR_BTCLTC e i multi-asset restano attivi.
|
||||
|
||||
Le 5 posizioni ETH già aperte NON vengono flattate (freeze = pausa, non liquidazione): un
|
||||
close forzato passerebbe per lo stesso feed congelato (= il close −2.83 di SH01). Restano
|
||||
gestite alla ripresa del feed; protezione di coda = disaster-SL on-book a −30%.
|
||||
|
||||
Test: `tests/portfolio/test_freeze_gate.py` (detector guasto-vs-illiquido, rilascio su barra
|
||||
completata, scope sui veri sleeve PORT06). Suite portfolio: 140/140 verdi.
|
||||
|
||||
## Lezione
|
||||
|
||||
Tre livelli di osservabilità del feed ora distinti: STALE_FEED (≥2 barre flat, alert umano),
|
||||
FEED_BOOK_GAP (feed≠book d'esecuzione, alert), **FEED_FROZEN_GATE (≥24 barre invariate, AGISCE)**.
|
||||
La firma che separa guasto da illiquidità è la **run di prezzo invariato**, non la barra flat:
|
||||
gli alt illiquidi stampano barre flat ma il prezzo si muove ogni ~10 barre.
|
||||
@@ -1,66 +0,0 @@
|
||||
# 2026-06-16 — Guard TP-invertito (churn MR02_BTC 15m)
|
||||
|
||||
## Sintomo
|
||||
Burst di **8 trade in 15 minuti** su `MR02_donchian_fade__BTC__15m` (09:00–09:15 UTC),
|
||||
tutti `long`, tutti chiusi `take_profit` a `bars_held=0-1` **in perdita**, accuracy
|
||||
crollata 60%→27%. TP **fisso** a 66189.25, **sotto** ogni entry (66700–66834):
|
||||
|
||||
```
|
||||
09:00 OPEN long 66780.5 tp=66189.25 sl=64218.21 ← tp E sl ENTRAMBI sotto l'entry
|
||||
09:02 CLOSE take_profit exit=66189.25 held=0 sim=-2.63 real=-0.12
|
||||
... ×8 ... +7× REAL_TP_FAIL: invalid_reduce_only_order
|
||||
```
|
||||
|
||||
I trade MR02 sani prima del cluster hanno il TP dal lato giusto (long → tp>entry:
|
||||
65033>63414, 64148>63775, 66079>65717). Il cluster delle 09:00 è l'unico **invertito**.
|
||||
|
||||
## Causa radice — segnale da wick transitorio (NON feed congelato, NON spike d'ingresso)
|
||||
BTC alle 09:00 era **davvero** ~66780 (MR01 short@66919, MR07 short@66780.5 nello stesso
|
||||
istante, slippage reale 0.7–2.5 bps → feed sano). Il difetto è a monte:
|
||||
|
||||
1. Una barra con **wick verso il basso** (~64218 = il livello SL) fa scattare il donchian
|
||||
"rottura canale basso" → segnale **LONG**, con `tp`=centro canale (66189) e `sl`=64218
|
||||
calcolati **dal contesto wickato**.
|
||||
2. Il wick rientra; il worker entra `long` al prezzo **recuperato** 66780 — cioè **sopra
|
||||
il proprio TP=66189**.
|
||||
3. L'exit intrabar (`bar_high >= tp`) è banalmente vera all'istante → chiude "take_profit"
|
||||
a 66189 = **perdita garantita a held=0**. Si ripete 8× perché il livello donchian
|
||||
wickato resta nel lookback.
|
||||
|
||||
Differenza chiave da TP_PHANTOM: lì il wick è sull'**exit** (tocco fantasma del TP);
|
||||
qui il wick produce un **tp dal lato sbagliato dell'entry** → la posizione non doveva
|
||||
proprio aprirsi.
|
||||
|
||||
## Perché i guard esistenti non l'hanno preso
|
||||
- **TP_PHANTOM** richiede un limit reduce-only resting come oracolo. Qui il limit è
|
||||
**respinto** (`invalid_reduce_only_order`: una sell reduce-only a 66189 sotto il mercato
|
||||
è invalida) → niente `real_tp_order_id` → fail-open → l'exit passa. E il prezzo corrente
|
||||
(66780) ha **realmente** superato il livello → non è un tocco fantasma.
|
||||
- **Freeze-gate (v1.1.32)**: BTC non è congelato (prezzi che si muovono) → non scatta.
|
||||
|
||||
## Danno reale: contenuto (il real-truth ledger ha funzionato)
|
||||
- Σ **reale** del cluster ≈ **−€2.29** (solo slippage+fee: il fill reale è al prezzo vero
|
||||
~66700-66730, non al TP fantasma).
|
||||
- Σ **sim** sarebbe stato ≈ **−€17.9** → il real-truth ledger ha evitato che ~**€15.6** di
|
||||
perdita fantasma colpisse l'equity.
|
||||
- Costi collaterali: 8 round-trip di fee, 7 TP reduce-only respinti, 8 disaster-SL da
|
||||
piazzare/cancellare, sim accuracy/report inquinati.
|
||||
- Auto-esaurito alle 09:15 (sleeve poi flat).
|
||||
|
||||
## Fix — guard "TP invertito" (v1.1.33, zero parametri)
|
||||
`StrategyWorker._open_position`: **prima** di aprire, se il TP è già sfondato all'ingresso
|
||||
(`long & tp<=entry` oppure `short & tp>=entry`) il segnale è malformato (artefatto wick)
|
||||
→ **NON si apre** (niente ordine reale, niente disaster-SL). Verità d'esecuzione, non un
|
||||
filtro di strategia (stessa filosofia di TP_PHANTOM). Log `INVERTED_TP_SKIP` (dedup
|
||||
per-barra) + alert Telegram una-tantum per processo. Agisce **solo sul path live**: il
|
||||
backtest canonico entra al close del bar del segnale (entry == base di tp/sl → mai
|
||||
invertito) e resta non filtrato → il live farà meglio del backtest, come loss-guard /
|
||||
trend / TP_PHANTOM.
|
||||
|
||||
Test: `tests/portfolio/test_inverted_tp.py` (long/short invertiti skippati, controlli
|
||||
positivi long/short validi aprono, no-tp apre, dedup per-barra). Suite portfolio 146/146.
|
||||
|
||||
## Lezione
|
||||
Cerotto testnet (il feed wicka): il fix vero è **mainnet**, dove l'arbitraggio elimina i
|
||||
wick-print. Ma il guard è corretto in assoluto — un segnale con TP dal lato sbagliato
|
||||
dell'entry non va mai eseguito, su qualsiasi venue.
|
||||
@@ -1,57 +0,0 @@
|
||||
# 2026-06-16 — Fase 0 smoke mainnet VERDE (ETH→USDC, limit non market)
|
||||
|
||||
## Contesto
|
||||
Il conto Deribit mainnet, fino al 2026-06-14 **vuoto** (€0, unico blocco al micro-test), ha
|
||||
ricevuto un deposito iniziale di **~$50**: 25.00 USDC + 0.013878 ETH. Occasione per eseguire la
|
||||
**Fase 0** del piano (`docs/specs/mainnet-microtest-plan.md`): validare la catena d'esecuzione su
|
||||
soldi VERI con rischio ~0, abbinandola a un'operazione utile — **consolidare l'ETH stranded in
|
||||
margine USDC**.
|
||||
|
||||
Perché consolidare: noi eseguiamo sui perp **lineari USDC** (`*_USDC-PERPETUAL`), marginati in
|
||||
**USDC**. I 0.0138 ETH stavano nel wallet ETH (collateral dell'inverse, che NON usiamo per la
|
||||
matematica lineare del backtest) → margine effettivo solo i $25 USDC. Convertendo, l'intero ~$50
|
||||
diventa USDC utilizzabile.
|
||||
|
||||
## Ordine (LIMIT, non market — istruzione utente)
|
||||
Check capability read-only prima: spot `ETH_USDC` esiste (bid 1780.3/ask 1780.9, `testnet:false`,
|
||||
price tick 0.1). Il listing strumenti NON espone lo spot (kind=spot vuoto, endpoint v1 404) ma il
|
||||
ticker basta. `place_order` supporta `order_type="limit"` + `price`.
|
||||
|
||||
- **LIMIT SELL `ETH_USDC` 0.0138 ETH @ floor 1776.3** (~0.1% sotto il bid) — *marketable limit con
|
||||
cap di slippage*: crossa e filla al bid corrente, ma con un floor sotto cui NON può fillare.
|
||||
Soddisfa "non a market" (prezzo protetto, niente slippage incontrollato) garantendo il fill.
|
||||
- Step 0.0001 ok al primo colpo (niente fallback 0.013); fallback previsti 0.013/0.012.
|
||||
|
||||
### Esito
|
||||
```
|
||||
order_state = filled filled_amount = 0.0138
|
||||
average_price = 1778.1 (= bid al momento dell'invio; il bid era sceso 1780.3->1778.1 tra
|
||||
quote e invio, ma > floor 1776.3 -> zero slippage negativo)
|
||||
fee = 0.0 (maker, costo nullo)
|
||||
order_id = ETH_USDC-8488088107
|
||||
```
|
||||
Riconciliazione conto (before→after):
|
||||
| Wallet | Prima | Dopo |
|
||||
|---|---|---|
|
||||
| USDC | 25.00 | **49.538** (+24.538) |
|
||||
| ETH | 0.013878 | 0.000078 (dust ~$0.14, sotto il min → non convertibile) |
|
||||
| BTC | 0 | 0 |
|
||||
| posizioni / ordini resting | — | nessuna / nessuno |
|
||||
|
||||
## Cosa è dimostrato
|
||||
Catena end-to-end su **mainnet** (`testnet:false`), a costo ~0: routing live + auth + `place_order`
|
||||
limit + fill + verifica via `get_trade_history` + riconciliazione `get_account_summary`. La
|
||||
meccanica d'esecuzione reale FUNZIONA su soldi veri. **Fase 0 ✅.**
|
||||
|
||||
## Limite residuo (resta il blocco vero)
|
||||
~$49.54 USDC è **sotto il minimo €500** del piano: a questo margine il rumore di arrotondamento
|
||||
BTC (step lineare ~$6.6) soffoca il segnale → NON si può ancora testare l'**edge**. Per la **Fase 1**
|
||||
(fade-only, €1000, 2-4 settimane, verdetto ledger-vs-backtest) serve un **top-up a ~€500-1000 USDC**.
|
||||
Stato piano aggiornato: token+smoke ✅, funding 🟡 parziale, Fase 1 in attesa di capitale.
|
||||
|
||||
## Note operative
|
||||
- Operazione MANUALE one-off (non il runner): `.env.mainnet` sourcato a mano, client puntato a
|
||||
mainnet solo per questa sessione. Il runner di produzione resta su **testnet** (`.env` condiviso
|
||||
invariato) → nessun rischio di flip accidentale.
|
||||
- La marketable-limit con floor è il pattern giusto per conversioni one-shot a prezzo controllato
|
||||
(vs il TP resting/limit-al-livello degli sleeve): fill immediato + cap di slippage, fee maker.
|
||||
@@ -1,265 +0,0 @@
|
||||
# 2026-06-18 — Price Ladder (griglia) vs gate PORT06
|
||||
|
||||
**Branch:** `price_ladder_research` · **Harness:** `scripts/analysis/ladder_search.py`
|
||||
(engine `grid_mtm`: mark-to-market onesto, SL gap-aware, flat-skip, fee 0.10% RT taker).
|
||||
**Baseline PORT06:** FULL Sharpe 8.13 / DD 2.47% — OOS Sharpe 10.86 / DD 2.09%.
|
||||
**Metodo:** caccia multi-agente su asset × TF (15m/30m/1h) × regime-gate (none / range
|
||||
trend_max 1.5/2.0/2.5), poi `verify` avversariale sui finalisti (plateau, fee 2x, corr,
|
||||
FULL DD di portafoglio). **Goal di progetto:** trovare un Price Ladder che *diversifichi*
|
||||
(PASSI il gate) senza accendere la coda di trend.
|
||||
|
||||
---
|
||||
|
||||
## 1. Cosa era già noto
|
||||
|
||||
Il gioco-griglia precedente aveva trovato una **griglia ETH fortissima standalone**
|
||||
(Sharpe ~5.61) ma **BOCCIATA al gate PORT06**: corr ~0.40 con le fade ETH già deployate
|
||||
→ **ridondante**, non un diversificatore. La lezione: lo standalone Sharpe non basta, conta
|
||||
quanto il ladder *aggiunge ortogonalmente* al portafoglio. Questa ricerca cerca proprio un
|
||||
ladder che PASSI il gate = che abbia corr bassa con gli sleeve esistenti.
|
||||
|
||||
---
|
||||
|
||||
## 2. Risultato NUOVO — i ladder PASSANO il gate
|
||||
|
||||
Sì. Su **tutti gli asset liquidi** (BTC e ETH) e su quasi tutte le combinazioni TF×regime,
|
||||
i ladder migliorano l'OOS Sharpe di portafoglio (10.86 → ~11.0–11.35) **con corr bassa**:
|
||||
|
||||
- **BTC** (15m/30m/1h, range o none): corr **0.15–0.27**, molto più ortogonale della
|
||||
griglia ETH bocciata (0.40). OOS di portafoglio 11.1–11.35 (il guadagno OOS più grosso).
|
||||
- **ETH** (15m/30m/1h): corr **0.21–0.57** (15m la peggiore, fino a 0.57; a 1h scende a
|
||||
0.22–0.39). OOS di portafoglio ~10.9–11.1.
|
||||
- **SOL/LTC**: SOL passa solo 2 celle, half-only, edge standalone quasi nullo
|
||||
(full_sh ~0.2); **LTC è negativo ovunque** (full_sh −0.4…−0.8, bocciato) → solo BTC/ETH
|
||||
liquidi danno un ladder vivo, come atteso.
|
||||
|
||||
Il gate **misura corr + OOS**, e su questi due assi i ladder BTC vincono nettamente.
|
||||
|
||||
### Migliori candidati (dai `verify` avversariali)
|
||||
|
||||
| Asset/TF/regime/struttura | OOS base→new | FULL DD standalone | FULL DD portafoglio (full / half) | corr | fee2x OOS | robust? |
|
||||
|---|---|---|---|---|---|---|
|
||||
| **ETH 1h range2 rd0.16 ru0.04 L4** | 10.86→**11.00** | 11.79% | **2.70** / 2.52 | 0.305 | 4.89 | ✅ sì |
|
||||
| **ETH 1h range2 rd0.16 ru0.06 L6** | 10.86→11.01 | 12.09% | 2.74 / 2.54 | 0.328 (al filo) | 5.05 | ✅ sì |
|
||||
| **ETH 1h range2 rd0.16 ru0.06 L4** | 10.86→10.98 | 12.64% | **2.68** / 2.51 | 0.249 | 4.44 | ✅ sì |
|
||||
| **ETH 30m range2 rd0.16 ru0.04 L3** | 10.86→10.93 | 12.56% | **2.48** / 2.41 | 0.223 | 4.21 | ✅ sì |
|
||||
| **ETH 1h none rd0.20 ru0.06 L6** | 10.86→11.03 | 17.89% | 2.59 / 2.46 | 0.271 | 5.43 | ✅ sì |
|
||||
| **ETH 30m none rd0.16 ru0.06 L4** | 10.86→10.92 | 18.68% | **2.37** / 2.35 | 0.319 | 5.42 | ✅ sì |
|
||||
| **ETH 1h none rd0.16 ru0.06 L4** | 10.86→10.96 | 23.13% | **2.40** / 2.37 | 0.224 | 4.59 | ✅ sì |
|
||||
| **BTC 1h none rd0.08 ru0.06 L3** | 10.86→**11.34** | **53.69%** | 3.11 / **2.48** | 0.216 | 5.78 | ⚠ half-only |
|
||||
| **BTC 30m range2.5 rd0.08 ru0.06 L3** | 10.86→11.22 | 55.33% | 3.27 / **2.50** | 0.265 | 5.19 | ⚠ half-only |
|
||||
| **BTC 30m none rd0.08 ru0.06 L3** | 10.86→11.32 | 55.33% | 3.27 / **2.44** | 0.220 | 5.37 | ⚠ half-only (tail) |
|
||||
| **BTC 1h range1.5 rd0.20 ru0.06 L6** | 10.86→11.13 | 54.43% | 3.19 / **2.33** | **0.161** | 5.46 | ⚠ half-only (tail) |
|
||||
|
||||
`rd` = spacing down, `ru` = spacing up, `L` = livelli. Tutti i finalisti hanno plateau
|
||||
robusto (4–7 vicini di struttura restano PROMOSSO) e fee2x ~= OOS standalone.
|
||||
|
||||
---
|
||||
|
||||
## 3. IL NODO — la FULL DD (che il gate IGNORA)
|
||||
|
||||
**Il gate verdict NON guarda la FULL DD.** Misura solo corr + OOS Sharpe/DD. Una griglia
|
||||
long-only ha una coda di trend 2021/22 (viene comprata fino in fondo mentre il prezzo crolla
|
||||
in un trend persistente) → la **FULL DD standalone** è il vero rischio nascosto. Il filtro
|
||||
onesto è la **FULL DD di PORTAFOGLIO** (`full_full_dd` / `half_full_dd`), con soglia di
|
||||
tail-risk **~+0.8pp sopra il baseline 2.47%** (cioè restare sotto ~3.3%).
|
||||
|
||||
Due famiglie nette emergono:
|
||||
|
||||
- **BTC** — FULL DD standalone **~54–67%** (la coda long-only è devastante, come temuto).
|
||||
Il regime-gate range *taglia gli ingressi nei trend* ma **non immunizza** dalle posizioni
|
||||
già aperte → a FULL size la FULL DD di portafoglio sale a **3.1–6.6%** (+0.6/+4.0pp,
|
||||
**oltre la soglia tail** in quasi tutte le celle). **A HALF size invece rientra a 2.33–2.54%**
|
||||
(~baseline) preservando l'OOS ~11.0–11.3. → **BTC deployabile SOLO a half-size**, e il
|
||||
guadagno OOS più grosso (11.3+) viene proprio da queste celle a coda alta.
|
||||
|
||||
- **ETH** — FULL DD standalone **molto più bassa** del previsto: **12–33%** (1h range scende
|
||||
a **~12%**), NON il ~60% temuto. Lo SL-buffer + flat-skip + il regime-gate range tengono la
|
||||
griglia fuori dai trend estesi. Conseguenza: la FULL DD di portafoglio resta **2.37–2.74%**
|
||||
(+0.0/+0.27pp, **sotto soglia anche a FULL size**) — in diversi casi *scende* sotto il
|
||||
baseline (es. ETH 30m none L4 → 2.37%). → **ETH è la famiglia tail-safe.** Il prezzo è una
|
||||
corr più alta (0.22–0.33 sui finalisti 1h/30m, fino a 0.57 sul 15m da scartare).
|
||||
|
||||
**Lettura chiave:** il regime-gate *abbassa* la FULL DD ma su BTC **non a sufficienza** a
|
||||
full size (la coda 54% è troppo grande); è l'**half-size** a fare il lavoro. Su ETH la coda
|
||||
è già piccola e il portafoglio l'assorbe. Quindi il discriminante reale è **asset (ETH vs
|
||||
BTC) + size**, non solo il regime-gate.
|
||||
|
||||
---
|
||||
|
||||
## 4. Vantaggio Deribit — fill MAKER
|
||||
|
||||
Un Price Ladder è una griglia di **ordini LIMIT ai livelli** → su Deribit i fill sono
|
||||
**MAKER (~0% fee)**, non taker. L'harness assume **0.10% RT taker** ovunque → è
|
||||
**CONSERVATIVA**: la stessa griglia live pagherebbe meno fee e potrebbe rendere PIÙ del
|
||||
backtest. Lo confermano i `verify`: il **fee2x** (raddoppio fee) lascia l'OOS Sharpe quasi
|
||||
intatto (~98% trattenuto su quasi tutti i finalisti) → nessun fee-cliff, e con i fill maker
|
||||
reali c'è upside, non downside, sul lato costi. (Il rischio resta la coda di trend e lo
|
||||
slippage/fill in esecuzione reale, non le fee.)
|
||||
|
||||
---
|
||||
|
||||
## 5. Verdetto operativo
|
||||
|
||||
**C'è un Price Ladder deployabile.** Il candidato più pulito su tutti gli assi
|
||||
(PROMOSSO + FULL DD di portafoglio controllata a full size + plateau robusto + corr genuina):
|
||||
|
||||
> **ETH 1h, regime=range trend_max 2.0, rd=0.16 / ru=0.04 / 4 livelli, sl_buf 0.12 / tp_buf 0.05, max_bars 720.**
|
||||
> OOS 10.86→11.00, FULL DD portafoglio **2.70% a full / 2.52% a half** (standalone 11.79%),
|
||||
> corr 0.305, fee2x OOS 4.89, plateau 4 vicini PROMOSSO. **Deploy raccomandato a HALF size**
|
||||
> (FULL DD +0.05pp, marginale; il caveat slippage live giustifica la prudenza).
|
||||
|
||||
**Alternative ETH equivalenti** (stessa banda di sicurezza, scegliere per corr/coda):
|
||||
`ETH 1h range2 rd0.16 ru0.06 L4` (corr 0.249, la più bassa) e `ETH 30m range2 rd0.16 ru0.04 L3`
|
||||
(FULL DD portafoglio 2.48, ~baseline). Tutte ETH 1h/30m **range-gated rd≥0.16** → NON scendere
|
||||
sotto rd 0.16 (rd 0.12 fa risalire la corr verso 0.38 = ricomincia a somigliare alle fade ETH;
|
||||
il 15m ha corr 0.43–0.57 = troppo ridondante, scartare).
|
||||
|
||||
**I BTC NON a full size.** Danno il guadagno OOS più grande (fino a 11.34) e la corr più bassa
|
||||
(0.16–0.22 = la diversificazione migliore), MA la FULL DD standalone ~54% li rende
|
||||
**tail-risky a full size** (FULL DD portafoglio 3.1–6.6%, oltre soglia). **Deployabili SOLO a
|
||||
half-size** (FULL DD portafoglio 2.33–2.50), dove restano un diversificatore eccellente. Il
|
||||
migliore BTC half-size è `BTC 1h range1.5 rd0.20 ru0.06 L6` (corr **0.161**, FULL DD portafoglio
|
||||
half **2.33**).
|
||||
|
||||
**BLOCCO prima di qualsiasi deploy:** il gate PORT06 (corr + OOS) è **necessario ma non
|
||||
sufficiente** — non controlla la FULL DD, e l'OOS held-out è un **regime calmo** (2024–25). La
|
||||
coda di trend 2021/22 è reale e standalone è enorme su BTC. **Nessun deploy senza un gate
|
||||
stressato sul 2022** (verificare la FULL DD di portafoglio attraverso il trend duro, non solo
|
||||
l'OOS calmo) e una conferma su **ledger reale shadow** per slippage/fill maker. Il verdetto del
|
||||
gate va sempre incrociato con la FULL DD di portafoglio (filtro vero) + fattibilità feed live +
|
||||
regime recente — la stessa lezione del timing-sweep pairs/honest (2026-06-14).
|
||||
|
||||
**Sintesi:** ETH 1h/30m range-gated rd≥0.16 a half-size è il **deploy-candidate sano e
|
||||
tail-safe**; BTC è il diversificatore migliore ma **solo a half-size** per la coda di trend.
|
||||
Prossimo passo obbligatorio: stress-test 2022 + shadow ledger reale (i fill maker possono solo
|
||||
migliorare il risultato sul lato fee).
|
||||
|
||||
---
|
||||
|
||||
## 6. ⚠️ RETTIFICA CRITICA — il verdetto §5 è ROVESCIATO (critico + verifica dati)
|
||||
|
||||
Il critico di completezza + una verifica diretta dei dati **ribaltano la raccomandazione di
|
||||
deploy della §5**. Messo a verbale: la §5 è SUPERATA da quanto segue.
|
||||
|
||||
**(1) I risultati BTC poggiano su DATI CORROTTI (spike-print), verificato.** La "coda di trend
|
||||
BTC ~54%" su cui ruota la §3 NON è un crollo di mercato: è **feed sporco**. Misurato su `btc_1h`:
|
||||
**37 barre con range intrabar >20%**, concentrate a **feb-2024** (es. 2024-02-13: low=38.580 con
|
||||
close~49.968 = wick fasullo −23% che rimbalza nella stessa barra), con min 22.706 / max 104.688 in
|
||||
un trimestre dove BTC stava ~47–57k. È lo **stesso spike-print testnet documentato ovunque in
|
||||
CLAUDE.md** (TP_PHANTOM / feed congelato). L'engine SL-gap-aware filla su questi wick fantasma e la
|
||||
griglia "compra" i dip fasulli → la coda BTC ~54% e parte dell'edge OOS sono **artefatto, non
|
||||
mercato**. Conseguenza: i candidati BTC NON sono affidabili, e lo "stress 2022" proposto NON
|
||||
toccherebbe la coda vera (che è a feb-2024, da dati sporchi). Serve `close_only` + pulizia feed.
|
||||
|
||||
**(2) Il guadagno OOS è RUMORE al peso deployabile.** +0.14 OOS Sharpe su base 10.86, con il ladder
|
||||
che pesa **~5.3% full / ~2.7% half** in un portafoglio già a Sharpe ~11, su **592 giorni di un
|
||||
solo regime calmo** (2024-10→2026-05, niente 2022). Nessun test di significatività
|
||||
(block-bootstrap). A half-size il contributo è quasi inerte (a volte l'OOS DD *migliora*): è dentro
|
||||
l'errore di campionamento, non un edge dimostrato.
|
||||
|
||||
**(3) La diversificazione ETH è più sottile di quanto venduto.** Il finalista ETH "raccomandato" è
|
||||
**corr 0.305** (non 0.15–0.20: quella è BTC half-only non deployabile), già vicino allo **0.40 che
|
||||
fece bocciare la griglia ETH originale**. Peggio: il `regime_mask` usa **lo stesso filtro
|
||||
trend-distance** (|close−EMA200|/ATR) delle fade ETH già live → la "diversificazione" è in parte
|
||||
illusoria (gate e sleeve condividono il filtro). La corr misurata è **daily in regime calmo**, NON
|
||||
co-tail: una griglia long-only e una fade reversion possono co-crollare in un trend (entrambe
|
||||
"comprano il calo") — la metrica che conterebbe (co-movimento nella coda) non è calcolata.
|
||||
|
||||
**(4) La FULL DD standalone è mascherata dal compounding.** Il finalista ETH compone a **~31x
|
||||
(+3.1M%) in 5.4 anni**: una "FULL DD 11.79%" accanto a un ritorno di milioni-% è artefatto di
|
||||
notional reinvestito, e il daily-resample **nasconde l'inventory-risk intrabar** che il docstring
|
||||
di `grid_game_gate.py` (righe 5–7) avverte esplicitamente di non vedere.
|
||||
|
||||
**(5) Stress disponibile NON usato.** `ladder_search`/`grid_mtm` hanno `close_only=True` (filla solo
|
||||
sul close, neutralizza gli spike-print): NON è stato girato sui finalisti — proprio il test che
|
||||
smonterebbe la coda BTC fasulla.
|
||||
|
||||
### Verdetto rettificato
|
||||
|
||||
**NON c'è un Price Ladder deployabile dimostrato.** La ricerca ha prodotto (a) una **harness onesta
|
||||
e validata** (`ladder_search.py` + regime-gate, riproduce esatto il gate noto), (b) un **risultato
|
||||
negativo/guardingo** robusto: ogni candidato o è ridondante (ETH, corr→0.40), o poggia su dati
|
||||
sporchi (BTC spike-print), o è rumore al peso deployabile. **Il multi-agente + critico ha evitato
|
||||
un deploy ingiustificato** — esattamente la lezione anti-squeeze del progetto.
|
||||
|
||||
**Prima di riconsiderare QUALSIASI ladder servono, in ordine:** (1) **pulire il feed BTC** dagli
|
||||
spike-print + girare `close_only` sui finalisti; (2) **test di significatività** del delta OOS
|
||||
(block-bootstrap) al peso reale; (3) **co-tail / corr nei crash** (2022), non corr daily calma;
|
||||
(4) isolare e spiegare l'**evento feb-2024**. Config live **invariata**.
|
||||
|
||||
---
|
||||
|
||||
## 7. RE-GATE su DATI PULITI (post clean_feed.py) — quadro onesto finale
|
||||
|
||||
Dopo `clean_feed.py` (254 spike-print riparati con Binance) ho ri-gateato i top candidati con
|
||||
le verifiche che il critico chiedeva (`ladder_regate_clean.py`): gate PORT06 + stress
|
||||
`close_only` + **DD per anno** sulla storia completa.
|
||||
|
||||
| Candidato | DD (gate, 2021+) | OOS Sh | corr | fee2x | close_only OOS | gate½ | **DD 2018 (tail vero)** |
|
||||
|---|---:|---:|---:|---:|---:|---|---:|
|
||||
| ETH 1h rd0.16 ru0.04 L4 range2 | 12.4% | 4.70 | 0.29 | 4.62 | 0.24 | PROMOSSO | −52.4% |
|
||||
| ETH 1h rd0.16 ru0.06 L4 range2 | 12.6% | 4.25 | 0.23 | 4.17 | 0.20 | PROMOSSO | −49.9% |
|
||||
| BTC 1h rd0.08 ru0.06 L3 none | 10.8% | 5.90 | 0.24 | 5.78 | 0.60 | PROMOSSO | −50.3% |
|
||||
| **BTC 1h rd0.20 ru0.06 L6 range1.5** | 14.8% | 5.58 | 0.23 | 5.46 | 0.89 | PROMOSSO | **−27.7%** |
|
||||
| BTC 30m rd0.08 ru0.06 L3 none | 14.8% | 5.47 | 0.25 | 5.37 | 1.07 | PROMOSSO | −36.6% |
|
||||
|
||||
**Cosa cambia coi dati puliti:**
|
||||
1. ✅ **L'obiezione "coda artefatto" CADE.** Il 54% del BTC era spike-print 2024: ora la DD del
|
||||
gate (2021+) è **~11-15%** e tutti i candidati restano PROMOSSO a half-size, corr 0.22-0.29,
|
||||
reggono fee2x. Sono candidati *veri*, non artefatti.
|
||||
2. 🔴 **Emerge il tail VERO: il 2018** (−44/−52% standalone), che **il gate NON VEDE** perché
|
||||
l'IDX del progetto parte dal 2021-01-01. Una griglia long-only sarebbe stata sventrata nel
|
||||
bear 2018 (BTC −84% sull'anno). È il nuovo rischio portante — e una **lacuna metodologica
|
||||
generale**: tutte le metriche "FULL" del progetto escludono il 2018. Mitigante reale: il
|
||||
**regime-gate stretto** (BTC rd0.20 L6 **range1.5**) dimezza il tail 2018 a **−27.7%** (vs
|
||||
−50% senza gate) → il gate-di-regime fa il suo lavoro contro i bear sostenuti.
|
||||
3. 🟡 **L'edge dipende dai fill INTRABAR.** `close_only` (fill solo sul close) fa crollare l'OOS
|
||||
(4.7→0.24 ETH, 5.9→0.6 BTC). Per ordini LIMIT i fill intrabar sono legittimi (close_only è
|
||||
troppo severo come stress), ma il gap segnala forte **sensibilità all'ipotesi di fill** →
|
||||
il ledger shadow reale è indispensabile prima di fidarsi.
|
||||
4. 🟡 Restano: corr 0.22-0.29 (moderata), guadagno OOS ai limiti del rumore al peso deployabile
|
||||
(~2.7% half), OOS singolo regime calmo.
|
||||
|
||||
**Verdetto finale (clean data):** la pulizia ha rimosso l'obiezione FALSA (coda artefatto) e
|
||||
promosso i candidati a *genuini*, ma ha anche scoperto il tail REALE (2018, gate-cieco) e
|
||||
confermato due cautele (fill intrabar, OOS rumoroso). **Il candidato più sensato è ora
|
||||
`BTC 1h rd0.20 ru0.06 L6 regime=range trend_max1.5`**: PROMOSSO, corr 0.23, e la **miglior coda
|
||||
2018 (−27.7%)** grazie al regime-gate. **Prima di QUALSIASI deploy**: (1) backtest che INCLUDA il
|
||||
2018 nel gate (non solo IDX 2021+), (2) ledger shadow reale per i fill intrabar/maker, (3) half-size.
|
||||
La pulizia del feed resta il guadagno trasversale più grande (irrobustisce ogni backtest del progetto).
|
||||
|
||||
---
|
||||
|
||||
## 8. I 3 PASSI PRE-DEPLOY + STUDIO SL/TP (ladder_sltp_study.py)
|
||||
|
||||
**[1] Valutazione 2018-INCLUSIVE** (standalone, tutta la storia; il gate IDX2021+ è cieco al 2018):
|
||||
| Candidato (sl0.12/tp0.05) | full_sh | full_dd | oos_sh | DD 2018 | DD 2021 |
|
||||
|---|---:|---:|---:|---:|---:|
|
||||
| BTC 1h L6 **range1.5** | 3.18 | −27.7% | 4.95 | **−27.7%** | −14.8% |
|
||||
| BTC 1h L3 none | 2.93 | −60.2% | 5.51 | **−50.3%** | −10.8% |
|
||||
|
||||
Il regime-gate già dimezza il tail vero (2018: −50%→−27.7%). Senza gate la griglia long-only è insostenibile (−60%).
|
||||
|
||||
**Studio SL/TP** (sweep sl_buf × tp_buf sul candidato regime-gated, full 2018+):
|
||||
- **Sweet spot: `sl_buf=0.10, tp_buf=0.03` → DD 2018 −23.5%** (da −27.7%), oos_sh 5.06, full_sh 2.92. Migliora il tail SENZA intaccare l'edge.
|
||||
- **Lezione (conferma il prior del progetto):** un SL **troppo stretto PEGGIORA** (sl 0.06 → −33/−35%): stoppa e rideploya più in basso nel coltello che cade = la trappola del falso-negativo mean-reversion. Un SL **troppo largo** (0.20) idem (−29/−31%, oos più basso). Il bene sta in mezzo (0.10).
|
||||
- **Il SL da solo (senza regime-gate) è ERRATICO** (tabella L3 none non-monotona: −20% → −52% → −43% al variare di pochi punti): è il **regime-gate** il controllo primario della coda; il SL moderato fine-tuna. Catastrophe-control = "non deployare nel bear" (regime) + "cappa l'episodio" (SL 0.10), NON uno stop stretto.
|
||||
|
||||
**[2] Fill maker vs taker** (Deribit: i livelli sono LIMIT → maker):
|
||||
| fee | oos_sh | DD 2018 | gate½ |
|
||||
|---|---:|---:|---|
|
||||
| taker 0.10% RT (harness) | 5.06 | −23.5% | PROMOSSO (OOS 10.86→11.0, corr 0.195) |
|
||||
| **maker 0%** (Deribit reale) | 5.18 | −22.7% | PROMOSSO (OOS→11.0, corr 0.194) |
|
||||
|
||||
Il maker è leggermente MIGLIORE → la harness taker è conservativa, nessun fee-cliff. (La parte live = shadow ledger reale resta il passo operativo finale.)
|
||||
|
||||
**[3] Half-size:** il gate "half" è già a metà size e PROMOSSO; la coda 2018 standalone −23.5% si dimezza sul book (~−12% in un 2018-repeat a half-size) = reale ma gestibile.
|
||||
|
||||
### CONFIG FINALE raccomandata (con SL/TP aggiunti)
|
||||
> **BTC 1h · regime=range trend_max 1.5 · rd 0.20 / ru 0.06 / 6 livelli · sl_buf 0.10 / tp_buf 0.03 · HALF-size.**
|
||||
> - Tail 2018-inclusive: −23.5% standalone (~−12% sul book a half) — reale ma controllato dal regime-gate + SL moderato.
|
||||
> - Gate PORT06: PROMOSSO (OOS 10.86→11.0, corr 0.195); maker Deribit lo migliora; nessun fee-cliff.
|
||||
> - **Unico passo residuo: shadow ledger reale** (fill intrabar/maker su Deribit) — operativo, non backtestabile.
|
||||
|
||||
Caveat onesti residui: l'OOS gain al peso deployabile è modesto (10.86→11.0); il tail 2018 non è zero (−12% a half); l'edge dipende dai fill intrabar (per i LIMIT è legittimo, ma lo shadow lo deve confermare).
|
||||
@@ -0,0 +1,109 @@
|
||||
# 2026-06-19 — Reset: storico certificato da Deribit mainnet, ripartenza pulita
|
||||
|
||||
Documento di fondazione per la nuova ricerca. Riassume perché la libreria "validata" è
|
||||
crollata, come abbiamo ricostruito e **certificato** lo storico, e quali sono le regole
|
||||
e l'universo dati su cui costruire da qui in poi. Lo storico delle 60+ voci di diario
|
||||
precedenti e tutto il codice/strategie vecchio sono archiviati in `Old/` (non cancellati).
|
||||
|
||||
---
|
||||
|
||||
## 1. Cosa è successo — la contaminazione
|
||||
|
||||
L'intera libreria ("+201% / +1238% / +16492% validato OOS") era basata su uno **storico
|
||||
contaminato**. Radice nel codice (`src/data/downloader.py`, ora in `Old/`): la fase
|
||||
"Deribit" veniva pescata da Cerbero col **token TESTNET** (print fantasma) e la fase
|
||||
storica da **Binance/USDT**. Gli edge nascevano da wick fantasma e da entry su estremi di
|
||||
candela mai scambiati.
|
||||
|
||||
**Binance NON è la verità** (cross-check multi-venue): è denominato USDT, sistematicamente
|
||||
~10 bps fuori dal consenso, e sotto depeg USDT (mag-2022) fino al **3.16%** lontano dal
|
||||
prezzo USD reale. "Ripulire verso Binance" avrebbe iniettato errore. Il venue più vicino al
|
||||
consenso (0-1 bps) è **Deribit mainnet** — che è anche **dove eseguiamo**: ancora migliore e
|
||||
ancora rilevante coincidono.
|
||||
|
||||
## 2. La via scelta — rebuild da Deribit mainnet
|
||||
|
||||
`scripts/analysis/rebuild_history.py` (TENUTO): ricostruzione da **`ccxt.deribit` mainnet**
|
||||
(pubblico, tokenless). Principi:
|
||||
- **Strumento prezzo**: BTC/ETH → inverse (storia lunga 2018/2019, ~3 bps dal lineare USDC
|
||||
che eseguiamo); alt → lineare USDC (unica opzione, solo dal 2022).
|
||||
- **Base unica + resample**: si scarica un solo TF base (5m) e si derivano 15m/1h →
|
||||
coerenza interna garantita (si valida una serie, non venti).
|
||||
- **Copertura onesta**: major 2018/2019→oggi; alt SOLO dal 2022 (prima non eseguibili su
|
||||
Deribit → backtestarli pre-2022 = validare un mercato che non potevamo tradare).
|
||||
|
||||
Eseguito su 8 asset → 24 feed (5m/15m/1h) il 2026-06-19.
|
||||
|
||||
## 3. Il verdetto — la libreria era artefatto
|
||||
|
||||
Ri-eseguiti tutti i backtest sul feed pulito con gli engine canonici (ora in `Old/`).
|
||||
|
||||
**FADE** (6 sleeve, 1h E 15m): tutte NEGATIVE, ogni anno. Es. MR01_BTC −41% (claim +201%),
|
||||
MR01_ETH −25% (claim +1238%), MR02_ETH −83% a 15m. I numeri 15m coincidono col check mainnet
|
||||
indipendente del 18-06 → due path-dati separati, stessa conclusione.
|
||||
|
||||
**Intera libreria** (`report_families.py`, ora in `Old/`): ogni portafoglio profondamente
|
||||
negativo (MASTER Sharpe −2.3…−3.0, DD ~40%; il claim "Sharpe ~5, ogni anno positivo" è falso).
|
||||
- ☠️ **FADE / PAIRS / XS01 / TSM01**: morti o inerti. Il flagship PR_ETHBTC e il blend 15m
|
||||
deployato live sono negativi ogni anno.
|
||||
- 🟡 **HONEST** (TR01 volatile, DIP01 marginale) e **SH01** (specie ETH, 5/6 anni +) mostrano
|
||||
segnale residuo — ma NON bastano a rendere positivo alcun portafoglio, e vanno distinti da
|
||||
fortuna di regime. Sono gli UNICI candidati a sopravvivere a una ri-validazione seria.
|
||||
|
||||
## 4. La certificazione dello storico
|
||||
|
||||
`scripts/analysis/certify_feed.py` (TENUTO) — suite read-only, 4 blocchi:
|
||||
1. **Integrità**: 24/24 feed OK (zero violazioni OHLC, NaN, prezzi≤0, dup; **zero gap**).
|
||||
2. **Coerenza resample**: 5m→15m/1h ricalcolato == salvato, **maxΔ 0.00 bps**.
|
||||
3. **Spike**: i pochi sospetti sono crash REALI (COVID 2020, mag-2021, FTX 2022), non contaminazione.
|
||||
4. **Cross-venue vs Coinbase USD** (venue indipendente, USD non USDT), storia intera per anno:
|
||||
|
||||
| Asset | median bps | barre >1% | Verdetto |
|
||||
|---|---|---|---|
|
||||
| **BTC** | 2.0–6.4 | 0.0–0.2% | 🟢 certificato pulito, 2018→oggi |
|
||||
| **ETH** | 2.0–6.0 | 0.0–0.2% | 🟢 certificato pulito, 2019→oggi |
|
||||
| SOL | 4–8 | 0–1.3% | 🟡 pulito da ~2024; 2022-23 rumoroso |
|
||||
| ADA | 9–13 | 0.3–3.5% | 🟡 basis largo persistente |
|
||||
| XRP | — | — | ⚠️ non certificabile (Coinbase delistò XRP 2021-23, causa SEC) |
|
||||
| LTC / DOGE | 24–36 (2022) | 1–21% | 🔴 divergenti + 50-82% barre flat |
|
||||
| BNB | — | — | ⚠️ non listato su Coinbase + storia da 2024-10 |
|
||||
|
||||
I max bps su BTC/ETH (889/594) sono singole barre di crash; mediana annua 2-6 bps → **la
|
||||
storia vecchia, dove viveva la contaminazione, è ora pulita contro un venue USD indipendente.**
|
||||
|
||||
**Illiquidità alt** (barre flat O=H=L=C): BTC/ETH ~0% a 1h; alt pesanti (LTC 5m 82%, run fino a
|
||||
~3 giorni; DOGE/BNB ~78%). I 5m/15m alt "tradano" un book fermo — spiega a posteriori la
|
||||
fragilità di pairs-su-LTC e XS01.
|
||||
|
||||
## 5. REGOLE per la nuova ricerca
|
||||
|
||||
- **Universo certificato = BTC / ETH**, ogni timeframe (5m/15m/1h). È l'unico dato attivo in
|
||||
`data/raw` (gli alt sono archiviati in `Old/data/raw`). Il guardrail è fisico: `load_data`
|
||||
su un alt solleva `FileNotFoundError`.
|
||||
- **Fonte di verità = Deribit mainnet** (dove eseguiamo). Binance/USDT solo come check, mai
|
||||
come ancora. Aggiornare il dato con `rebuild_history.py`, MAI col vecchio `download_all`
|
||||
(token testnet).
|
||||
- **Metodologia** (CLAUDE.md, invariata): ingresso eseguibile (direzione/prezzo decisi entro
|
||||
`close[i]`, mai entry su estremi di candela), backtest netto fee 0.10% RT, OOS held-out +
|
||||
griglia + sweep fee. **In più, lezione di oggi**: il gate PORT06 full+OOS NON basta — un
|
||||
edge va incrociato con la **liquidità reale** del book e con la **plausibilità del prezzo**
|
||||
(cross-venue), o si finisce per "validare" un book fermo / wick fantasma.
|
||||
|
||||
## 6. Stato della ripartenza (cleanup eseguito)
|
||||
|
||||
- **Archiviato in `Old/`** (git preserva tutto): tutte le strategie, lo stack live
|
||||
(`src/live`, `src/portfolio`, runner/executor, yml, docker), i ~100 script di ricerca/gate,
|
||||
waste/games/portfolios, i dati non certificati + cache, le 60+ voci di diario, le spec vecchie.
|
||||
- **Skeleton tenuto**: `src/strategies/{base,indicators}` (Strategy ABC), `src/fractal`,
|
||||
`src/backtest/engine`, `src/data/downloader` (`load_data`); i 4 tool dati certificati
|
||||
(`rebuild_history`, `certify_feed`, `audit_feed`, `multi_source_check`); dati BTC/ETH;
|
||||
config base; i due summary sui frattali (tesi di ricerca).
|
||||
- **Esecuzione DISABILITATA**, conto mainnet flat. La riorganizzazione è in staging (non
|
||||
committata).
|
||||
|
||||
### Code minori rimasti
|
||||
- 3 dir di stato live root-owned (`data/portfolio_paper{,_stats}`, `data/portfolios`) non
|
||||
archiviabili senza `sudo` → spostare a mano in `Old/data/` quando comodo.
|
||||
- `clean_feed.py` (arbitrava verso Binance) è già archiviato — approccio superato.
|
||||
- XRP ri-certificabile solo su venue USD con storia profonda (marginale, non core).
|
||||
- `CLAUDE.md` è in gran parte stale (descrive strategie morte) → va riscritto per il reset.
|
||||
@@ -1,17 +0,0 @@
|
||||
# Diario di Ricerca — PythagorasGoal
|
||||
|
||||
Registro cronologico di ogni passo del progetto: decisioni, esperimenti, risultati attesi e reali.
|
||||
|
||||
## Formato entry
|
||||
|
||||
Ogni entry segue il formato:
|
||||
|
||||
```
|
||||
### YYYY-MM-DD HH:MM — Titolo
|
||||
|
||||
**Cosa:** descrizione azione
|
||||
**Perché:** motivazione
|
||||
**Atteso:** risultato previsto
|
||||
**Reale:** risultato effettivo
|
||||
**Note:** osservazioni, lezioni apprese
|
||||
```
|
||||
Reference in New Issue
Block a user