diff --git a/scripts/live/usde_convert.py b/scripts/live/usde_convert.py index baeacf3..2fa07cb 100644 --- a/scripts/live/usde_convert.py +++ b/scripts/live/usde_convert.py @@ -120,9 +120,18 @@ def cancella_residui(c) -> list[str]: -> lista degli order_id cancellati. Se la LETTURA degli ordini aperti fallisce SOLLEVA: non si piazza un nuovo ordine senza sapere cosa c'e' gia' aperto (P5, non si ordina al buio).""" - out = c._unwrap(c._post("/mcp-deribit/tools/get_open_orders", - {"currency": "USDC", "kind": "spot", "type": "all"})) - ordini = out if isinstance(out, list) else (out.get("orders", []) if isinstance(out, dict) else []) + # non e' verificato sotto quale valuta Deribit elenchi lo spot USDE_USDC (quotazione USDC o + # base USDE): si interrogano entrambe e si unisce per order_id, cosi' non si perde il residuo + # se il venue lo elenca sotto la base. + visti = {} + for valuta in ("USDC", "USDE"): + out = c._unwrap(c._post("/mcp-deribit/tools/get_open_orders", + {"currency": valuta, "kind": "spot", "type": "all"})) + ordini = out if isinstance(out, list) else (out.get("orders", []) if isinstance(out, dict) else []) + for o in ordini: + if isinstance(o, dict) and o.get("order_id") is not None: + visti[o["order_id"]] = o + ordini = list(visti.values()) cancellati = [] for o in ordini: if not isinstance(o, dict): diff --git a/tests/test_usde_u3.py b/tests/test_usde_u3.py index 6c526ed..25ed034 100644 --- a/tests/test_usde_u3.py +++ b/tests/test_usde_u3.py @@ -31,8 +31,13 @@ from src.live import usde as U # noqa: E402 class _ClientOrdini: """Fake minimale per _post/_unwrap: nessuna rete.""" - def __init__(self, open_orders=None, risposte_place=None, boom_cancel=None): + def __init__(self, open_orders=None, open_orders_usde=None, risposte_place=None, + boom_cancel=None): self.open_orders = open_orders or [] + # None = stessa lista di open_orders (retrocompat dei test esistenti, che non + # distinguono la valuta interrogata); una lista propria serve solo a chi vuole + # simulare un residuo elencato SOLO sotto USDE. + self.open_orders_usde = open_orders_usde self.risposte_place = list(risposte_place or []) self.boom_cancel = boom_cancel or set() # order_id la cui cancel fallisce self.cancellati = [] @@ -41,6 +46,8 @@ class _ClientOrdini: def _post(self, path, payload): if path.endswith("get_open_orders"): self.get_open_orders_chiamate += 1 + if payload.get("currency") == "USDE" and self.open_orders_usde is not None: + return {"result": self.open_orders_usde} return {"result": self.open_orders} if path.endswith("cancel_order"): oid = payload["order_id"] @@ -72,6 +79,19 @@ def test_cancella_residui_solo_le_nostre_label(): assert client.cancellati == ["R1"], "l'ordine con altra label o su altro strumento non si tocca" +def test_cancella_residui_trovato_solo_sotto_USDE(): + """Non e' verificato sotto quale valuta Deribit elenchi lo spot USDE_USDC: se lo elenca + sotto la base (USDE) invece che sotto la quotazione (USDC), la sola lettura USDC non lo + vedrebbe mai e il residuo si accumulerebbe per sempre.""" + client = _ClientOrdini( + open_orders=[], + open_orders_usde=[{"instrument": U.SPOT, "label": "usde-quota-0.64", "order_id": "R9"}], + ) + out = C.cancella_residui(client) + assert out == ["R9"] + assert client.cancellati == ["R9"] + + def test_cancella_residui_senza_residui_non_cancella_nulla(): client = _ClientOrdini(open_orders=[ {"instrument": U.SPOT, "label": "altra-cosa", "order_id": "R2"},