Esplorazione onesta con agenti paralleli su harness condiviso (explore_lab.py): ingresso close[i], netto fee, OOS, DD basso, attenzione fee. 7 famiglie su 9 sono rumore (stagionalita' oraria/mensile, cross-sectional reversal, opening-range, lead-lag BTC->alt, continuation intraday) e l'harness le rifiuta senza falsi positivi. Due edge reali verificati indipendentemente: - PR01 Pairs: spread reversion market-neutral su log-ratio z-score (ETH/BTC, LTC/ETH, ADA/ETH). ETH/BTC CAGR 144% Sharpe 4.04 OOS DD 17% 8/9 anni, corr mercato ~0.02, no-look-ahead verificato, regge fee 0.40%/coppia. Fee su 2 gambe (worker da estendere). - TSM01: TSMOM multi-orizzonte 3/6/12m + risk-off, distinto da ROT02 (corr 0.53), DD 22%/12% OOS, mai un anno negativo, regge fee 0.40%. Payoff: aggiungere i pairs (quasi scorrelati ~0.05) al MASTER -> CAGR 47->66%, DD 5.2->3.8% full / 4.7->3.3% OOS, Sharpe OOS 4.33->6.86 (combine_v2.py). Fix: explore_lab.get_df ora produce timestamp ms reale per 1d/4h (era placeholder). Diario 2026-05-29-exploration.md + nota CLAUDE.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
14 KiB
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 inuv.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
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:
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 consign(close[i]-close[i-1])(la candela di breakouti) ma entrano aclose[i-1]— cioè comprano prima della candela che usano per scegliere la direzione. Dal vivo il worker scopre il breakout solo aclose[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). Vediscripts/analysis/oos_validation.pyeintrabar_test.py.
Tutte le strategie estendono src.strategies.base.Strategy
(generate_signals() → backtest()). Le strategie mean-reversion condividono
src.strategies.fade_base.FadeStrategy (backtest intrabar TP/SL/max_bars).
Strategie con edge netto validato OOS fee-aware (tutte fade/mean-reversion):
| Codice | Nome | Meccanismo | Edge OOS netto (1h, fee 0.10% RT) | DD | Note |
|---|---|---|---|---|---|
| MR01 | Bollinger Fade | banda std attorno a SMA | BTC +201% / ETH +1238% | 15-72% | Fada la banda, TP alla media, SL ad ATR |
| MR02 | Donchian Fade | estremi canale H/L | BTC +172% / ETH enorme | 30-42% | Fada la rottura del canale, TP al centro |
| MR07 | Return Reversal | z dei rendimenti di barra | BTC +105% / ETH +195% | 25-46% | Fada il movimento estremo, exit in ATR; esposizione ~8% |
MR03 Keltner Fade spostata in
scripts/waste/: era la fade più debole (BTC Sharpe 1.22, il filtro trend la peggiorava) e ridondante con MR01 (stessa idea di banda). Rimuoverla dal portafoglio ne ha migliorato le metriche. La funzionekeltner_faderesta instrategy_research_v2.pycome record.
Lezione confermata: l'edge è sempre mean-reversion (i breakout rientrano). Il trend-following (Donchian trend, RSI cross) e gli oscillatori senza filtro (RSI revert, ADX-filtered fade) perdono netti → restano scartati.
Ogni strategia è robusta su tutta la sua griglia parametri (entrambi gli asset
→ tutte positive OOS) e su tutte le fee 0.00-0.20% RT (margine ampio).
MR01 validato col worker reale: BTC +196% / ETH +251% OOS (nov 2023→mag 2026).
Ricerca completa: scripts/analysis/strategy_research.py (MR01) e
scripts/analysis/strategy_research_v2.py (MR02/MR03/MR07).
Validazione live-path: scripts/analysis/oos_validation.py.
Filtro trend (riduzione DD + aumento Acc). Tutte le fade accettano i parametri
opzionali trend_max / ema_long: saltano i segnali quando il prezzo è troppo
esteso rispetto al trend di fondo (|close − EMA(ema_long)| / ATR(14) > trend_max),
cioè quando si starebbe fadando un trend/crollo estremo. Con trend_max=3.0,
ema_long=200 (default in strategies.yml): accuratezza su tutti gli sleeve
e DD giù drasticamente su ETH (MR01 71%→26%, MR02 42%→25%, MR03 66%→34%,
MR07 46%→21%), edge OOS confermato (vedi scripts/analysis/risk_management.py).
Unica eccezione: MR03 BTC, dove il filtro peggiora entrambe → lasciato disattivo.
Leva non robusta scartate: vol-target sizing e skip-alta-volatilità (peggiorano).
Portafoglio. Diversificare su sotto-conti indipendenti equipesati (le 4 strategie × BTC/ETH, pos 0.15 ciascuno) abbatte il DD aggregato: ~14% full / ~10% OOS sul paniere di 8 sleeve, contro il 20-70% del singolo. È la vera leva anti-drawdown.
Combinare le due famiglie (fade + honest). Le fade (reversione intraday 1h) e le
honest (DIP/TR/ROT trend+rotazione multi-crypto) sono quasi scorrelate
(correlazione cross-famiglia ~0.05). Combinarle in un unico portafoglio migliora il
rischio/rendimento rispetto a ciascuna famiglia da sola: equal-weight dei 9 sleeve
→ DD 5.2% full / 4.7% OOS e Sharpe 4.23 full / 4.33 OOS (vs honest-only 12.6% DD /
2.20 Sharpe e fade-only 8.2% DD / 4.09 Sharpe), CAGR ~47% mantenuta. Studio in
scripts/analysis/combine_portfolio.py.
ROT02 — riduzione DD (top_k 2→3). La rotazione dual-momentum honest concentrava
il book su 2 soli asset (DD 40%). Diversificare su 3 (top_k=3) dimezza quasi il DD
(40%→26%) e alza pure il ritorno full (+1095%→+1303%, ret/DD da 27 a 50); il
vol-target abbassa il DD ma sacrifica ritorno, quindi si tiene top_k=3 senza VT.
Applicato a ROT02_dual_momentum.py e a _rot_daily_equity (usata dai portafogli).
Portafogli pronti (artefatti accorpati e migliorati). Oltre a PORT01 (solo
honest), due script in scripts/strategies/:
PORT02_fade_master.py— le 3 fade × BTC/ETH accorpate (6 sleeve, filtro trend), equal-weight daily: DD ~8.2% full / 5.9% OOS, Sharpe 3.95/4.09, CAGR ~46%.PORT03_all_master.py— portafoglio MASTER (fade + honest, 9 sleeve). Due varianti:equal(massimo Sharpe: DD 5.2%/4.7% OOS, Sharpe 4.23/4.33) e5050fra le due famiglie (minimo DD: 5.0% full / 4.5% OOS). È la configurazione consigliata. ComePORT01, sono meta-portafogli (scriptrun()di report), nonStrategycongenerate_signals, quindi non nelstrategy_loader.
Esplorazione famiglie alternative (branch strategy_explore, 2026-05-29). Esplorate
9 famiglie nuove con agenti paralleli su harness onesto condiviso
(scripts/analysis/explore_lab.py). 7 sono rumore (rifiutate: stagionalità oraria/mensile,
cross-sectional reversal, opening-range breakout, lead-lag BTC→alt, continuation intraday —
quest'ultima riconferma la dominanza mean-reversion). Due edge reali:
- PR01 Pairs (
scripts/strategies/PR01_pairs_reversion.py): spread reversion market-neutral sul log-ratio z-score di coppie cripto (ETH/BTC, LTC/ETH, ADA/ETH). ETH/BTC: CAGR 144%, Sharpe 4.04, OOS DD 17%, 8/9 anni; corr col mercato ~0.02. Fee su 2 gambe (worker da estendere prima del live). Verifica:pairs_research.py. - TSM01 (
scripts/analysis/tsmom_research.py): TSMOM multi-orizzonte 3/6/12m + risk-off, marginale ma distinto (corr 0.53 con ROT02), DD 22%/12% OOS, mai un anno negativo.
Aggiungere i pairs al MASTER (quasi scorrelati, ~0.05) è il free-lunch più grande:
MASTER+pairs (12 sleeve) → CAGR 47→66%, DD 5.2→3.8% full / 4.7→3.3% OOS, Sharpe OOS
4.33→6.86 (scripts/analysis/combine_v2.py). Caveat: backtest leva 3x, OOS ~1.6 anni.
Metodologia obbligatoria per ogni nuova strategia (per non ripetere l'errore squeeze):
- Ingresso eseguibile: direzione e prezzo decisi con dati fino a
close[i], maiclose[i-1]con direzione dai. - Backtest NETTO dopo fee realistiche Deribit (0.10% RT taker, non 0.20%) + leva.
- Validazione out-of-sample (held-out) + robustezza su griglia parametri + sweep fee.
- Crea script in
scripts/strategies/, aggiungi aMODULE_MAP(strategy_loader.py) e astrategies.yml.
Strategie scartate storiche in scripts/waste/ (W01-W28 + la famiglia squeeze).
Verso €50/giorno. Con 4 strategie indipendenti (MR01/MR02/MR03/MR07) × 2 asset (BTC/ETH) su €1000 ciascuna, il PnL medio storico aggregato è ben oltre €50/giorno; ma quei numeri sono backtest a leva 3x su 8 anni e includono anni eccezionali (es. ETH 2024). Stima onesta: il target è plausibile su un portafoglio diversificato di queste fade, ma va confermato col paper trader live prima di rischiare capitale reale.
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]includeclose[i]che è un candle nel futuro — usarereturns[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 chereturns[k]usaclose[k+1]. I feature devono fermarsi areturns[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_datecome data nuda è inclusivo dell'intera giornata fino all'ultima candela chiusa (es.end=oggiarriva 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.