# 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.