Trovate e promosse 3 strategie con edge netto distinto da MR01, stessa metodologia (ingresso close[i], netto fee 0.10% RT + leva 3x, OOS ultimo 30%, robustezza su griglia + sweep fee 0.00-0.20%): - MR02 Donchian Fade: fade rottura canale H/L, TP al centro. BTC +172% OOS. - MR03 Keltner Fade: canale ATR su EMA (indipendente da Bollinger). BTC +112%. - MR07 Return Reversal: fade movimento di barra estremo (z dei rendimenti). BTC +105%. Tutte positive netto OOS su entrambi gli asset e su tutto lo sweep fee, anche 0.20% RT pessimista (validate anche via oos_validation live-path). Scartate MR04 (= MR01 riparametrizzato), MR05 (ADX non robusto), MR06 (RSI2 ETH neg). Base condivisa fade_base.FadeStrategy (backtest intrabar TP/SL/max_bars). Aggiunte a strategy_loader e strategies.yml (BTC+ETH 1h). Ricerca in strategy_research_v2.py. Diario e CLAUDE.md aggiornati. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8.3 KiB
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:
end_datedata-nuda tronca a mezzanotte:end=oggirestituiva candele solo fino aoggi 00:00. Ildflive finiva sempre alla barra di mezzanotte e non avanzava durante la giornata → nessun breakout fresco sull'ultima barra → nessun ingresso (condizione workerlast_signal.idx >= last_idx - 1).- 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 oggisearchsortedcadeva 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_signalsaccetta undf_1hopzionale (fallback al parquet se assente).StrategyWorker.tick(df, df_1h=None)lo inoltra ai signal.multi_runnerfa 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 undownload_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
- 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). - 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.