14522262e6
Reset del progetto su fondamenta verificate dopo la scoperta che l'intera libreria "validata OOS" era artefatto di feed contaminato (print fantasma del feed Cerbero TESTNET + storico Binance/USDT). - Storico ricostruito da Deribit MAINNET (ccxt pubblico, tokenless) e CERTIFICATO (certify_feed.py): BTC/ETH puliti su TUTTA la storia (mediana 2-6 bps vs Coinbase USD), integrita' OHLC + coerenza resample (maxΔ 0.00) + cross-venue OK. Alt esclusi (illiquidi/divergenti: LTC/DOGE 50-82% barre flat; XRP/BNB non certificabili). - Verdetto sul feed pulito: FADE / PAIRS / XS01 / TSM01 morti (ogni portafoglio Sharpe -2.3..-3.0, DD ~40%); solo SH01 e frammenti HONEST con segnale residuo, da ri-validare in isolamento. - Cleanup "restart pulito": strategie, stack live (src/live, src/portfolio, runner/executor, yml, docker), ~100 script ricerca/gate, waste/games/ portfolios, dati non certificati + cache e 60+ diari -> archiviati in Old/ (preservati, non cancellati). Diario consolidato in un unico documento. - Skeleton ricerca tenuto: Strategy ABC + indicatori + src/fractal + src/backtest/engine + load_data; tool dati certificati (rebuild_history, certify_feed, audit_feed, multi_source_check). - Universo dati ATTIVO: solo BTC/ETH (5m/15m/1h); guardrail fisico (load_data su alt -> FileNotFoundError). Esecuzione DISABILITATA, conto flat. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
54 lines
3.2 KiB
Markdown
54 lines
3.2 KiB
Markdown
# 2026-06-08 — Executor a 2 gambe per i pairs (PairsExecutionClient)
|
||
|
||
Implementato il pezzo di esecuzione reale più impegnativo rimasto: l'esecuzione
|
||
shadow a 2 gambe per la famiglia PAIRS (29% del portafoglio, finora solo simulata).
|
||
|
||
## Cosa
|
||
|
||
- **`execution.PairsExecutionClient`**: compone l'`ExecutionClient` single-leg.
|
||
- `open_pair(inst_a, inst_b, direction, notional)`: piazza le 2 gambe (long A/short B
|
||
o viceversa) a market, verifica per-gamba sul trade; **LEG-RISK**: se UNA sola gamba
|
||
filla → UNWIND (richiude la fillata reduce-only) per non restare direzionali →
|
||
verified=False.
|
||
- `close_pair(...)`: chiude entrambe reduce-only (solo `close_amount` della quota,
|
||
MAI `close_position`), riconcilia fee/prezzi.
|
||
- `register_contract`: fetch dinamico spec USDC da Deribit per strumenti non hardcodati.
|
||
- Strumenti = lineari USDC (payoff lineare = matematica del backtest a 2 gambe).
|
||
Aggiunti spec LTC/ADA/SOL_USDC (step 0.1/0.2/0.1).
|
||
- **`PairsWorker` shadow**: ledger reale parallelo (`real_capital`, `real_dir`,
|
||
`real_amount_a/b`, `real_entry_a/b`, `real_notional_a/b`, fee), persistito e resume-safe;
|
||
`_real_open_pair`/`_real_close_pair` agganciati a `_open`/`_close`; PnL reale per gamba
|
||
(dir A=+d, dir B=−d). Doppio arrotondamento → piccolo sbilanciamento notional, riportato.
|
||
- **runner**: `pairs_executor` (PairsExecutionClient su stesso ExecutionClient dei fade),
|
||
`_pairs_exec_for`, gate su `execution.pairs_enabled`. Config `portfolios.yml`:
|
||
instruments estesi (LTC/ADA/SOL) + `pairs_enabled: false` (capability pronta, SPENTA).
|
||
|
||
## Validazione
|
||
|
||
- Test (executor finto): 92/92 — open/close a 2 gambe, **leg-risk unwind**, ledger reale
|
||
persiste e resume.
|
||
- **Smoke testnet end-to-end** (`live_pairs_smoke.py`, €0): open 2 gambe verificate
|
||
(long ETH 0.011 @1666 / short BTC 0.0003 @63263, fee $0.019), close 2 gambe reduce-only,
|
||
riconciliazione PnL reale −0.039 vs sim −0.036 (coerente), **conto flat dopo**.
|
||
|
||
## Incidente operativo (testnet, €0) — da ricordare
|
||
|
||
Durante la prima esecuzione, lo smoke è crashato (bug del test: prezzi sim=0 → divisione
|
||
per zero nel ramo sim) lasciando una posizione aperta. Per pulirla ho usato a mano
|
||
`ExecutionClient.close()` (= `close_position`) che **flatta l'intero strumento** → ho
|
||
chiuso anche le 3 posizioni reali SHADOW dei fade del runner (BTC/ETH_USDC condivisi).
|
||
Impatto: testnet, shadow (non guida le decisioni), €0; 3 worker fade con
|
||
`real_in_position=True` su conto flat → si auto-riconciliano al prossimo close sim
|
||
(close_amount su flat → verified=False, reset; "shadow pulito dalla prossima apertura").
|
||
I TP resting erano già stati cancellati da close_position (cancel → order_not_found).
|
||
|
||
**Lezione (CLAUDE.md la documentava già)**: MAI `close_position` su strumenti condivisi.
|
||
Fix permanente: lo smoke ora (a) usa solo `close_amount` della quota, (b) ABORTA se ci
|
||
sono posizioni di produzione aperte sugli strumenti, (c) usa prezzi sim reali.
|
||
|
||
## Stato: PRONTO ma SPENTO (`pairs_enabled: false`)
|
||
|
||
L'executor è validato (test + smoke). NON attivato in produzione: accenderlo richiede
|
||
una finestra a conto flat e un periodo di osservazione, dato il conto condiviso coi fade.
|
||
Quando si accende: i 5 pairs eseguiranno reale a 2 gambe accanto al sim.
|