feat(live): disaster-SL on-book con lifecycle completo (idempotente) nel loop di esecuzione

ensure_disaster_sl(): garantisce UN solo STOP_MARKET reduce_only a ~-30% coerente con la posizione,
ad ogni run del loop, per asset:
- flat  -> cancella i bracket orfani;
- long  -> assicura lo stop (size = posizione, prezzo al tick);
- gia' coerente (1 bracket, amount~=, stop entro 5%) -> lascia com'e' (niente churn ne' gap di
  protezione fra cancel e place).

- deribit.py: open_orders (merge type all+trigger_all), disaster_stop_price.
- execution.py: cancel_order + ensure_disaster_sl.
- live_execute.py: gestione bracket ogni run, gated come l'esecuzione. Validato armato: flat ->
  disaster-SL 'flat' (cleanup), zero ordini. Test 28/28.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano Dal Pastro
2026-06-20 15:47:30 +00:00
parent 4650aa71a2
commit e5e2d3ec9b
4 changed files with 81 additions and 13 deletions
+6
View File
@@ -77,6 +77,12 @@ def test_partial_rebalance_direction():
assert dn["side"] == "sell" and dn["delta_notional"] == -400 and dn["reduce_only"] is False
def test_disaster_stop_price():
from src.live.deribit import disaster_stop_price
assert disaster_stop_price(LIN, 64000, 0.30, long=True) == 44800.0 # -30%, al tick
assert disaster_stop_price(LIN, 64000, 0.30, long=False) == 83200.0 # +30% (short)
def test_parity_live_target_equals_backtest():
from src.backtest.harness import load
tp = TrendPortfolio(**CANONICAL)