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:
dekun
2026-06-26 22:21:15 +08:00
parent fd49b08c08
commit f2940d41e9
4 changed files with 229 additions and 2 deletions
+95
View File
@@ -0,0 +1,95 @@
"""Deploy pending order reconcile fix and verify stale monitors cleared."""
import paramiko
import sys
import textwrap
from pathlib import Path
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
root = Path(__file__).resolve().parents[1]
FILES = [
"order_pending.py",
"install_trading.py",
]
VERIFY = textwrap.dedent(
'''
import sqlite3, urllib.request, urllib.parse, http.cookiejar, json
conn = sqlite3.connect("/opt/qihuo/data.db")
conn.row_factory = sqlite3.Row
pending = conn.execute(
"SELECT id, symbol, direction, vt_order_id, status FROM trade_order_monitors WHERE status='pending'"
).fetchall()
print("pending_monitors", len(pending))
for r in pending:
print(dict(r))
jar = http.cookiejar.CookieJar()
op = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
user = pwd = ""
for line in open("/opt/qihuo/.env"):
line = line.strip()
if line.startswith("ADMIN_USERNAME="):
user = line.split("=", 1)[1].strip().strip('"').strip("'")
if line.startswith("ADMIN_PASSWORD="):
pwd = line.split("=", 1)[1].strip().strip('"').strip("'")
op.open(urllib.request.Request(
"http://127.0.0.1:6600/login",
urllib.parse.urlencode({"username": user, "password": pwd}).encode(),
))
raw = op.open("http://127.0.0.1:6600/api/trading/live").read().decode()
data = json.loads(raw)
orders = data.get("active_orders") or []
cj = [o for o in orders if "CJ" in (o.get("symbol_code") or "").upper()]
print("active_orders", len(orders), "cj_orders", len(cj))
ok = True
if cj:
ok = False
print("FAIL still showing CJ pending in active_orders", cj)
if ok:
print("VERIFY PASS")
'''
)
def main() -> None:
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect("192.168.8.21", username="root", password="woaini88", timeout=15)
sftp = c.open_sftp()
for rel in FILES:
local = root / rel
remote = f"/opt/qihuo/{rel.replace(chr(92), '/')}"
sftp.put(str(local), remote)
print("uploaded", rel)
sftp.close()
for cmd in (
"cd /opt/qihuo && pm2 restart qihuo",
"sleep 4",
):
print(">>>", cmd)
_, stdout, stderr = c.exec_command(cmd)
out = stdout.read().decode("utf-8", errors="replace")
err = stderr.read().decode("utf-8", errors="replace")
if out.strip():
print(out.strip())
if err.strip():
print(err.strip())
sftp = c.open_sftp()
with sftp.open("/tmp/verify_pending_fix.py", "w") as f:
f.write(VERIFY)
sftp.close()
_, stdout, stderr = c.exec_command("/opt/qihuo/venv/bin/python /tmp/verify_pending_fix.py")
print(stdout.read().decode("utf-8", errors="replace"))
err = stderr.read().decode("utf-8", errors="replace")
if err.strip():
print(err.strip())
c.close()
if __name__ == "__main__":
main()
+55
View File
@@ -0,0 +1,55 @@
import paramiko
import sys
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
VERIFY = r"""
import sqlite3, urllib.request, urllib.parse, http.cookiejar, json, os
db = "/opt/qihuo/futures.db"
print("db", db)
conn = sqlite3.connect(db)
conn.row_factory = sqlite3.Row
pending = conn.execute(
"SELECT id, symbol, direction, vt_order_id, status FROM trade_order_monitors WHERE status='pending'"
).fetchall()
print("pending_monitors", len(pending))
for r in pending:
print(dict(r))
jar = http.cookiejar.CookieJar()
op = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
user = pwd = ""
for line in open("/opt/qihuo/.env"):
line = line.strip()
if line.startswith("ADMIN_USERNAME="):
user = line.split("=", 1)[1].strip().strip('"').strip("'")
if line.startswith("ADMIN_PASSWORD="):
pwd = line.split("=", 1)[1].strip().strip('"').strip("'")
op.open(urllib.request.Request(
"http://127.0.0.1:6600/login",
urllib.parse.urlencode({"username": user, "password": pwd}).encode(),
))
raw = op.open("http://127.0.0.1:6600/api/trading/live").read().decode()
data = json.loads(raw)
orders = data.get("active_orders") or []
cj = [o for o in orders if "CJ" in (o.get("symbol_code") or "").upper()]
print("active_orders", len(orders), "cj_orders", len(cj))
if cj:
print("cj detail", cj)
else:
print("VERIFY PASS")
"""
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect("192.168.8.21", username="root", password="woaini88", timeout=15)
sftp = c.open_sftp()
with sftp.open("/tmp/verify_pending_fix.py", "w") as f:
f.write(VERIFY)
sftp.close()
_, stdout, stderr = c.exec_command("/opt/qihuo/venv/bin/python /tmp/verify_pending_fix.py")
print(stdout.read().decode("utf-8", errors="replace"))
print(stderr.read().decode("utf-8", errors="replace"))
c.close()