Fix trailing break-even stop loss not linked to CTP positions.
Match pending monitors to filled positions, reconcile pending on fast refresh, and refresh CTP before promote. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+31
-1
@@ -698,6 +698,26 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
|||||||
return row
|
return row
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _find_pending_monitor(conn, symbol: str, direction: str) -> Optional[dict]:
|
||||||
|
"""开仓委托 pending 仍带止损/移动保本元数据,需与 CTP 持仓关联展示。"""
|
||||||
|
direction = (direction or "long").strip().lower()
|
||||||
|
for r in conn.execute(
|
||||||
|
"SELECT * FROM trade_order_monitors WHERE status='pending' ORDER BY id DESC"
|
||||||
|
).fetchall():
|
||||||
|
row = dict(r)
|
||||||
|
if (row.get("direction") or "long") != direction:
|
||||||
|
continue
|
||||||
|
if _match_ctp_symbol(symbol, row.get("symbol") or ""):
|
||||||
|
return row
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _has_pending_monitors(conn) -> bool:
|
||||||
|
return bool(
|
||||||
|
conn.execute(
|
||||||
|
"SELECT 1 FROM trade_order_monitors WHERE status='pending' LIMIT 1"
|
||||||
|
).fetchone()
|
||||||
|
)
|
||||||
|
|
||||||
def _revive_closed_monitor(conn, symbol: str, direction: str) -> Optional[dict]:
|
def _revive_closed_monitor(conn, symbol: str, direction: str) -> Optional[dict]:
|
||||||
"""柜台仍有持仓但本地监控被误关时,恢复最近一条同品种记录。"""
|
"""柜台仍有持仓但本地监控被误关时,恢复最近一条同品种记录。"""
|
||||||
direction = (direction or "long").strip().lower()
|
direction = (direction or "long").strip().lower()
|
||||||
@@ -1459,6 +1479,10 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
|||||||
mon = mv
|
mon = mv
|
||||||
break
|
break
|
||||||
ths = _ctp_pos_to_ths_code(p) or (p.get("symbol") or "")
|
ths = _ctp_pos_to_ths_code(p) or (p.get("symbol") or "")
|
||||||
|
if not mon:
|
||||||
|
mon = _find_pending_monitor(
|
||||||
|
conn, ths, p.get("direction") or "long",
|
||||||
|
)
|
||||||
if mon and not fast:
|
if mon and not fast:
|
||||||
_sync_monitor_from_ctp(
|
_sync_monitor_from_ctp(
|
||||||
conn, int(mon["id"]), mon.get("symbol") or ths,
|
conn, int(mon["id"]), mon.get("symbol") or ths,
|
||||||
@@ -1495,8 +1519,9 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
|||||||
mode = get_trading_mode(get_setting)
|
mode = get_trading_mode(get_setting)
|
||||||
ctp_st = ctp_status(mode)
|
ctp_st = ctp_status(mode)
|
||||||
capital = _capital(conn)
|
capital = _capital(conn)
|
||||||
if ctp_st.get("connected") and not fast:
|
if ctp_st.get("connected") and (not fast or _has_pending_monitors(conn)):
|
||||||
_reconcile_pending(conn, mode, capital=capital)
|
_reconcile_pending(conn, mode, capital=capital)
|
||||||
|
if ctp_st.get("connected") and not fast:
|
||||||
_sync_trade_monitors_with_ctp(conn, mode)
|
_sync_trade_monitors_with_ctp(conn, mode)
|
||||||
rows = _build_trading_live_rows(conn, fast=fast)
|
rows = _build_trading_live_rows(conn, fast=fast)
|
||||||
active_orders = _build_active_orders(
|
active_orders = _build_active_orders(
|
||||||
@@ -2281,6 +2306,11 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
|||||||
order_price=price,
|
order_price=price,
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
try:
|
||||||
|
with _ctp_td_lock:
|
||||||
|
get_bridge().refresh_positions()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
_reconcile_pending(conn, mode, capital=_capital(conn))
|
_reconcile_pending(conn, mode, capital=_capital(conn))
|
||||||
st_row = conn.execute(
|
st_row = conn.execute(
|
||||||
"SELECT status FROM trade_order_monitors WHERE id=?", (mid,),
|
"SELECT status FROM trade_order_monitors WHERE id=?", (mid,),
|
||||||
|
|||||||
+1
-1
@@ -156,7 +156,7 @@ def reconcile_pending_orders(
|
|||||||
|
|
||||||
match = match_symbol_fn or _match_symbol
|
match = match_symbol_fn or _match_symbol
|
||||||
positions = (
|
positions = (
|
||||||
list_positions_fn(mode, refresh_if_empty=False, refresh_margin=False)
|
list_positions_fn(mode, refresh_if_empty=True, refresh_margin=False)
|
||||||
if list_positions_fn
|
if list_positions_fn
|
||||||
else []
|
else []
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user