feat(execution): reconcile timed-out orders safely
This commit is contained in:
@@ -9,6 +9,7 @@ from __future__ import annotations
|
||||
|
||||
import threading
|
||||
from decimal import Decimal
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from trex_core.adapters.broker.seq_store import SeqStore
|
||||
@@ -80,7 +81,15 @@ class PaperBroker:
|
||||
self._orders[oid] = _Order(oid, req)
|
||||
return OrderAck(accepted=True, broker_order_id=oid, venue=req.venue)
|
||||
|
||||
def poll_fill(self, broker_order_id: str, *, side: str, symbol: str) -> FillStatus:
|
||||
def poll_fill(
|
||||
self,
|
||||
broker_order_id: str,
|
||||
*,
|
||||
side: str,
|
||||
symbol: str,
|
||||
order_date: Optional[str] = None,
|
||||
submitted_at: Optional[datetime] = None,
|
||||
) -> FillStatus:
|
||||
with self._lock:
|
||||
o = self._orders.get(broker_order_id)
|
||||
if o is None:
|
||||
@@ -91,7 +100,12 @@ class PaperBroker:
|
||||
if symbol in self._reject:
|
||||
return FillStatus(state="rejected", raw={"reason": "paper_reject"})
|
||||
if o.polls <= self._fill_after:
|
||||
return FillStatus(state="accepted", filled_qty=o.filled, avg_price=o.price)
|
||||
return FillStatus(
|
||||
state="accepted",
|
||||
filled_qty=o.filled,
|
||||
avg_price=o.price,
|
||||
raw={"order_open_confirmed": True},
|
||||
)
|
||||
step = self._qty_per_poll if self._qty_per_poll is not None else (o.qty - o.filled)
|
||||
o.filled = min(o.qty, o.filled + step)
|
||||
if o.filled >= o.qty:
|
||||
@@ -105,7 +119,12 @@ class PaperBroker:
|
||||
state="filled", filled_qty=o.filled, avg_price=o.price,
|
||||
execution_id=execution_id, fee=fee, tax=tax,
|
||||
)
|
||||
return FillStatus(state="partially_filled", filled_qty=o.filled, avg_price=o.price)
|
||||
return FillStatus(
|
||||
state="partially_filled",
|
||||
filled_qty=o.filled,
|
||||
avg_price=o.price,
|
||||
raw={"order_open_confirmed": True},
|
||||
)
|
||||
|
||||
def cancel_order(
|
||||
self,
|
||||
|
||||
Reference in New Issue
Block a user