# PythagorasGoal — Istruzioni per agenti ## Panoramica Progetto di ricerca: riconoscimento pattern frattali per trading algoritmico su criptovalute (BTC, ETH). L'obiettivo è arrivare a €50/giorno di profitto partendo da €1.000, entro 6–8 mesi. ## Stack - **Linguaggio:** Python 3.11+ - **Package manager:** uv (dipendenze in `pyproject.toml`, lock in `uv.lock`) - **Dati:** Parquet in `data/raw/` (non committati, ~70 MB) - **ML:** scikit-learn (GradientBoostingClassifier) - **Analisi:** numpy, pandas, scipy - **API dati:** Cerbero MCP su `cerbero-mcp.tielogic.xyz` (Deribit, Bybit, Hyperliquid), ccxt/Binance come fallback - **Config:** pyyaml per `strategies.yml` ## Struttura ``` src/data/ → download e caricamento dati (downloader.py) src/fractal/ → indicatori frattali (patterns.py, indicators.py, similarity.py) src/backtest/ → engine di backtesting (engine.py) src/strategies/ → classe base Strategy ABC + indicatori condivisi base.py → Strategy, Signal, BacktestResult, YearlyStats indicators.py → keltner_ratio, detect_squeezes, ema, atr, rv, correlation src/live/ → paper trading live multi-strategia multi_runner.py → orchestratore: carica YAML, fetch candele, tick worker strategy_worker.py → worker indipendente: capital, trade log, stato persistente. Exit guidati da strategia (TP/SL/max_bars via Signal.metadata), fallback hold_bars/stop -2%. Usa fee_rt della strategia. strategy_loader.py → import dinamico classi Strategy da scripts/strategies/ 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/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 docs/diary/ → diario di ricerca giornaliero docs/specs/ → specifiche di design data/raw/ → file .parquet OHLCV (gitignored) ``` ## Comandi ```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/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 docker compose up -d # deploy Docker uv run pytest # test ``` ## Dati storici Scaricati e salvati localmente in Parquet. Per rigenerarli: ```python from src.data.downloader import download_all, load_data download_all() # scarica BTC + ETH su 5m/15m/1h dal 2018 df = load_data("ETH", "15m") # carica un asset/timeframe ``` Fonte primaria: Cerbero MCP (endpoint `/mcp-deribit/tools/get_historical`). Token observer: nel file `secrets/observer.token` del progetto CerberoSuite. ## Strategie attive > **LEZIONE CRITICA (2026-05-28).** L'intera famiglia squeeze-breakout (SQ01-04, > MT01, ML01, AD01, CM01, PD01) è stata **scartata in `scripts/waste/`**: le > accuratezze storiche 76-82% erano un **artefatto di look-ahead**. Quei backtest > decidono la direzione con `sign(close[i]-close[i-1])` (la candela di breakout `i`) > ma entrano a `close[i-1]` — cioè comprano *prima* della candela che usano per > scegliere la direzione. Dal vivo il worker scopre il breakout solo a `close[i]` > ed entra lì: l'edge sparisce (win-rate ~47%, lancio di moneta). Sotto ingresso > onesto e fee reali **tutte perdono, anche a fee zero**. Inoltre i breakout > *rientrano* (mean-reversion > continuation). Vedi `scripts/analysis/oos_validation.py` > e `intrabar_test.py`. Tutte le strategie estendono `src.strategies.base.Strategy` (`generate_signals() → backtest()`). **Unica strategia con edge netto validato:** | Codice | Nome | Tipo | Edge OOS netto | DD | Note | |--------|------|------|----------------|----|------| | **MR01** | Bollinger Fade | Mean-reversion | **BTC 1h n50 k2.5: +201% / +196% (worker)** | 15% | Fada la banda, TP alla media, SL ad ATR | MR01 è robusto su **tutta** la griglia parametri (`n∈{14,20,30,50}` × `k∈{2.0,2.5,3.0}`, entrambi gli asset → tutte positive OOS) e su **tutte** le fee 0.00-0.20% RT. Validato col worker reale: BTC +196% / ETH +251% OOS (nov 2023→mag 2026). Ricerca completa: `scripts/analysis/strategy_research.py`. **Metodologia obbligatoria per ogni nuova strategia** (per non ripetere l'errore squeeze): 1. Ingresso eseguibile: direzione e prezzo decisi con dati **fino a `close[i]`**, mai `close[i-1]` con direzione da `i`. 2. Backtest **NETTO** dopo fee realistiche Deribit (**0.10% RT** taker, non 0.20%) + leva. 3. Validazione **out-of-sample** (held-out) + robustezza su griglia parametri + sweep fee. 4. Crea script in `scripts/strategies/`, aggiungi a `MODULE_MAP` (`strategy_loader.py`) e a `strategies.yml`. Strategie scartate storiche in `scripts/waste/` (W01-W28 + la famiglia squeeze). ## Multi-Strategy Paper Trader 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). **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%. **Notifiche:** Telegram per ogni trade (richiede `.env` con `TELEGRAM_BOT_TOKEN` e `TELEGRAM_CHAT_ID`). ## Convenzioni - Strategie in `scripts/strategies/` con codice univoco (MR01, ...). - Script scartati in `scripts/waste/` (W01-W28 + famiglia squeeze). - Diario in `docs/diary/YYYY-MM-DD.md`. Aggiornare dopo ogni esperimento significativo. - Nessun dato sensibile nei commit (token, chiavi API). Usare `.gitignore`. - Verificare sempre assenza di data leakage prima di fidarsi dei risultati. In particolare: `returns[i-w : i]` include `close[i]` che è un candle nel futuro — usare `returns[i-w : i-1]`. ## Attenzione - **Data leakage:** è stata trovata e corretta nello script 05. Ogni volta che si usano rendimenti logaritmici (`np.diff(np.log(close))`), ricordare che `returns[k]` usa `close[k+1]`. I feature devono fermarsi a `returns[i-2]` se il prezzo corrente è `close[i-1]`. - **Fee:** Deribit perp reale = taker ~0.05%/lato (**0.10% round-trip**), maker ~0%. Usare 0.10% RT come baseline (lo 0.20% storico era pessimista 2x). Includere SEMPRE nel backtest: sono vincolo di prim'ordine, molte operazioni = morte per fee. Il worker usa `strategy.fee_rt` (MR01 = 0.001). - **Leva:** testato con 3x. Aumentare a 5x migliora i rendimenti ma raddoppia il drawdown. - **GBM:** GradientBoostingClassifier di scikit-learn. Ensemble di alberi decisionali sequenziali. Walk-forward per evitare leakage temporale. - **Cerbero `get_historical` (fix 2026-05-28):** `end_date` come data nuda è inclusivo dell'intera giornata fino all'ultima candela chiusa (es. `end=oggi` arriva fino ad ora, non più a mezzanotte); accettati anche timestamp con orario (`...T14:00:00`, naive=UTC); nessun cap a ~5000 righe (paginazione interna). Il client passa già `end=oggi`, ora corretto. Prima del fix il paper trader restava a zero trade perché il feed era fermo a mezzanotte. - **Dati ETH Deribit 15m:** 14-30%/anno di candele *flat* (O=H=L=C, volume 0, run fino a ~54h) per bassa liquidità del perpetuo. Verificato (2026-05-28): escluderle NON cambia i backtest (Δacc ≤0.5pp) → edge robusto. Resta un caveat operativo (slippage/fill in trading reale, irrilevante per paper). BTC pulito eccetto picco ~8% nel 2024.