Files
PythagorasGoal/docs/diary/2026-05-28.md
T
Adriano Dal Pastro 8fd2c16cac fix(live): MT01 usa trend 1h live da Cerbero, non dal parquet statico
Il paper trader restava a zero trade: il feed Cerbero era fermo a
mezzanotte (bug end_date lato cerbero-mcp, poi risolto) e MT01 leggeva
il trend 1h da un parquet statico, di fatto congelandolo (gap ~15h sul
bar corrente). Ora il runner fa fetch 1h live per le strategie MTF e lo
passa a generate_signals via il parametro df_1h (fallback al parquet se
assente). Aggiornati CLAUDE.md, README e diario 2026-05-28.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 15:30:26 +00:00

5.6 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:

  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.