Fix stale pending orders after CTP rejection or cancel.
When the exchange rejects or cancels an order, close local pending monitors once the order leaves CTP active list instead of waiting for the full timeout. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+44
-2
@@ -19,6 +19,33 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
TZ = ZoneInfo("Asia/Shanghai")
|
||||
DEFAULT_PENDING_ORDER_TIMEOUT_SEC = 300
|
||||
# 报单刚提交后短暂等待 CTP 回报,避免误判为拒单
|
||||
PENDING_ORDER_SETTLE_GRACE_SEC = 8
|
||||
|
||||
|
||||
def pending_monitor_has_live_order(
|
||||
mon: dict,
|
||||
*,
|
||||
active_orders: dict[str, dict],
|
||||
active_order_list: list[dict],
|
||||
match_fn: Callable[[str, str], bool] | None = None,
|
||||
) -> bool:
|
||||
"""本地 pending 是否仍对应 CTP 柜台上的有效开仓委托。"""
|
||||
match = match_fn or _match_symbol
|
||||
sym = mon.get("symbol") or ""
|
||||
direction = mon.get("direction") or "long"
|
||||
vt_oid = (mon.get("vt_order_id") or "").strip()
|
||||
age = pending_age_sec(mon)
|
||||
|
||||
if vt_oid and _vt_order_in_active(vt_oid, active_orders):
|
||||
return True
|
||||
if _symbol_open_order_active(active_order_list, sym, direction, match):
|
||||
return True
|
||||
if not vt_oid and age < PENDING_ORDER_SETTLE_GRACE_SEC:
|
||||
return True
|
||||
if vt_oid and age < PENDING_ORDER_SETTLE_GRACE_SEC:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def parse_monitor_ts(raw: str) -> Optional[float]:
|
||||
@@ -183,8 +210,8 @@ def reconcile_pending_orders(
|
||||
continue
|
||||
|
||||
live_open = _symbol_open_order_active(active_order_list, sym, direction, match)
|
||||
if live_open or (vt_oid and age < limit_sec):
|
||||
if live_open and age >= limit_sec and is_trading_session():
|
||||
if live_open:
|
||||
if age >= limit_sec and is_trading_session():
|
||||
cancel_oid = (
|
||||
vt_oid
|
||||
or live_open.get("vt_order_id")
|
||||
@@ -199,6 +226,21 @@ def reconcile_pending_orders(
|
||||
stats["cancelled"] += 1
|
||||
continue
|
||||
|
||||
# 有委托号但已不在 CTP 活跃列表且无持仓 → 拒单/已撤/终态
|
||||
if vt_oid:
|
||||
if age < PENDING_ORDER_SETTLE_GRACE_SEC:
|
||||
continue
|
||||
conn.execute(
|
||||
"UPDATE trade_order_monitors SET status='closed' WHERE id=?",
|
||||
(mid,),
|
||||
)
|
||||
stats["closed"] += 1
|
||||
logger.info(
|
||||
"pending monitor=%s order=%s closed (no longer active on CTP)",
|
||||
mid, vt_oid,
|
||||
)
|
||||
continue
|
||||
|
||||
if age >= limit_sec:
|
||||
if vt_oid and is_trading_session():
|
||||
if ctp_cancel_order(mode, vt_oid):
|
||||
|
||||
Reference in New Issue
Block a user