Stop auto-deleting roll pending legs when monitor briefly closes but CTP position remains.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3657,7 +3657,25 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
|||||||
(now_s, gid),
|
(now_s, gid),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _ctp_has_open_position(mode: str, sym: str, direction: str) -> bool:
|
||||||
|
"""柜台是否仍有该品种方向持仓(滚仓组是否应保留)。"""
|
||||||
|
direction = (direction or "long").strip().lower()
|
||||||
|
sym = (sym or "").strip()
|
||||||
|
if not sym or not ctp_status(mode).get("connected"):
|
||||||
|
return False
|
||||||
|
for p in list(_ctp_positions(mode) or []) + list(trading_state.get_positions() or []):
|
||||||
|
if int(p.get("lots") or 0) <= 0:
|
||||||
|
continue
|
||||||
|
if (p.get("direction") or "long").strip().lower() != direction:
|
||||||
|
continue
|
||||||
|
if _match_ctp_symbol(sym, p.get("symbol") or ""):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def _close_stale_roll_groups(conn) -> int:
|
def _close_stale_roll_groups(conn) -> int:
|
||||||
|
"""仅当持仓监控已结束且柜台无对应持仓时,才归档滚仓组。"""
|
||||||
|
mode = get_trading_mode(get_setting)
|
||||||
|
_revive_monitors_for_open_ctp(conn, mode)
|
||||||
rows = conn.execute(
|
rows = conn.execute(
|
||||||
"""SELECT g.*, m.status AS monitor_status
|
"""SELECT g.*, m.status AS monitor_status
|
||||||
FROM roll_groups g
|
FROM roll_groups g
|
||||||
@@ -3665,9 +3683,33 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
|||||||
WHERE g.status='active'
|
WHERE g.status='active'
|
||||||
AND (m.id IS NULL OR m.status != 'active')"""
|
AND (m.id IS NULL OR m.status != 'active')"""
|
||||||
).fetchall()
|
).fetchall()
|
||||||
|
closed = 0
|
||||||
for r in rows:
|
for r in rows:
|
||||||
_archive_roll_group(conn, dict(r), result_label="持仓已结束")
|
grp = dict(r)
|
||||||
return len(rows)
|
gid = int(grp.get("id") or 0)
|
||||||
|
sym = (grp.get("symbol") or "").strip()
|
||||||
|
direction = (grp.get("direction") or "long").strip().lower()
|
||||||
|
mid = int(grp.get("order_monitor_id") or 0)
|
||||||
|
if mid:
|
||||||
|
fresh = conn.execute(
|
||||||
|
"SELECT status FROM trade_order_monitors WHERE id=?",
|
||||||
|
(mid,),
|
||||||
|
).fetchone()
|
||||||
|
if fresh and (fresh["status"] or "").strip().lower() == "active":
|
||||||
|
continue
|
||||||
|
if _ctp_has_open_position(mode, sym, direction):
|
||||||
|
if mid:
|
||||||
|
_revive_closed_monitor(conn, sym, direction)
|
||||||
|
logger.debug(
|
||||||
|
"skip stale roll group #%s: CTP position still open %s %s",
|
||||||
|
gid, sym, direction,
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
_archive_roll_group(conn, grp, result_label="持仓已结束")
|
||||||
|
closed += 1
|
||||||
|
if closed:
|
||||||
|
commit_retry(conn)
|
||||||
|
return closed
|
||||||
|
|
||||||
def _enrich_roll_leg_row(row: dict, mode: str) -> dict:
|
def _enrich_roll_leg_row(row: dict, mode: str) -> dict:
|
||||||
out = dict(row)
|
out = dict(row)
|
||||||
@@ -4703,6 +4745,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
|||||||
init_strategy_tables(conn)
|
init_strategy_tables(conn)
|
||||||
mode = get_trading_mode(get_setting)
|
mode = get_trading_mode(get_setting)
|
||||||
try:
|
try:
|
||||||
|
if ctp_status(mode).get("connected"):
|
||||||
|
_revive_monitors_for_open_ctp(conn, mode)
|
||||||
check_roll_monitors(
|
check_roll_monitors(
|
||||||
conn,
|
conn,
|
||||||
get_mark_price_fn=lambda sym: _roll_mark_price(sym, {}, mode, allow_ctp=True),
|
get_mark_price_fn=lambda sym: _roll_mark_price(sym, {}, mode, allow_ctp=True),
|
||||||
|
|||||||
Reference in New Issue
Block a user