feat(dashboard): mostra i disaster-SL attivi nella sezione LIVE

Lo shadow espone i bracket disaster-SL aperti (open_orders filtrati per label DISASTER_LABEL,
centralizzata in deribit.py): asset, stop price, size. La sezione LIVE li mostra
("disaster-SL attivi (-30%): ..." o "nessuno (flat)"). 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 16:05:18 +00:00
parent e5e2d3ec9b
commit 3cba5bb9d0
4 changed files with 24 additions and 7 deletions
+3 -5
View File
@@ -15,7 +15,7 @@ from __future__ import annotations
from dataclasses import dataclass
from src.live.deribit import DeribitRead, disaster_stop_price, notional_to_amount, quantize_price
from src.live.deribit import DISASTER_LABEL, DeribitRead, disaster_stop_price, notional_to_amount, quantize_price
# Conto USDC -> perp LINEARE USDC (amount in base-coin). MAX_AMOUNT = TETTO HARD anti-fat-finger
# (~$630/$430 su un conto ~$600): backstop sopra il sizing di TP01, non il sizing operativo (quello
@@ -152,15 +152,13 @@ class DeribitTrader(DeribitRead):
def cancel_order(self, order_id: str) -> dict:
return self._unwrap(self._post("/mcp-deribit/tools/cancel_order", {"order_id": order_id})) or {}
DISASTER_LABEL = "tp01-disaster"
def ensure_disaster_sl(self, instrument: str, sl_pct: float) -> dict:
"""Garantisce UN disaster-SL coerente con la posizione (lifecycle completo, idempotente):
- flat -> cancella eventuali bracket orfani;
- long -> assicura UN solo STOP_MARKET reduce_only a ~-sl_pct, size = posizione;
- gia' coerente (1 bracket, amount~=, stop entro 5%) -> lascia com'e' (niente churn/gap)."""
pos = self.position_usd(instrument)
brackets = [o for o in self.open_orders(instrument) if (o.get("label") or "") == self.DISASTER_LABEL]
brackets = [o for o in self.open_orders(instrument) if (o.get("label") or "") == DISASTER_LABEL]
if abs(pos) < FLAT_USD:
for o in brackets:
self.cancel_order(o.get("order_id"))
@@ -179,7 +177,7 @@ class DeribitTrader(DeribitRead):
for o in brackets: # incoerente o multipli -> ricostruisci UN bracket
self.cancel_order(o.get("order_id"))
f = self.place_disaster_sl(instrument, "buy" if long else "sell", want_amount, want_stop,
label=self.DISASTER_LABEL)
label=DISASTER_LABEL)
return {"state": "placed" if f.verified else "place-failed", "stop": want_stop,
"amount": want_amount, "notes": f.notes}
# trade_history / open_orders ereditati da DeribitRead (read-only)