diff --git a/CLAUDE.md b/CLAUDE.md index c64a839..3bf15e0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -34,7 +34,8 @@ src/live/ → paper trading live multi-strategia cerbero_client.py → client HTTP per Cerbero MCP (Deribit testnet) signal_engine.py → squeeze + ML real-time (legacy ML01, ora in waste) + validazione OOS telegram_notifier.py → notifiche Telegram per trade -scripts/strategies/ → strategie con edge validato OOS (solo MR01_bollinger_fade) +scripts/strategies/ → strategie con edge validato OOS: FADE (MR01/MR02/MR07), + HONEST (DIP01/TR01/ROT02), PAIRS (PR01), TSMOM + portafogli (PORT01/02/03) scripts/waste/ → strategie scartate (W01-W28 + famiglia squeeze SQ/MT/ML/AD/CM/PD) scripts/analysis/ → ricerca/validazione OOS fee-aware (strategy_research, oos_validation, ...) strategies.yml → config multi-strategy paper trader @@ -48,11 +49,13 @@ data/raw/ → file .parquet OHLCV (gitignored) ```bash uv sync # installa dipendenze uv run python -m src.data.downloader # scarica dati storici -uv run python scripts/strategies/MR01_bollinger_fade.py # strategia attiva (mean-reversion) +uv run python scripts/strategies/MR01_bollinger_fade.py # backtest una strategia (es. fade) +uv run python scripts/strategies/PR01_pairs_reversion.py # backtest pairs market-neutral uv run python scripts/analysis/strategy_research.py # ricerca strategie fee-aware OOS uv run python scripts/analysis/oos_validation.py # perche' la famiglia squeeze e' scartata -uv run python scripts/analysis/validate_worker_mr01.py # replay worker reale su MR01 -uv run python -m src.live.multi_runner # paper trading live multi-strategia +uv run python scripts/analysis/report_families.py # report per anno di tutte le famiglie +uv run python scripts/analysis/validate_worker_pairs.py # replay worker 2 gambe == backtest +uv run python -m src.live.multi_runner # paper trading live multi-strategia (strategie + pairs) docker compose up -d # deploy Docker uv run pytest # test ``` @@ -198,10 +201,14 @@ queste fade, ma va confermato col paper trader live prima di rischiare capitale Orchestratore che esegue N strategie in parallelo su dati live Cerbero, ognuna con €1000 USDC virtuali indipendenti. -**Config:** `strategies.yml` — lista strategie con asset, tf, sizing, parametri. Attualmente solo MR01 (BTC/ETH 1h). -**Persistenza:** `data/paper_trades/{strategy}___{asset}__{tf}/` con `trades.jsonl` (append-only) + `status.json` (resume al restart, include tp/sl/max_bars). +**Config:** `strategies.yml` — due sezioni: `strategies` (single-leg: fade/honest) e +`pairs` (a 2 gambe). Attive: 6 fade (MR01/MR02/MR07 × BTC/ETH) + 5 coppie PR01. +**Due worker:** `strategy_worker.py` (single-leg) e `pairs_worker.py` (2 gambe, +long A / short B sullo z-score del log-ratio, fee su 2 gambe). +**Persistenza:** `data/paper_trades/{worker_id}/` con `trades.jsonl` (append-only) + `status.json` (resume al restart). **Hot-add:** aggiungi riga YAML → `docker compose restart` → storico intatto. -**Exit strategia:** se un `Signal` porta `tp`/`sl`/`max_bars` in `metadata` (come MR01), il worker esce su take-profit/stop-loss/time-limit a quei livelli; altrimenti usa il fallback `hold_bars`/stop -2%. +**Exit strategia:** se un `Signal` porta `tp`/`sl`/`max_bars` in `metadata` (come le fade), il worker esce su take-profit/stop-loss/time-limit; i pairs escono su |z|≤z_exit o max_bars. +**Naming Deribit (feed live):** major = `-PERPETUAL` (inverse); alt = `_USDC-PERPETUAL` (lineari USDC). Vedi INSTRUMENT_MAP in `multi_runner.py`. **Notifiche:** Telegram per ogni trade (richiede `.env` con `TELEGRAM_BOT_TOKEN` e `TELEGRAM_CHAT_ID`). ## Convenzioni diff --git a/README.md b/README.md index 056e41b..b34b448 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Sistema di riconoscimento pattern frattali e predizione per il trading di cripto ## Obiettivo -Partendo da un capitale iniziale di €1.000, raggiungere un profitto medio di €50 al giorno entro 6–8 mesi, tramite strategie algoritmiche che combinano analisi frattale, squeeze di volatilità e machine learning. +Partendo da un capitale iniziale di €1.000, raggiungere un profitto medio di €50 al giorno entro 6–8 mesi, tramite un portafoglio di strategie algoritmiche poco correlate fra loro — mean-reversion, trend/rotazione e spread market-neutral — validate out-of-sample e fee-aware. ## Risultati @@ -15,18 +15,40 @@ Partendo da un capitale iniziale di €1.000, raggiungere un profitto medio di > ingresso onesto (`close[i]`) e fee reali, l'edge sparisce e tutte perdono, anche > a fee zero. Dettagli e prove: `scripts/analysis/oos_validation.py`. -Dopo una validazione **out-of-sample, fee-aware** di tutte le famiglie, l'unica con -edge netto reale è il **mean-reversion** (i breakout *rientrano*, non continuano): +Dopo una validazione **out-of-sample, fee-aware** di molte famiglie di strategie, +emergono quattro famiglie con edge netto reale, tutte radicate nella stessa lezione +(in cripto la **mean-reversion** funziona, la continuazione no) o nella diversificazione: -| Codice | Strategia | Mercato | Edge OOS netto | Max DD | Robustezza | -|--------|-----------|---------|----------------|--------|------------| -| **MR01** | Bollinger Fade (mean-reversion) | BTC 1h | **+196 / +201%** | 15% | ✅ | -| **MR01** | Bollinger Fade (mean-reversion) | ETH 1h | **+251%** | ~25% | ⚠️ DD alto | +| Famiglia | Meccanismo | Strategie | Profilo (netto OOS) | +|----------|-----------|-----------|---------------------| +| **FADE** | mean-reversion intraday 1h (long/short, BTC/ETH) | MR01 Bollinger, MR02 Donchian, MR07 Return-reversal | Acc 52-55%, DD 18-34% | +| **HONEST** | long-only multi-regime multi-crypto | DIP01 dip-buy, TR01 EMA-trend, ROT02 dual-momentum | CAGR 31-56%, DD 15-27% | +| **PAIRS** | spread reversion *market-neutral* (2 gambe) | PR01 ETH/BTC, LTC/ETH, ADA/ETH, BTC/LTC, ETH/SOL | Sharpe 2.0-4.4, corr col mercato ~0.05 | +| **TSMOM** | time-series momentum multi-orizzonte | TSM01 (3/6/12m + risk-off) | diversificatore, DD 15-22% | -Netto dopo **fee realistiche Deribit 0.10% RT** (taker), leva 3x, pos 15%, su finestra -held-out (nov 2023→mag 2026). MR01 è positivo su **tutta** la griglia parametri -(`n∈{14,20,30,50}` × `k∈{2.0,2.5,3.0}`) e per **ogni** livello di fee 0.00-0.20% RT — -margine di sicurezza ampio, niente parametro fortunato. Ri-validato col worker live reale. +Tutti i numeri sono **netti** dopo fee realistiche (Deribit 0.10% RT single-leg, 0.20% +RT/coppia sui pairs), leva 3x, su finestra held-out. Le strategie sono robuste su griglia +parametri, sweep fee 0.00-0.20% RT e — per i pairs — validate con **walk-forward** e +config universale (niente cherry-picking). + +### Portafoglio combinato (la vera leva anti-drawdown) + +Le famiglie sono **quasi scorrelate fra loro** (~0.05). Combinandole in un unico +portafoglio equipesato il drawdown crolla sotto quello di ogni singola sleeve: + +| Portafoglio | CAGR | Max DD | Sharpe | +|-------------|------|--------|--------| +| FADE (6 sleeve) | ~46% | 8% | 3.9 | +| HONEST (3 sleeve) | ~46% | 13% | 2.2 | +| **MASTER** (FADE + HONEST, 9) | ~47% | **5%** | 4.2 | +| **MASTER + PAIRS + TSM01** (15) | ~67% | ~5% | ~6 | + +> 🔎 **Numeri sobri (anti-overfit).** L'OOS singolo cade nel regime favorevole 2024-25: +> i valori di Sharpe/DD sopra sono ottimistici di circa il 50%. Da pianificare per le +> decisioni: **Sharpe atteso ~5**, **worst-drawdown su 90 giorni ~6%**, profilo che regge +> a leva 2x con slippage raddoppiato. Configurazione raccomandata: equal-weight, leva 2x, +> con un cap sull'allocazione ai pairs (~30-35%, poiché concentrano ~57% del rischio). +> Tutto resta da confermare nel paper trading live. ## Come funziona @@ -42,6 +64,21 @@ di prezzo **rientrano verso la media** più di quanto proseguano: Nessun look-ahead: direzione e livelli sono calcolati con dati fino a `close[i]`. +### Le altre famiglie + +- **FADE** (oltre MR01): MR02 fada la rottura del canale Donchian verso il centro; + MR07 fada il movimento di barra estremo misurato in deviazioni standard dei + rendimenti. Stessa logica di reversione, indicatori indipendenti. +- **HONEST** (long-only, multi-crypto): DIP01 compra i dip estremi e rivende al + recupero; TR01 segue il trend con incrocio di EMA su un paniere; ROT02 ruota ogni + giorno sui tre asset col momentum più forte, andando in cash quando BTC è sotto la + sua media (risk-off). Coprono i regimi di trend e rotazione, complementari alle fade. +- **PAIRS** (market-neutral): scommette sul rientro verso la media del log-ratio fra + due cripto (z-score). Long su una, short sull'altra: l'esposizione netta al mercato è + quasi nulla (correlazione ~0.02), il che la rende un diversificatore eccellente. +- **TSMOM**: tiene gli asset con momentum positivo persistente su più orizzonti + (3/6/12 mesi), con overlay risk-off. Rende meno ma è poco correlato, utile in ensemble. + ### Perché lo squeeze breakout è stato abbandonato L'ipotesi originale era opposta — *continuazione* dopo la compressione di volatilità @@ -71,16 +108,17 @@ PythagorasGoal/ │ │ ├── base.py # Strategy, Signal, BacktestResult, YearlyStats │ │ └── indicators.py # keltner_ratio, detect_squeezes, ema, atr, rv, corr │ └── live/ # Paper trading live su Deribit testnet -│ ├── multi_runner.py # Orchestratore multi-strategia -│ ├── strategy_worker.py # Worker indipendente con stato persistente +│ ├── multi_runner.py # Orchestratore multi-strategia (strategie + pairs) +│ ├── strategy_worker.py # Worker single-leg con stato persistente +│ ├── pairs_worker.py # Worker a 2 gambe per i pairs (market-neutral) │ ├── strategy_loader.py # Import dinamico classi Strategy │ ├── cerbero_client.py # Client HTTP per Cerbero MCP │ ├── signal_engine.py # Squeeze + ML real-time (legacy) + validazione OOS │ └── telegram_notifier.py ├── scripts/ -│ ├── strategies/ # Strategie con edge validato OOS (solo MR01_bollinger_fade) -│ ├── waste/ # Strategie scartate (W01-W28 + famiglia squeeze SQ/MT/ML/AD/CM/PD) -│ └── analysis/ # Ricerca/validazione OOS fee-aware (strategy_research, oos_validation, ...) +│ ├── strategies/ # Strategie con edge validato OOS (FADE, HONEST, PAIRS, TSMOM + portafogli) +│ ├── waste/ # Strategie scartate (squeeze SQ/MT/ML/AD/CM/PD, MR03, ROT01, W01-W28) +│ └── analysis/ # Ricerca/validazione OOS fee-aware, gestione rischio, report ├── strategies.yml # Config multi-strategy paper trader ├── data/ │ └── raw/ # Parquet OHLCV (gitignored, ~70 MB) @@ -94,32 +132,65 @@ PythagorasGoal/ ## Strategie attive -Tutte le strategie estendono `src.strategies.base.Strategy` (`generate_signals() → backtest()`). +Le strategie single-asset estendono `src.strategies.base.Strategy` +(`generate_signals() → backtest()`); i pairs hanno un worker dedicato a 2 gambe. -| Codice | Script | Tipo | Descrizione | -|--------|--------|------|-------------| -| **MR01** | `MR01_bollinger_fade.py` | Mean-reversion | Fada la banda di Bollinger, TP alla media, SL ad ATR. Unica con edge netto validato OOS. | +| Codice | Script | Famiglia | Descrizione | +|--------|--------|----------|-------------| +| **MR01** | `MR01_bollinger_fade.py` | FADE | Fada la banda di Bollinger, TP alla media, SL ad ATR | +| **MR02** | `MR02_donchian_fade.py` | FADE | Fada la rottura del canale Donchian, TP al centro | +| **MR07** | `MR07_return_reversal.py` | FADE | Fada il movimento di barra estremo (z dei rendimenti) | +| **DIP01** | `DIP01_dip_reversion.py` | HONEST | Dip-buy long-only su z-score estremo | +| **TR01** | `TR01_ema_trend.py` | HONEST | EMA 20/100 trend-following su paniere cripto (4h) | +| **ROT02** | `ROT02_dual_momentum.py` | HONEST | Rotazione cross-sectional top-3 + risk-off (1d) | +| **PR01** | `PR01_pairs_reversion.py` | PAIRS | Spread reversion market-neutral su 5 coppie | +| **TSM01** | `tsmom_research.py` | TSMOM | Time-series momentum multi-orizzonte + risk-off | -La famiglia squeeze (SQ01-04, ML01, MT01, PD01, CM01, AD01) è in `scripts/waste/`: -edge storico = artefatto di look-ahead (vedi sezione *Come funziona*). +Le fade applicano un **filtro trend** opzionale (`trend_max`/`ema_long`): saltano i +segnali quando il prezzo è troppo esteso rispetto alla EMA200 — alza l'accuratezza e +abbassa il drawdown. Portafogli pronti: `PORT01` (honest), `PORT02` (fade), `PORT03` +(master fade+honest). -Per eseguire il backtest della strategia: +**Scartate** (in `scripts/waste/`): la famiglia squeeze (SQ01-04, ML01, MT01, PD01, +CM01, AD01 — artefatto di look-ahead), MR03 Keltner (debole/ridondante con MR01) e +ROT01 (dominata da ROT02). + +### Comandi utili ```bash +# Backtest di una strategia uv run python scripts/strategies/MR01_bollinger_fade.py -``` +uv run python scripts/strategies/PR01_pairs_reversion.py -Per la ricerca/validazione fee-aware out-of-sample: +# Ricerca e validazione fee-aware out-of-sample +uv run python scripts/analysis/strategy_research.py # screening famiglie + deep-dive fade +uv run python scripts/analysis/strategy_research_v2.py # MR02 / MR03 / MR07 +uv run python scripts/analysis/oos_validation.py # perche' la famiglia squeeze e' scartata +uv run python scripts/analysis/pairs_research.py # ricerca + verifica no-look-ahead dei pairs -```bash -uv run python scripts/analysis/strategy_research.py # screening famiglie + deep-dive MR01 -uv run python scripts/analysis/oos_validation.py # perche' la famiglia squeeze e' scartata -uv run python scripts/analysis/validate_worker_mr01.py # replay del worker live su MR01 +# Gestione rischio, combinazione, report +uv run python scripts/analysis/risk_management.py # filtro trend + portafoglio fade +uv run python scripts/analysis/combine_portfolio.py # combinare fade + honest +uv run python scripts/analysis/combine_v2.py # master esteso con pairs + TSM01 +uv run python scripts/analysis/report_families.py # report per anno di tutte le famiglie + +# Validazione dei worker live (replay == backtest) +uv run python scripts/analysis/validate_worker_mr01.py # worker single-leg su MR01 +uv run python scripts/analysis/validate_worker_pairs.py # worker a 2 gambe sui pairs +uv run python scripts/analysis/live_smoke_pairs.py # smoke test feed live reale dei pairs ``` ## Paper Trading Live -Il multi-strategy runner esegue N strategie in parallelo su dati live da Cerbero MCP, ognuna con €1000 USDC virtuali indipendenti. Se un `Signal` porta `tp`/`sl`/`max_bars` in `metadata` (come MR01), il worker chiude su take-profit alla media / stop-loss ad ATR / time-limit; altrimenti usa il fallback `hold_bars`/stop -2%. +Il multi-strategy runner esegue N strategie in parallelo su dati live da Cerbero MCP, +ognuna con €1000 USDC virtuali indipendenti. Gestisce due tipi di worker: + +- **Single-leg** (`strategy_worker.py`): per le strategie direzionali. Se un `Signal` + porta `tp`/`sl`/`max_bars` in `metadata` (come le fade), chiude su take-profit / + stop-loss / time-limit; altrimenti usa il fallback `hold_bars`/stop -2%. +- **Due gambe** (`pairs_worker.py`): per i pairs market-neutral. Apre long su una gamba + e short sull'altra, esce sul rientro dello z-score o per time-limit, conta le fee su + entrambe le gambe. Validato: il replay storico coincide *esattamente* col backtest. ### Avvio @@ -141,19 +212,24 @@ defaults: position_size: 0.15 leverage: 3 -strategies: +strategies: # strategie single-leg - name: MR01_bollinger_fade asset: BTC tf: 1h enabled: true - params: - bb_window: 50 - k: 2.5 - sl_atr: 2.0 - max_bars: 24 + params: { bb_window: 50, k: 2.5, sl_atr: 2.0, max_bars: 24, trend_max: 3.0, ema_long: 200 } + +pairs: # strategie a 2 gambe (market-neutral) + - name: PR01_pairs_reversion + a: ETH + b: BTC + tf: 1h + enabled: true + params: { n: 50, z_in: 2.0, z_exit: 0.75, max_bars: 72, jump_max: 0.08 } ``` -Per aggiungere una strategia: nuova riga in `strategies.yml`, poi `docker compose restart`. Lo storico delle strategie esistenti rimane intatto. +Per aggiungere una strategia: nuova riga in `strategies.yml` (sezione `strategies` o +`pairs`), poi `docker compose restart`. Lo storico delle strategie esistenti rimane intatto. ### Persistenza @@ -194,12 +270,19 @@ uv run python -m src.live.multi_runner ## Dati -| Asset | Timeframe | Candele | Copertura | -|-------|-----------|---------|-----------| -| BTC | 5m / 15m / 1h | 883K / 294K / 74K | 2018-01 → oggi | -| ETH | 5m / 15m / 1h | 882K / 294K / 74K | 2018-01 → oggi | +| Asset | Timeframe | Copertura | +|-------|-----------|-----------| +| BTC, ETH | 5m / 15m / 1h | 2018-01 → oggi | +| SOL, LTC, ADA, XRP, BNB, DOGE | 15m / 1h | 2019-2022 → oggi (variabile per asset) | -Fonte primaria: Deribit perpetual via Cerbero MCP. Fallback: Binance spot via ccxt. Formato: Apache Parquet. +Fonte primaria: perpetual Deribit via Cerbero MCP. Fallback: Binance spot via ccxt. +Formato: Apache Parquet (in `data/raw/`, gitignored). + +> **Nota sul naming Deribit (per il feed live).** I major sono perpetui *inverse* +> (`BTC-PERPETUAL`, `ETH-PERPETUAL`); gli altcoin sono perpetui *lineari USDC* +> (`SOL_USDC-PERPETUAL`, `LTC_USDC-PERPETUAL`, …) con storia dal 2022. Attenzione: +> `LTC-PERPETUAL`/`ADA-PERPETUAL` non esistono e `SOL-PERPETUAL` restituisce dati +> errati — per gli altcoin usare sempre la forma `_USDC-PERPETUAL`. ## Riferimenti