Fix post-close UI: persist closing state in DB, defer trade log until CTP fill.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-03 22:58:14 +08:00
parent d6cfeeac75
commit e3b640b35c
2 changed files with 109 additions and 41 deletions
+14 -31
View File
@@ -66,6 +66,7 @@ from modules.trading.sl_tp_guard import (
monitor_order_status,
monitor_source_label,
place_monitor_exit_orders,
position_close_in_progress,
reconcile_monitors_without_position,
should_skip_monitor_revive,
start_sl_tp_guard_worker,
@@ -1234,8 +1235,6 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
break
if should_skip_monitor_revive(symbol, direction) and not ctp_still_open:
return None
if ctp_still_open and close_pending_active(symbol, direction):
clear_close_pending(symbol, direction)
for r in conn.execute(
"SELECT * FROM trade_order_monitors WHERE status='closed' ORDER BY id DESC LIMIT 40"
).fetchall():
@@ -2447,12 +2446,12 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
direction = p.get("direction") or "long"
if not mon:
mon = _find_pending_monitor(conn, ths, direction)
if not mon and not close_pending_active(ths, direction):
if not mon and not position_close_in_progress(conn, mode, ths, direction):
if fast:
mon = _find_active_monitor(conn, ths, direction)
else:
mon = _find_or_revive_monitor(conn, ths, direction)
if mon and not close_pending_active(ths, direction):
if mon and not position_close_in_progress(conn, mode, ths, direction):
if fast:
mon = _overlay_sl_tp_readonly(conn, mon, ths, direction) or mon
else:
@@ -2466,9 +2465,9 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
conn, mon.get("symbol") or ths, mon.get("direction") or direction,
) or mon
mon = _restore_monitor_sl_tp_if_missing(conn, mon, ths, direction) or mon
elif fast and not close_pending_active(ths, direction):
elif fast and not position_close_in_progress(conn, mode, ths, direction):
mon = _overlay_sl_tp_readonly(conn, None, ths, direction)
elif close_pending_active(ths, direction):
elif position_close_in_progress(conn, mode, ths, direction):
mon = mon or {"symbol": ths, "direction": direction}
try:
row = _compose_position_row(
@@ -2476,7 +2475,7 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
now_iso=now_iso, fast=fast,
)
if row:
if close_pending_active(ths, direction):
if position_close_in_progress(conn, mode, ths, direction):
row = _row_as_closing_state(row)
rows.append(row)
except Exception as exc:
@@ -3404,14 +3403,9 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
if not sym or price <= 0:
conn.close()
return jsonify({"ok": False, "error": "品种或价格无效"}), 400
if close_pending_active(sym, direction):
if close_pending_active(sym, direction, conn=conn):
conn.close()
return jsonify({"ok": False, "error": "平仓处理中,请稍候查看柜台委托"}), 400
from modules.trading.sl_tp_guard import _has_pending_close_order
if _has_pending_close_order(mode, sym, direction):
mark_close_pending(sym, direction)
conn.close()
return jsonify({"ok": False, "error": "已有平仓委托在柜台排队,请勿重复提交"}), 400
offset = "close_long" if direction == "long" else "close_short"
capital = _capital(conn)
mon = None
@@ -3434,6 +3428,12 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
mon = row
mid = int(row["id"])
break
from modules.trading.sl_tp_guard import _has_pending_close_order
if _has_pending_close_order(mode, sym, direction):
mark_close_pending(sym, direction, conn=conn, monitor_id=mid)
conn.commit()
conn.close()
return jsonify({"ok": False, "error": "已有平仓委托在柜台排队,请勿重复提交"}), 400
entry = float(mon.get("entry_price") or 0) if mon else 0.0
if entry <= 0:
for p in _ctp_positions(mode):
@@ -3450,24 +3450,7 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
lots=lots, price=price, settings=_settings_dict(),
order_type="market", urgency="stop_loss",
)
mark_close_pending(sym, direction)
# 始终写本地记录:CTP 同步依赖内存开平配对,重启后或成交回报延迟时会漏记
write_manual_close_trade_log(
conn,
mon,
symbol=sym,
direction=direction,
lots=lots,
close_price=price,
entry_price=entry or price,
trading_mode=mode,
capital=capital,
stop_loss=float(mon["stop_loss"]) if mon and mon.get("stop_loss") is not None else None,
take_profit=float(mon["take_profit"]) if mon and mon.get("take_profit") is not None else None,
open_time=(mon.get("open_time") or "") if mon else "",
symbol_name=(mon.get("symbol_name") or "") if mon else "",
market_code=(mon.get("market_code") or "") if mon else "",
)
mark_close_pending(sym, direction, conn=conn, monitor_id=mid)
if mon:
cancel_monitor_exit_orders(conn, mon, mode=mode)
conn.commit()