Files
PythagorasGoal/docs/diary/2026-06-04-shadow-divergence.md
T
2026-06-04 16:20:07 +00:00

40 lines
2.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-06-04 — Shadow execution: divergenza sim/reale misurata + TODO limit reduce-only
## Deploy v1.0.6
Fix float deployata (`74670da` + release): `_quantize_step` con `Decimal` in
`src/live/execution.py``72*0.001 = 0.07200000000000001` causava `Invalid params`
su Deribit (1 `REAL_OPEN_FAIL` su MR07 il 2026-06-03). Resume pulito al restart.
## Misura della divergenza sim vs reale (primi 7 close shadow)
**Bilancio: PnL sim +11.85 USD vs reale +0.62 USD → delta 11.22 USD.**
Le fee NON sono il problema ($0.63 totali = 0.05%/lato, esattamente l'assunto del
backtest). Il problema è tutto nel **timing delle uscite**.
- **Aperture allineate**: slippage da 8 a +27 bps, mediana ~±7 bps. OK.
- **Chiusure take-profit: +235 bps di slippage medio** (MR07 ETH short: +257/+267/+283/+333 bps).
Causa strutturale, non liquidità: il sim esce *al livello TP* intrabar (come il
backtest), il reale chiude **a mercato solo al poll del tick**, quando il prezzo è
già rientrato (TP toccato a ~1790, fill reale a ~1840). Sim +3 USD a trade, reale ~0.
- **Stop-loss: stessa meccanica ma a favore** (MR02 SL: 0.68 reale vs 2.87 sim).
Le fade però hanno più TP che SL → netto negativo.
- **2 `REAL_CLOSE` non verificate** (order_id null, fallback su stima sim). Venue flat
(`get_positions()=[]`), nessuna posizione orfana — ma sorvegliare i prossimi close.
**Implicazione onesta: l'edge di MR07 non sopravvive all'esecuzione market-on-poll.**
Il backtest assume il fill al livello TP; il reale incassa il prezzo post-rimbalzo.
## TODO (richiesto, da implementare)
Nello shadow-execution (`src/live/execution.py` + `StrategyWorker`): all'apertura
della posizione reale piazzare su Deribit un **LIMIT reduce-only appoggiato al
livello TP** (e idealmente stop-market per lo SL), invece di chiudere a mercato al
poll — così il fill reale replica l'assunzione intrabar del backtest.
Dettagli da considerare:
- cancellare/aggiornare l'ordine resting se il sim esce per `max_bars` o al restart (resume);
- i 3 fade BTC condividono lo strumento (posizioni nettate per conto): il limit
reduce-only deve coprire la SOLA quota del worker, come già fa `close_amount`;
- verificare il fill del resting order via `get_trade_history` (order_id), come per i market.