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:
@@ -274,6 +274,30 @@ def count_active_trade_monitors(conn) -> int:
|
||||
return 0
|
||||
|
||||
|
||||
def _position_slot_key(sym: str, direction: str) -> tuple[str, str]:
|
||||
base = (sym or "").strip().lower().split(".")[0]
|
||||
return (base, (direction or "long").strip().lower())
|
||||
|
||||
|
||||
def active_position_slots_from_monitors(conn) -> set[tuple[str, str]]:
|
||||
"""按品种+方向去重;滚仓/加仓共用同一监控,不额外占仓位槽。"""
|
||||
keys: set[tuple[str, str]] = set()
|
||||
try:
|
||||
for r in conn.execute(
|
||||
"SELECT symbol, direction FROM trade_order_monitors WHERE status='active'"
|
||||
):
|
||||
sym = (r["symbol"] or "").strip()
|
||||
if sym:
|
||||
keys.add(_position_slot_key(sym, r["direction"] or "long"))
|
||||
except Exception:
|
||||
pass
|
||||
return keys
|
||||
|
||||
|
||||
def count_active_position_slots(conn) -> int:
|
||||
return len(active_position_slots_from_monitors(conn))
|
||||
|
||||
|
||||
def _position_keys_from_rows(rows: list) -> set[tuple[str, str]]:
|
||||
keys: set[tuple[str, str]] = set()
|
||||
for p in rows or []:
|
||||
@@ -285,10 +309,10 @@ def _position_keys_from_rows(rows: list) -> set[tuple[str, str]]:
|
||||
or p.get("symbol_code")
|
||||
or p.get("ths_code")
|
||||
or ""
|
||||
).strip().lower()
|
||||
).strip()
|
||||
direction = (p.get("direction") or "long").strip().lower()
|
||||
if sym:
|
||||
keys.add((sym, direction))
|
||||
keys.add(_position_slot_key(sym, direction))
|
||||
return keys
|
||||
|
||||
|
||||
@@ -298,8 +322,8 @@ def effective_active_position_count(
|
||||
*,
|
||||
ctp_connected: Optional[bool] = None,
|
||||
) -> int:
|
||||
"""风控持仓数:柜台/快照实际持仓优先,本地监控作兜底。"""
|
||||
monitor_count = count_active_trade_monitors(conn)
|
||||
"""风控持仓数:品种+方向槽位去重;滚仓不计入新仓位。"""
|
||||
keys = active_position_slots_from_monitors(conn)
|
||||
if ctp_connected is None:
|
||||
try:
|
||||
from modules.ctp.vnpy_bridge import ctp_status
|
||||
@@ -307,23 +331,21 @@ def effective_active_position_count(
|
||||
ctp_connected = bool(ctp_status(mode).get("connected"))
|
||||
except Exception:
|
||||
ctp_connected = False
|
||||
if not ctp_connected:
|
||||
return monitor_count
|
||||
keys: set[tuple[str, str]] = set()
|
||||
try:
|
||||
from modules.ctp.ctp_trading_state import trading_state
|
||||
if ctp_connected:
|
||||
try:
|
||||
from modules.ctp.ctp_trading_state import trading_state
|
||||
|
||||
keys |= _position_keys_from_rows(trading_state.get_positions())
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
from modules.trading.position_stream import position_hub
|
||||
keys |= _position_keys_from_rows(trading_state.get_positions())
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
from modules.trading.position_stream import position_hub
|
||||
|
||||
snap = position_hub.get_snapshot() or {}
|
||||
keys |= _position_keys_from_rows(snap.get("rows"))
|
||||
except Exception:
|
||||
pass
|
||||
return max(monitor_count, len(keys))
|
||||
snap = position_hub.get_snapshot() or {}
|
||||
keys |= _position_keys_from_rows(snap.get("rows"))
|
||||
except Exception:
|
||||
pass
|
||||
return len(keys)
|
||||
|
||||
|
||||
def parse_mood_issues(raw: Any) -> list[str]:
|
||||
@@ -419,7 +441,11 @@ def get_risk_status(
|
||||
"UPDATE account_risk_state SET cooloff_until_ms=NULL, cooloff_hours=NULL WHERE id=1"
|
||||
)
|
||||
conn.commit()
|
||||
active = count_active_trade_monitors(conn) if active_count is None else int(active_count)
|
||||
active = (
|
||||
count_active_position_slots(conn)
|
||||
if active_count is None
|
||||
else int(active_count)
|
||||
)
|
||||
mx = max_active_positions()
|
||||
pos_limit = active >= mx
|
||||
daily_opens = count_daily_opens(conn, now)
|
||||
|
||||
Reference in New Issue
Block a user