Files
PythagorasGoal/Old/docs/diary/2026-06-08-pairs-executor.md
Adriano Dal Pastro 14522262e6 chore(reset): v2.0.0 — storico certificato Deribit mainnet, ripartenza pulita
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>
2026-06-19 15:20:59 +00:00

3.2 KiB
Raw Permalink Blame History

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.