Fix position limit to count distinct slots and speed up strategy page.
Roll/add-on shares one monitor per symbol+direction so it no longer inflates the active position count; strategy page skips full CTP sync when monitors already exist. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+38
-25
@@ -3502,25 +3502,32 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
||||
return None
|
||||
|
||||
def _ensure_strategy_monitors(conn, mode: str) -> int:
|
||||
"""策略页加载前:恢复误关监控并同步柜台,与持仓页逻辑一致。"""
|
||||
"""策略页:仅当柜台持仓缺少 active 监控时才恢复/同步,避免每次打开都全量写库。"""
|
||||
if not _cached_ctp_status(mode).get("connected"):
|
||||
return 0
|
||||
capital = _capital(conn)
|
||||
synced = 0
|
||||
seen: set[tuple[str, str]] = set()
|
||||
positions = list(trading_state.get_positions() or [])
|
||||
if not positions:
|
||||
positions = list(_ctp_positions(mode, refresh_if_empty=False) or [])
|
||||
missing: list[tuple[dict, str, str]] = []
|
||||
for p in positions:
|
||||
lots = int(p.get("lots") or 0)
|
||||
if lots <= 0:
|
||||
continue
|
||||
ths = _ctp_pos_to_ths_code(p) or (p.get("symbol") or "")
|
||||
direction = (p.get("direction") or "long").strip().lower()
|
||||
key = (ths.lower(), direction)
|
||||
key = (ths.lower().split(".")[0], direction)
|
||||
if key in seen:
|
||||
continue
|
||||
seen.add(key)
|
||||
if _find_active_monitor(conn, ths, direction):
|
||||
continue
|
||||
missing.append((p, ths, direction))
|
||||
if not missing:
|
||||
return 0
|
||||
capital = _capital(conn)
|
||||
synced = 0
|
||||
for p, ths, direction in missing:
|
||||
mon = _find_or_revive_monitor(conn, ths, direction)
|
||||
if not mon:
|
||||
continue
|
||||
@@ -3550,27 +3557,33 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
||||
capital = _capital(conn)
|
||||
mode = get_trading_mode(get_setting)
|
||||
_ensure_strategy_monitors(conn, mode)
|
||||
for grow in conn.execute(
|
||||
"SELECT id, order_monitor_id, initial_lots FROM roll_groups WHERE status='active'"
|
||||
).fetchall():
|
||||
gfix = dict(grow)
|
||||
if int(gfix.get("initial_lots") or 0) > 0:
|
||||
continue
|
||||
mon_row = conn.execute(
|
||||
"SELECT lots FROM trade_order_monitors WHERE id=?",
|
||||
(int(gfix["order_monitor_id"]),),
|
||||
).fetchone()
|
||||
if not mon_row:
|
||||
continue
|
||||
gid = int(gfix["id"])
|
||||
filled = _roll_filled_lots_map(conn, [gid]).get(gid, 0)
|
||||
lots = int(mon_row["lots"] or 0)
|
||||
initial = lots if lots > 0 and filled > 0 and lots <= filled else max(1, lots - filled)
|
||||
conn.execute(
|
||||
"UPDATE roll_groups SET initial_lots=? WHERE id=?",
|
||||
(initial, gid),
|
||||
)
|
||||
commit_retry(conn)
|
||||
need_initial = conn.execute(
|
||||
"SELECT id FROM roll_groups WHERE status='active' AND COALESCE(initial_lots, 0)=0 LIMIT 1"
|
||||
).fetchone()
|
||||
if need_initial:
|
||||
for grow in conn.execute(
|
||||
"SELECT id, order_monitor_id, initial_lots FROM roll_groups WHERE status='active' AND COALESCE(initial_lots, 0)=0"
|
||||
).fetchall():
|
||||
gfix = dict(grow)
|
||||
mon_row = conn.execute(
|
||||
"SELECT lots FROM trade_order_monitors WHERE id=?",
|
||||
(int(gfix["order_monitor_id"]),),
|
||||
).fetchone()
|
||||
if not mon_row:
|
||||
continue
|
||||
gid = int(gfix["id"])
|
||||
filled = _roll_filled_lots_map(conn, [gid]).get(gid, 0)
|
||||
lots = int(mon_row["lots"] or 0)
|
||||
initial = (
|
||||
lots
|
||||
if lots > 0 and filled > 0 and lots <= filled
|
||||
else max(1, lots - filled)
|
||||
)
|
||||
conn.execute(
|
||||
"UPDATE roll_groups SET initial_lots=? WHERE id=?",
|
||||
(initial, gid),
|
||||
)
|
||||
commit_retry(conn)
|
||||
active_trend = conn.execute(
|
||||
"SELECT * FROM trend_pullback_plans WHERE status='active' ORDER BY id DESC LIMIT 1"
|
||||
).fetchone()
|
||||
|
||||
Reference in New Issue
Block a user