From 95424f0755a795dedba686a87d90d26ad84fbea6 Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Wed, 2 Sep 2026 15:53:42 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20il=20README=20era=20fermo=20a=2015=20gi?= =?UTF-8?q?orni=20PRIMA=20del=20reset=20=E2=80=94=20riscritto=20contro=20l?= =?UTF-8?q?o=20stato=20vero?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ultimo commit del README: 2026-06-04. Reset v2.0.0: 2026-06-19. Per 75 giorni la prima pagina del repo ha pubblicato la libreria pre-reset (FADE/HONEST/PAIRS/TSMOM/SHAPE, PORT01-06) con Sharpe 7,84/10,06 e CAGR ~79% come risultati correnti — cioe' esattamente i numeri che §2 elenca sotto "non citare", dalla libreria che il reset aveva dichiarato artefatto. Meta' dei file citati non esiste piu' (strategies.yml, portfolios.yml, scripts/waste, scripts/portfolios, src/live/multi_runner.py), e l'esecuzione descritta era su TESTNET, che e' la causa del reset. - README riscritto (423 -> 152 righe): cosa gira adesso (TP01+SKH01 75/25, ~$2.050, cadenza oraria :47), i numeri nella lente di §2 (TWR +10,6%, non la crescita del conto), la riga che ordina il piano, il metodo e i suoi sei requisiti, il dato, la struttura VERIFICATA file per file, i comandi, i gate con le loro date, l'obiettivo con la sua onesta'. - CLAUDE.md §0 e memoria 40: registrato il difetto e la lezione — un reset invalida anche i documenti che nessuno rilegge; l'inventario di cosa cita numeri morti va fatto il giorno del reset, non 75 giorni dopo per caso. - Diario 02/09c: sezione col confronto riga per riga; coda dichiarata (l'inventario completo degli altri documenti pre-reset non e' stato fatto). Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01XDJsH3iDSaBns3ccpPBwiu --- CLAUDE.md | 6 + README.md | 504 ++++++----------------- docs/diary/2026-09-02c-flag-e-pulizia.md | 28 +- docs/memory/40-produzione-e-deploy.md | 17 + 4 files changed, 167 insertions(+), 388 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index bd32ec3..000a842 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -32,6 +32,12 @@ Documento di fondazione: `docs/diary/2026-06-19-deribit-history.md`. - Lo storico e' **ricostruito da Deribit mainnet e certificato**. Universo affidabile = **solo BTC/ETH** (tutti i TF); gli alt sono esclusi (illiquidi/divergenti/non certificabili). - Tutto il codice pre-reset e' archiviato in `Old/` (preservato in git, non cancellato). +- 🚨 **Il README e' rimasto fermo al 2026-06-04 fino al 2026-09-02**, cioe' *quindici giorni prima* + del reset: per 75 giorni la prima pagina del repo ha pubblicato la libreria pre-reset e i suoi + numeri (PORT06 Sharpe 7,84/10,06, CAGR ~79%) come risultati correnti, mentre il progetto li aveva + gia' dichiarati artefatti. Riscritto contro lo stato vero. **La lezione non e' "aggiornare il + README": e' che un reset invalida anche i documenti che nessuno rilegge** — l'inventario di cosa + cita numeri morti va fatto il giorno del reset, non quando qualcuno ci inciampa. - **L'esecuzione e' ARMATA e LIVE** su Deribit mainnet dal 2026-06-20. Capitale reale **~$635** (NON i €2.000 nominali del paper trader). - Si riparte dalla ricerca di strategie NUOVE, su dati certi, con la metodologia della §8. diff --git a/README.md b/README.md index 041392f..c3be9ea 100644 --- a/README.md +++ b/README.md @@ -1,423 +1,153 @@ # PythagorasGoal -Sistema di riconoscimento pattern frattali e predizione per il trading di criptovalute (BTC, ETH), ispirato al framework teorico di Serleto & Malanga (*Pythagoras Trading Prediction*). +Ricerca e esecuzione di strategie algoritmiche su BTC/ETH, con **un libro che gira con soldi veri** +su Deribit mainnet dal 20 giugno 2026. -## Obiettivo +> 🚨 **v2.0.0 — RESET del 2026-06-19. Tutto ciò che questo README diceva prima è archiviato in +> `Old/` e non è fidato.** L'intera libreria di strategie "validata out-of-sample" (le famiglie +> FADE/HONEST/PAIRS/TSMOM/SHAPE, i portafogli PORT01-06, gli Sharpe fra 6 e 10) era un **artefatto +> di uno storico contaminato**: print fantasma di un feed *testnet* più storico Binance/USDT. +> Ri-testate sul feed reale ricostruito da Deribit mainnet, **perdono ogni anno**. Documento di +> fondazione: `docs/diary/2026-06-19-deribit-history.md`. +> +> Questo README descrive il progetto **dopo** il reset. È stato riscritto il 2026-09-02, dopo +> essere rimasto fermo al 4 giugno — quindici giorni prima del reset — mentre pubblicava i numeri +> che il progetto aveva già dichiarato falsi. -Partendo da un capitale iniziale di €1.000, raggiungere un profitto medio di €50 al giorno entro 6–8 mesi, tramite un portafoglio di strategie algoritmiche poco correlate fra loro — mean-reversion, trend/rotazione e spread market-neutral — validate out-of-sample e fee-aware. +**L'autorità sui numeri e sulle decisioni è `CLAUDE.md`**, e il racconto completo sta in +`docs/memory/`. Questo file è l'ingresso, non la fonte. -## Risultati +--- -> ⚠️ **Revisione 2026-05-28.** La famiglia squeeze-breakout (SQ/MT/ML/AD/CM/PD, con -> accuracy storiche dichiarate 76-82%) è stata **scartata**: quei numeri erano un -> **artefatto di look-ahead**. I backtest decidevano la direzione dalla candela di -> breakout `close[i]` ma entravano a `close[i-1]` — impossibile dal vivo. Sotto -> ingresso onesto (`close[i]`) e fee reali, l'edge sparisce e tutte perdono, anche -> a fee zero. Dettagli e prove: `scripts/analysis/oos_validation.py`. +## Cos'è vivo, adesso -Dopo una validazione **out-of-sample, fee-aware** di molte famiglie di strategie, -emergono cinque famiglie con edge netto reale, tutte radicate nella stessa lezione -(in cripto la **mean-reversion** funziona, la continuazione no) o nella diversificazione: +| | | +|---|---| +| libro live | **TP01 + SKH01 a 75/25**, nettati in software su una sola posizione per asset (50/50 BTC/ETH) | +| venue | Deribit mainnet, perpetual lineari USDC. Esecuzione **armata** dal 2026-06-20 | +| capitale | ~$2.050 (USDC + USDE), non i €2.000 nominali di nessun paper trader | +| cadenza | **oraria**, minuto `:47` (`scripts/cron_book.sh`) | +| leva | lorda ~0,28x su un tetto di 1,00x. Il cap non ha mai morso: **il vincolo è il segnale** | +| protezione on-book | un solo disaster-SL rotolante al −30% sulla posizione netta | -| Famiglia | Meccanismo | Strategie | Profilo (netto OOS) | -|----------|-----------|-----------|---------------------| -| **FADE** | mean-reversion intraday 1h (long/short, BTC/ETH) | MR01 Bollinger, MR02 Donchian, MR07 Return-reversal | Acc 52-55%, DD 18-34% | -| **HONEST** | long-only multi-regime multi-crypto | DIP01 dip-buy, TR01 EMA-trend, ROT02 dual-momentum | CAGR 31-56%, DD 15-27% | -| **PAIRS** | spread reversion *market-neutral* (2 gambe) | PR01 ETH/BTC, LTC/ETH, ADA/ETH, BTC/LTC, ETH/SOL | Sharpe 2.0-4.4, corr col mercato ~0.05 | -| **TSMOM** | time-series momentum multi-orizzonte | TSM01 (3/6/12m + risk-off) | diversificatore, DD 15-22% | -| **SHAPE** | ML walk-forward su feature di *forma* del prezzo | SH01 (LogisticRegression, orizzonte 12 barre) | diversificatore, corr +0.08 col resto | +**Non** sono nel libro live: XS01, VRP01, GTAA01, XSR01. Vivono nel portafoglio di **ricerca** +(paper, 5 sleeve), che è una serie diversa da quella che gira — quasi tutti i numeri di portafoglio +del progetto sono su quella, non su questa. -Tutti i numeri sono **netti** dopo fee realistiche (Deribit 0.10% RT single-leg, 0.20% -RT/coppia sui pairs), leva 3x, su finestra held-out. Le strategie sono robuste su griglia -parametri, sweep fee 0.00-0.20% RT e — per i pairs — validate con **walk-forward** e -config universale (niente cherry-picking). +## I numeri, con la loro lente -### Portafoglio combinato (la vera leva anti-drawdown) +Ogni numero va scritto con la lente e la banda che gli appartengono. La tabella completa +("non citare" ↔ "citare") è in `CLAUDE.md` §2; qui i tre che contano. -Le famiglie sono **quasi scorrelate fra loro** (~0.05). Combinandole in un unico -portafoglio equipesato il drawdown crolla sotto quello di ogni singola sleeve: +| grandezza | valore onesto | +|---|---| +| rendimento del libro live | **TWR +10,6%** dall'armamento, spezzato sul versamento del 25/08: +11,61% prima, −0,9% dopo | +| crescita di trading | **+$50** in 71 giorni, su 30 round-trip chiusi e $0,87 di fee totali | +| Sharpe del portafoglio di ricerca | **1,95** [1,81 – 2,12] full, **1,54** [1,11 – 1,91] hold-out | -| Portafoglio | CAGR | Max DD | Sharpe | -|-------------|------|--------|--------| -| FADE (6 sleeve) | ~46% | 8% | 3.9 | -| HONEST (3 sleeve) | ~46% | 13% | 2.2 | -| **MASTER** (FADE + HONEST, 9) | ~47% | **5%** | 4.2 | -| **MASTER + PAIRS + TSM01** (15) | ~67% | ~5% | ~6 | -| **PORT06 live** (17 sleeve, cap pairs 33%, leva 2×, config EXIT-16) | ~79% | **2.6%** | 7.8 (FULL) / 10.1 (OOS) | +⚠️ Il rendimento dell'equity **non** è la performance: il 96% della crescita del conto è un +bonifico. Chi legge una percentuale su questo progetto deve sapere se è un TWR o un rapporto fra +due saldi — è stato un difetto reale, riparato il 2026-09-02. -> 🔎 **Numeri sobri (anti-overfit).** L'OOS singolo cade nel regime favorevole 2024-25: -> i valori di Sharpe/DD sopra sono ottimistici di circa il 50%. Da pianificare per le -> decisioni: **Sharpe atteso ~5**, **worst-drawdown su 90 giorni ~6%**, profilo che regge -> a leva 2x con slippage raddoppiato. Configurazione raccomandata: equal-weight, leva 2x, -> con un cap sull'allocazione ai pairs (~30-35%, poiché concentrano ~57% del rischio). -> Tutto resta da confermare nel paper trading live. +## La riga che ordina tutto il resto -## Come funziona +> La ricerca ha smesso di essere il vincolo il 2026-07-26, e **sei ondate successive lo hanno +> confermato invece che ribaltarlo**. I vincoli sono **il capitale che entra** e **il conto che non +> sparisce**. -### MR01 — Bollinger Fade (mean-reversion) +Misurato: il miglior candidato nuovo vale **+0,046 €/giorno**; versare €500/mese invece di €250 +porta la probabilità di arrivare al traguardo in 20 anni **dal 14% all'85%**. E €100/mese in più +equivalgono a **+4,07%/anno di drift**, cioè più di tutta la leva autorizzabile. -La strategia attiva sfrutta il fatto, emerso dai dati, che su BTC/ETH a 1h gli estremi -di prezzo **rientrano verso la media** più di quanto proseguano: +## Metodo — cosa deve superare una strategia nuova -1. **Bollinger Bands** (window `n`, `k` deviazioni standard) sul close. -2. **Entry** — quando il close esce *sotto* la banda inferiore → **long** (o *sopra* la superiore → **short**). Ingresso a `close[i]`, eseguibile dal vivo. -3. **Take-profit** alla media mobile (il rientro atteso). -4. **Stop-loss** a `sl_atr × ATR` oltre l'estremo; **time-limit** a `max_bars`. +Sei requisiti, nessuno negoziabile (`CLAUDE.md` §8, gate in `scripts/research/alt/altlib.py`): -Nessun look-ahead: direzione e livelli sono calcolati con dati fino a `close[i]`. +1. **ingresso eseguibile** — direzione e prezzo da dati fino a `close[i]`, mai l'estremo di una candela; +2. **backtest netto** dopo fee Deribit realistiche, più la leva; +3. **out-of-sample** held-out, robustezza su griglia, sweep fee; +4. **liquidità e plausibilità** — un edge su un book fermo o su wick fantasma non è un edge; +5. i **gate**: `marginal_vs_tp01` (Sharpe marginale, non assoluto), `study_family_honest` con + deflated-Sharpe ≥ 0,95, `day_boundary_robust`, `anchor_luck_band`, `weights_tilt_null`; +6. codice, test e diario. -### Le altre famiglie +Il progetto ha **73 regole di prim'ordine** (`CLAUDE.md` §6) — sul dato, sul metodo, sui costi, +sulla produzione e sul piano — ognuna pagata almeno una volta. La più +ricorrente, cinque occorrenze: *un sorvegliante deve derivare il proprio bersaglio dal codice +sorvegliato, mai ridichiararlo — un controllo puntato su una configurazione diversa da quella che +gira passa sempre, e non sta controllando niente.* -- **FADE** (oltre MR01): MR02 fada la rottura del canale Donchian verso il centro; - MR07 fada il movimento di barra estremo misurato in deviazioni standard dei - rendimenti. Stessa logica di reversione, indicatori indipendenti. -- **HONEST** (long-only, multi-crypto): DIP01 compra i dip estremi e rivende al - recupero; TR01 segue il trend con incrocio di EMA su un paniere; ROT02 ruota ogni - giorno sui tre asset col momentum più forte, andando in cash quando BTC è sotto la - sua media (risk-off). Coprono i regimi di trend e rotazione, complementari alle fade. -- **PAIRS** (market-neutral): scommette sul rientro verso la media del log-ratio fra - due cripto (z-score). Long su una, short sull'altra: l'esposizione netta al mercato è - quasi nulla (correlazione ~0.02), il che la rende un diversificatore eccellente. -- **TSMOM**: tiene gli asset con momentum positivo persistente su più orizzonti - (3/6/12 mesi), con overlay risk-off. Rende meno ma è poco correlato, utile in ensemble. +## Il dato -### Perché lo squeeze breakout è stato abbandonato +- **La verità è Deribit mainnet**, perché è dove si esegue. Binance è un audit indipendente, mai + un'ancora per "ripulire": è USDT, ~10 bps fuori, fino al 3% sotto depeg. +- Universo certificato: **solo BTC/ETH**, ogni timeframe. Gli alt sono esclusi. +- Lo storico si aggiorna **solo** con `rebuild_history.py` e si certifica **sempre** con + `certify_feed.py`. Il vecchio downloader è la causa del reset. +- La catena opzioni si **raccoglie** ogni ora (`collect_chain.py`, minuto `:25`): un'ora non + raccolta è persa per sempre. -L'ipotesi originale era opposta — *continuazione* dopo la compressione di volatilità -(Bollinger dentro Keltner → breakout direzionale). Su dati storici sembrava dare -76-82% di accuracy, ma era un **artefatto di look-ahead**: il backtest entrava a -`close[i-1]` con direzione decisa da `close[i]`. Replicando l'esecuzione reale -(ingresso a `close[i]`) l'edge collassa al ~47% (lancio di moneta) e i costi fanno -il resto. Il test sui breakout intra-barra a 5m conferma che il movimento *rientra* -subito (mean-reversion), giustificando MR01. Tutta la famiglia squeeze è in `scripts/waste/`. - -### Lezione metodologica - -Ogni nuova strategia deve passare: (1) **ingresso eseguibile** senza look-ahead, -(2) backtest **netto** dopo fee realistiche (0.10% RT Deribit), (3) validazione -**out-of-sample** + robustezza su griglia parametri + sweep fee. Strumenti in -`scripts/analysis/` (`strategy_research.py`, `oos_validation.py`, `intrabar_test.py`). - -## Struttura progetto +## Struttura ``` -PythagorasGoal/ -├── src/ -│ ├── data/ # Download e gestione dati (Cerbero MCP + Binance) -│ ├── fractal/ # Indicatori frattali: Hurst, Higuchi FD, self-similarity -│ ├── backtest/ # Motore di backtesting con fee e metriche -│ ├── strategies/ # Classe base Strategy ABC + indicatori condivisi -│ │ ├── base.py # Strategy, Signal, BacktestResult, YearlyStats -│ │ └── indicators.py # keltner_ratio, detect_squeezes, ema, atr, rv, corr -│ ├── live/ # Paper trading live su Deribit testnet -│ │ ├── multi_runner.py # Orchestratore multi-strategia (strategie + pairs) -│ │ ├── strategy_worker.py # Worker single-leg con stato persistente -│ │ ├── pairs_worker.py # Worker a 2 gambe per i pairs (market-neutral) -│ │ ├── strategy_loader.py # Import dinamico classi Strategy -│ │ ├── cerbero_client.py # Client HTTP per Cerbero MCP -│ │ ├── signal_engine.py # Squeeze + ML real-time (legacy) + validazione OOS -│ │ └── telegram_notifier.py -│ └── portfolio/ # Portafogli di prima classe (capitale condiviso, backtest + live) -│ ├── base.py # SleeveSpec, Portfolio (.backtest), load_active_portfolio -│ ├── weighting.py # Schemi di ponderazione: equal, cap, inverse_vol, cluster_rp, manual -│ ├── sleeves.py # Builder unificato equity-per-sleeve (fonte unica, parità report) -│ ├── ledger.py # PortfolioLedger: PnL/DD aggregati, persistenza e resume -│ └── runner.py # PortfolioRunner live (Cerbero v2, sizing, ribilancio giornaliero) -├── scripts/ -│ ├── strategies/ # Strategie con edge validato OOS (FADE, HONEST, PAIRS, TSMOM + portafogli) -│ ├── portfolios/ # Definizioni PORT01-06 e report run() dei portafogli di prima classe -│ ├── waste/ # Strategie scartate (squeeze SQ/MT/ML/AD/CM/PD, MR03, ROT01, W01-W28) -│ └── analysis/ # Ricerca/validazione OOS fee-aware, gestione rischio, report -├── strategies.yml # Config multi-strategy paper trader -├── data/ -│ ├── raw/ # Parquet OHLCV (gitignored, ~70 MB) -│ └── regime/ # DVOL + funding (Deribit mainnet) + cache feature regime (gitignored) -├── VERSION # versione semver (cotta nell'immagine, mostrata nei msg Telegram) -├── docs/ -│ ├── diary/ # Diario di ricerca giornaliero -│ └── specs/ # Specifiche di design -├── Dockerfile -├── docker-compose.yml -└── pyproject.toml +src/ + data/downloader.py load_data(asset, tf) sui parquet certificati + strategies/ trend_portfolio.py (TP01) · skyhook.py (SKH01) · base · indicators + portfolio/ portfolio.py (N sleeve + weights_tilt_null) · sleeves.py · gtaa.py + backtest/harness.py backtest onesto, senza look-ahead + live/ book.py (esecutore netto) · deribit · livefeed · usde + venue_watch · venue_probe · venue_news · monitor_health · scale_watch + tradesdb · journal · analista · notifier · cli +scripts/ + live/ book_execute · trades_db · journal · analista · balance_watch + paper_* (forward-monitor) · usde_watch · usde_convert · fee_watch + research/ r_*.py — un file per esperimento, harness in alt/altlib.py + analysis/ rebuild_history · certify_feed · audit_feed · multi_source_check + cron_{book,daily,chain,balance,usde,opt_snapshot,vol_term}.sh +docs/ + memory/ LA MEMORIA — 6 file, indicizzati in testa a CLAUDE.md + research/ RESULTS-0822 (§1-73, un registro per filone) · BRIEF-0822 · SPEC-scale-key + diary/ una voce per esperimento (144) + journal/ libro di bordo, una voce al giorno, 4 livelli per provenienza +tests/ 910, tutti verdi +Old/ archivio pre-reset — consultabile, non fidato ``` -## Strategie attive - -Le strategie single-asset estendono `src.strategies.base.Strategy` -(`generate_signals() → backtest()`); i pairs hanno un worker dedicato a 2 gambe. - -| Codice | Script | Famiglia | Descrizione | -|--------|--------|----------|-------------| -| **MR01** | `MR01_bollinger_fade.py` | FADE | Fada la banda di Bollinger, TP alla media, SL ad ATR | -| **MR02** | `MR02_donchian_fade.py` | FADE | Fada la rottura del canale Donchian, TP al centro | -| **MR07** | `MR07_return_reversal.py` | FADE | Fada il movimento di barra estremo (z dei rendimenti) | -| **DIP01** | `DIP01_dip_reversion.py` | HONEST | Dip-buy long-only su z-score estremo | -| **TR01** | `TR01_ema_trend.py` | HONEST | EMA 20/100 trend-following su paniere cripto (4h) | -| **ROT02** | `ROT02_dual_momentum.py` | HONEST | Rotazione cross-sectional top-3 + risk-off (1d) | -| **PR01** | `PR01_pairs_reversion.py` | PAIRS | Spread reversion market-neutral su 5 coppie | -| **TSM01** | `tsmom_research.py` | TSMOM | Time-series momentum multi-orizzonte + risk-off | -| **SH01** | `SH01_shape_ml.py` | SHAPE | LogisticRegression walk-forward su 17 feature di forma, orizzonte 12 barre (diversificatore) | - -Le fade applicano tre protezioni live: un **filtro trend** (`trend_max`/`ema_long`, -salta i segnali col prezzo troppo esteso rispetto alla EMA200), un **loss-guard Hurst** -(`hurst_max=0.55`, salta i segnali in regime persistente/trending dove si concentrano gli stop-loss -— dimezza il drawdown del portafoglio, calcolato dalle sole close) e l'**EXIT-16 close-confirm SL** -(`sl_confirm_atr=0.5`, 2026-06-04: lo stop scatta solo se la barra *chiude* oltre `sl ∓ 0.5·ATR14` — -gli stop intrabar da wick erano falsi negativi, l'overshoot che buca lo stop è proprio il movimento -che la fade fada; a livello PORT06 porta l'OOS Sharpe da 8.82 a 10.06). Più un filtro `min_tp_frac` -che scarta i micro-scalp col take-profit entro il costo delle fee. Le tre protezioni sono -complementari: Hurst toglie il regime tossico, il trend-filter gli ingressi sovra-estesi, il -close-confirm i falsi stop. Portafogli pronti: `PORT01` -(honest), `PORT02` (fade), `PORT03` (master fade+honest), **`PORT06`** (master esteso, default live). - -**Scartate** (in `scripts/waste/`): la famiglia squeeze (SQ01-04, ML01, MT01, PD01, -CM01, AD01 — artefatto di look-ahead), MR03 Keltner (debole/ridondante con MR01) e -ROT01 (dominata da ROT02). - -### Comandi utili +## Comandi ```bash -# Backtest di una strategia -uv run python scripts/strategies/MR01_bollinger_fade.py -uv run python scripts/strategies/PR01_pairs_reversion.py - -# Ricerca e validazione fee-aware out-of-sample -uv run python scripts/analysis/strategy_research.py # screening famiglie + deep-dive fade -uv run python scripts/analysis/strategy_research_v2.py # MR02 / MR03 / MR07 -uv run python scripts/analysis/oos_validation.py # perche' la famiglia squeeze e' scartata -uv run python scripts/analysis/pairs_research.py # ricerca + verifica no-look-ahead dei pairs - -# Gestione rischio, combinazione, report -uv run python scripts/analysis/risk_management.py # filtro trend + portafoglio fade -uv run python scripts/analysis/combine_portfolio.py # combinare fade + honest -uv run python scripts/analysis/combine_v2.py # master esteso con pairs + TSM01 -uv run python scripts/analysis/report_families.py # report per anno di tutte le famiglie - -# Validazione dei worker live (replay == backtest) -uv run python scripts/analysis/validate_worker_mr01.py # worker single-leg su MR01 -uv run python scripts/analysis/validate_worker_pairs.py # worker a 2 gambe sui pairs -uv run python scripts/analysis/live_smoke_pairs.py # smoke test feed live reale dei pairs +uv sync # dipendenze +uv run python scripts/analysis/rebuild_history.py --asset BTC ETH # storico da Deribit mainnet +uv run python scripts/analysis/certify_feed.py # certifica i feed +uv run python scripts/live/trades_db.py --report # stato del libro + TWR +uv run python scripts/live/journal.py # voce del giorno +uv run python scripts/live/analista.py --secco # analisi del giorno, senza salvare +uv run python scripts/portfolio/run_portfolio.py # portafoglio di ricerca +uv run pytest # 910 test ``` -## Paper Trading Live +Ogni script di `scripts/live/` accetta `--help` e **rifiuta un flag che non conosce** (esce 2): fino +al 2026-09-02 un flag sbagliato eseguiva l'azione di default, e su tre script quell'azione scriveva. -Il multi-strategy runner esegue N strategie in parallelo su dati live da Cerbero MCP, -ognuna con €1000 USDC virtuali indipendenti. Gestisce due tipi di worker: +## Gate aperti -- **Single-leg** (`strategy_worker.py`): per le strategie direzionali. Se un `Signal` - porta `tp`/`sl`/`max_bars` in `metadata` (come le fade), chiude su take-profit / - stop-loss / time-limit; altrimenti usa il fallback `hold_bars`/stop -2%. -- **Due gambe** (`pairs_worker.py`): per i pairs market-neutral. Apre long su una gamba - e short sull'altra, esce sul rientro dello z-score o per time-limit, conta le fee su - entrambe le gambe. Validato: il replay storico coincide *esattamente* col backtest. +Un gate si decide **alla data**, coi criteri scritti **prima**. Elenco completo in `CLAUDE.md` §4. -### Avvio +| gate | data | dove punta oggi | +|---|---|---| +| STATARB | 2026-09-27 | ritiro (Sharpe −1,61 sulla serie vera) | +| SCALA-01 — leva 1,00 → 1,25 | non prima del 2026-10-01 | chiave costruita e **inerte**; 9 condizioni, 2 fatte | +| XSR01 | 2026-10-23 | sotto la lente rendita il meccanismo vale ~0 | +| DVOLSPREAD | kill 2026-10-24 | serie −4,41 | +| GTAA01 tenere/bloccare | al book a $15k | contributo reale +0,10/+0,12 di Sharpe, non incassabile sotto la soglia | -```bash -# Locale -uv run python -m src.live.multi_runner +## Obiettivo, e cosa lo rende difficile -# Docker -docker compose up -d -``` +Il target dichiarato è **€50/giorno partendo da €1.000**. Non è raggiungibile a questo capitale: +servono ~$313k (banda [$187k – $1,14M]) o **€1.733/mese per dieci anni** per averlo al 90% di +probabilità. La leva non è la scorciatoia — quella difendibile vale quanto €100-150/mese di +versamento. La via è target-vol, capitale e tempo. -### Configurazione - -Le strategie attive sono definite in `strategies.yml`: - -```yaml -defaults: - capital: 1000 - position_size: 0.15 - leverage: 3 - -strategies: # strategie single-leg - - name: MR01_bollinger_fade - asset: BTC - tf: 1h - enabled: true - params: { bb_window: 50, k: 2.5, sl_atr: 2.0, max_bars: 24, trend_max: 3.0, ema_long: 200 } - -pairs: # strategie a 2 gambe (market-neutral) - - name: PR01_pairs_reversion - a: ETH - b: BTC - tf: 1h - enabled: true - params: { n: 50, z_in: 2.0, z_exit: 0.75, max_bars: 72, jump_max: 0.08 } -``` - -Per aggiungere una strategia: nuova riga in `strategies.yml` (sezione `strategies` o -`pairs`), poi `docker compose restart`. Lo storico delle strategie esistenti rimane intatto. - -### Persistenza - -Ogni strategia ha la sua directory in `data/paper_trades/`: - -``` -data/paper_trades/ - MR01_bollinger_fade__BTC__1h/ - trades.jsonl # Storico trade append-only - status.json # Stato corrente (resume al restart, include tp/sl/max_bars) -``` - -Notifiche Telegram per ogni trade (richiede `TELEGRAM_BOT_TOKEN` e `TELEGRAM_CHAT_ID` in `.env`). - -## Paper Trading a Portafoglio - -Accanto al multi-strategy runner originale — in cui ogni strategia gestisce autonomamente il proprio conto virtuale da €1.000 — il progetto dispone ora di un **paper trader a portafoglio** (`src/portfolio/`) che tratta l'insieme delle strategie come un unico organismo con un capitale condiviso. - -### Come funziona - -La definizione di un portafoglio (`SleeveSpec` + schema di peso) ha due facce sulla stessa sorgente dati: - -- **Backtest** (`.backtest()`): ricostruisce le equity-curve di ogni sleeve tramite il builder unificato in `sleeves.py`, le pondera secondo lo schema scelto e calcola le metriche aggregate (CAGR, Sharpe, max DD). La parità con i report prodotti da `report_families.py` è garantita dalla fonte unica. -- **Live** (`PortfolioRunner`): ogni ora il runner scarica le candele aggiornate via Cerbero v2, calcola i pesi correnti, avvia i worker appropriati per ogni sleeve attiva e registra il PnL aggregato nel ledger (`data/portfolios/{code}/`). Il ledger persiste tra i riavvii. - -### Schemi di ponderazione - -Il modulo `weighting.py` mette a disposizione cinque schemi: `equal` (default), `cap` (tetto per famiglia — p.es. `pairs: 0.33` per limitare la concentrazione), `inverse_vol` (pesi inversamente proporzionali alla volatilità storica), `cluster_rp` (equal tra cluster naturali poi inverse-vol all'interno del cluster) e `manual` (pesi liberi). Lo schema si specifica in `portfolios.yml` insieme al codice portafoglio e alla leva. - -### Portafoglio di default: PORT06 - -La configurazione raccomandata è **PORT06** (`scripts/portfolios/PORT06_master_shape.py`): portafoglio master esteso che include tutte e sei le famiglie (FADE, HONEST, PAIRS, TSMOM, SHAPE), con schema `cap` che limita i pairs al 33% del capitale per moderare la loro concentrazione di rischio. Backtest canonico (dati al 2026-05-28): Sharpe 6.47 (FULL) / 8.82 (OOS), drawdown massimo 4.10% (FULL) / 1.30% (OOS), leva 2×; **con la config live attuale (EXIT-16 close-confirm): Sharpe 7.84 / 10.06, DD 2.60% / 1.15%**. - -### Scope live - -Il runner esegue **tutti e 17 gli sleeve** di PORT06: **fade** (MR01, MR02, MR07 × BTC/ETH), -**honest** (DIP01, TR01-basket 4h, ROT02-rotation 1d), **pairs** (PR01, cinque coppie), -**TSMOM** (TSM01 1d) e **shape** (SH01 × BTC/ETH). Worker dedicati: `StrategyWorker` (single-leg, fade/ -dip/**shape**), `PairsWorker` (2 gambe), `BasketTrendWorker`, `RotationWorker`, `TsmomWorker`. Il runner -fetcha 1h da Cerbero v2 e resampla a 4h/1d; il pool di capitale, il ribilancio giornaliero e il ledger -sono validati == backtest. - -> **SH01 (2026-06-01):** gira come `StrategyWorker` normale (il walk-forward è interno a -> `generate_signals`). Il vecchio `MLWorkerWrapper` usava il `SignalEngine` **squeeze scartato** — -> rimosso. **Loss-guard Hurst (2026-06-02):** le fade saltano i segnali in regime persistente -> (rolling-Hurst ≥ 0.55), dove si concentrano gli stop-loss — dimezza il drawdown del portafoglio -> (FULL 4.1%→2.4%; stop-loss fade −67% in numero, perdite totali −68%). Calcolato dalle sole close, -> attivo live (`hurst_max` nei params). Il report orario su Telegram **monitora lo stop-rate fade -> prima/dopo l'attivazione** e dà il verdetto automatico quando il campione è sufficiente. - -### Esecuzione reale (shadow, Deribit testnet) - -Sette sleeve single-leg — le **6 fade** (MR01/MR02/MR07 × BTC/ETH) e **DIP01** (dal 2026-06-04) — -eseguono ordini **reali su Deribit testnet** accanto al fill simulato (*shadow*: il sim resta la -verità che guida le decisioni; il reale misura la fattibilità). Punti chiave: - -- **Strumenti lineari USDC** (`BTC_USDC`/`ETH_USDC-PERPETUAL`): payoff lineare = matematica del - backtest; fee e PnL in USDC. Quantizzazione `Decimal` di amount (step) e prezzi (tick). -- **Take-profit reale = limit reduce-only AL livello** (v1.0.7): piazzato all'apertura, copre la - sola quota del worker (gli strumenti sono condivisi fra worker e nettati per conto); alla - chiusura il worker cancella il resting, riconcilia i fill dal trade history per `order_id` e - chiude a market solo il residuo. Fix della divergenza misurata: il market-on-poll usciva - +235 bps oltre il livello TP. Fill da resting = fee maker (~0%). -- **Stop-loss close-confirm** (v1.1.0): uscita al close che sfonda il livello → market - reduce-only al poll (nessun ordine stop sul book, per scelta: i trigger Deribit generano un - nuovo order_id allo scatto, non verificabile, e i wick non devono stoppare). -- **Verifica sul trade** (order_id in `get_trade_history`), fee reali dai `trades[]`, ledger - reale parallelo persistito (`real_capital`), eventi `REAL_OPEN`/`REAL_TP_RESTING`/`REAL_CLOSE` - nel log + alert Telegram (`REAL_EXEC_LIVE`, `REAL_OPEN_FAIL`). -- Config in `portfolios.yml` → `overrides.execution {enabled, sleeves, instruments}`. - **Pairs/rotation/TSMOM/shape restano simulati**: i pairs richiedono un executor a 2 gambe - (leg-risk), i multi-asset un rebalance-to-target; roadmap nel diario. - -### Versione & deploy - -Ogni deploy ha una **versione** (file `VERSION`, semver) che compare nei messaggi Telegram (notifiche -trade + report orario), così correli ogni messaggio al codice che l'ha generato. Il sorgente è **cotto -nell'immagine** → per aggiornare il live serve un **rebuild**, non un semplice restart: - -```bash -./scripts/deploy.sh # bump patch (1.0.0 → 1.0.1) + commit + rebuild + ricrea container -./scripts/deploy.sh minor # 1.0.x → 1.1.0 -``` - -Il volume `data/` persiste tra i deploy → i worker fanno RESUME dello stato (capitale, posizioni aperte). - -### Avvio del paper trader a portafoglio - -```bash -# Backtest del portafoglio di default (PORT06) -uv run python scripts/portfolios/PORT06_master_shape.py - -# Paper trading live a portafoglio -uv run python -m src.portfolio.runner - -# Report orario su Telegram (stato + stop-rate fade prima/dopo loss-guard) — via cron -uv run python scripts/portfolios/hourly_report.py - -# Smoke test del data layer Cerbero v2 -uv run python scripts/analysis/smoke_portfolio.py -``` - -## Setup - -```bash -# Clona e installa -git clone && cd PythagorasGoal -uv sync - -# Scarica dati storici (~70 MB) -uv run python -m src.data.downloader - -# Backtest strategia attiva -uv run python scripts/strategies/MR01_bollinger_fade.py - -# Paper trading live -uv run python -m src.live.multi_runner -``` - -### Requisiti - -- Python ≥ 3.11 -- [uv](https://docs.astral.sh/uv/) come package manager -- Accesso a Cerbero MCP (`cerbero-mcp.tielogic.xyz`) per dati Deribit live -- Docker (opzionale, per deploy su VPS) - -## Dati - -| Asset | Timeframe | Copertura | -|-------|-----------|-----------| -| BTC, ETH | 5m / 15m / 1h | 2018-01 → oggi | -| SOL, LTC, ADA, XRP, BNB, DOGE | 15m / 1h | 2019-2022 → oggi (variabile per asset) | - -Fonte primaria: perpetual Deribit via Cerbero MCP. Fallback: Binance spot via ccxt. -Formato: Apache Parquet (in `data/raw/`, gitignored). - -> **Nota sul naming Deribit (per il feed live).** I major sono perpetui *inverse* -> (`BTC-PERPETUAL`, `ETH-PERPETUAL`); gli altcoin sono perpetui *lineari USDC* -> (`SOL_USDC-PERPETUAL`, `LTC_USDC-PERPETUAL`, …) con storia dal 2022. Attenzione: -> `LTC-PERPETUAL`/`ADA-PERPETUAL` non esistono e `SOL-PERPETUAL` restituisce dati -> errati — per gli altcoin usare sempre la forma `_USDC-PERPETUAL`. - -### Discovery & validazione strumenti - -`src/data/instruments.py` scopre e **valida** gli strumenti disponibili sugli -exchange implementati — **Deribit** e **Hyperliquid** (esclusi Alpaca/stocks e -**Bybit**, feed testnet inaffidabile). Ogni perpetuo viene testato sui dati -storici realmente raccoglibili: esistenza, congruenza OHLC, contratto non-morto, -liquidità e **congruenza prezzo cross-exchange** (mediana per base-coin, tolleranza -5%) — così feed farlocchi e contratti sbagliati (es. `SOL-PERPETUAL`=9.6) vengono -scartati. Il risultato è `data/instruments_registry.json` (strumenti validi + -timeframe + data d'inizio). - -**Solo gli strumenti validati possono essere scaricati**: il downloader ha un gate -(`_download_cerbero_range`) che rifiuta quelli non nel registry. Rigenera con: - -```bash -uv run python -m src.data.instruments -``` - -Simboli Deribit: BTC/ETH = `-PERPETUAL` (inverse); altcoin = -`_USDC-PERPETUAL` (lineari USDC). Registry attuale (testnet): Deribit 18/106 -validi (major liquidi, BTC dal 2018), Hyperliquid 66/74. - -## Riferimenti - -- Serleto, L. & Malanga, C. — *Pythagoras Trading Prediction* (2024) -- Serleto, L. & Malanga, C. — *Libro dei Frattali* (2024) - -## Licenza - -Uso privato. Non destinato alla distribuzione. +**Onestà prima di tutto**: nessun numero va creduto finché non è netto fee, out-of-sample, robusto +su griglia, e su dati certificati, liquidi ed eseguibili. Il resto di questo repo esiste per rendere +quella frase verificabile invece che dichiarata. diff --git a/docs/diary/2026-09-02c-flag-e-pulizia.md b/docs/diary/2026-09-02c-flag-e-pulizia.md index e76d5a6..2757776 100644 --- a/docs/diary/2026-09-02c-flag-e-pulizia.md +++ b/docs/diary/2026-09-02c-flag-e-pulizia.md @@ -70,8 +70,34 @@ asserzioni sul testo del report non sono più ancorate al padding; `movimenti_ca righe già lette, così il report non fa due SELECT sulla stessa tabella a un'ora del cron — due letture ai due lati di una scrittura descriverebbero due istanti diversi. -## 5. Cosa NON ho fatto +## 5. Il README era fermo a quindici giorni prima del reset + +Chiesto un aggiornamento della documentazione, ho aperto il README e ho trovato un documento del +**2026-06-04**. Il reset v2.0.0 è del **19 giugno**. Per 75 giorni la prima pagina del repository ha +descritto la libreria pre-reset come se fosse il presente: + +| cosa diceva | stato vero | +|---|---| +| famiglie FADE / HONEST / PAIRS / TSMOM / SHAPE, strategie MR01…SH01 | archiviate in `Old/`, artefatto di feed contaminato | +| PORT06: Sharpe **7,84 / 10,06**, DD 2,60%, CAGR ~79% | numeri che `CLAUDE.md` §2 elenca sotto «non citare» | +| paper trader su `strategies.yml`, portafogli in `portfolios.yml` | **file inesistenti** | +| `scripts/waste/`, `scripts/portfolios/`, `src/live/multi_runner.py` | **inesistenti** | +| esecuzione shadow su Deribit **testnet** | il testnet è *la causa del reset*; oggi si esegue su mainnet con soldi veri | + +Riscritto contro lo stato vero: cosa gira adesso, i numeri nella lente di §2 (TWR +10,6%, non la +crescita del conto), il metodo e i sei requisiti, la struttura verificata file per file, i gate con +le loro date, l'obiettivo con la sua onestà. Ogni percorso citato è stato controllato: esiste. +Da 423 righe a 152. + +**La lezione che ho registrato non è «aggiornare il README».** È che un reset invalida anche i +documenti che nessuno rilegge, e l'inventario di cosa cita numeri morti va fatto il giorno del +reset — non 75 giorni dopo, per caso, mentre si fa altro. + +## 6. Cosa NON ho fatto - I loader `importlib` dei test sulla **ricerca** (moduli in `scripts/research/`) restano come sono: sono a livello di modulo, con radici diverse, e toccarli non ripara niente. - Il bound USDE nel classificatore: manca la storia, non il codice. + +- Non ho cercato altri documenti fermi al pre-reset fuori da `README.md` e `docs/`: l'inventario + completo (ogni file che cita un numero morto) resta da fare, ed è la vera coda di questa scoperta. diff --git a/docs/memory/40-produzione-e-deploy.md b/docs/memory/40-produzione-e-deploy.md index 597fcd9..ef46b90 100644 --- a/docs/memory/40-produzione-e-deploy.md +++ b/docs/memory/40-produzione-e-deploy.md @@ -939,6 +939,23 @@ parser accetta solo espressioni regolari e rifiuta il resto. Vincolo del minuto un commento che dichiara una cadenza diversa da quella che gira si paga quando qualcuno lo "corregge" nel verso sbagliato.** +### Il README ha pubblicato per 75 giorni la libreria che il progetto aveva dichiarato falsa + +Ultimo commit del README: **2026-06-04**. Reset v2.0.0: **2026-06-19**. In mezzo, quindici giorni; dopo, +75 in cui la prima pagina del repository descriveva FADE/HONEST/PAIRS/TSMOM/SHAPE, i portafogli PORT01-06, +il paper trader su `strategies.yml` e l'esecuzione shadow su testnet — con Sharpe 7,84/10,06 e CAGR ~79% +presentati come risultati correnti. Metà dei file citati non esisteva più (`strategies.yml`, +`portfolios.yml`, `scripts/waste/`, `scripts/portfolios/`, `src/live/multi_runner.py`); i numeri erano +esattamente quelli che `CLAUDE.md` §2 elenca sotto «non citare», e provenivano dalla libreria che il +reset aveva dichiarato artefatto di un feed contaminato. + +Nessun danno sui soldi — il README non decide niente. Il danno è di **citazione**, ed è la forma peggiore: +un lettore esterno (o un agente nuovo) parte da lì. **La lezione non è "tenere aggiornato il README"**, +che nessuno fa più di quanto già non faccia: è che **un reset invalida anche i documenti che nessuno +rilegge**, e l'inventario di cosa cita numeri morti va fatto il giorno del reset, quando si sa che sono +morti — non 75 giorni dopo, quando qualcuno ci inciampa per caso. Riscritto il 2026-09-02 contro lo stato +vero, con ogni riferimento a file verificato e i numeri nella lente di §2. + ### Un flag sconosciuto non è l'azione di default (2026-09-02) Nessuno dei 18 script di `scripts/live/` usava argparse: leggevano `sys.argv` con `in` e `index`,