feat: 计仓改为固定手数/固定金额,推荐过滤与CTP保证金,下单与持仓UI优化
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+43
-1
@@ -59,18 +59,34 @@ def enrich_recommend_rows(
|
||||
capital: float,
|
||||
*,
|
||||
max_margin_pct: float = 30.0,
|
||||
trading_mode: str = "simulation",
|
||||
) -> list[dict]:
|
||||
"""用当前权益与保证金比例补算最大可开手数(兼容旧缓存)。"""
|
||||
cap = float(capital or 0)
|
||||
pct = max(1.0, min(100.0, float(max_margin_pct or 30.0)))
|
||||
budget = cap * pct / 100.0 if cap > 0 else 0.0
|
||||
ctp_connected = False
|
||||
try:
|
||||
from vnpy_bridge import ctp_estimate_margin_one_lot, ctp_status
|
||||
ctp_connected = bool(ctp_status(trading_mode).get("connected"))
|
||||
except Exception:
|
||||
pass
|
||||
enriched: list[dict] = []
|
||||
for raw in rows:
|
||||
row = dict(raw)
|
||||
margin_one = 0.0
|
||||
try:
|
||||
margin_one = float(row.get("margin_one_lot") or 0)
|
||||
except (TypeError, ValueError):
|
||||
margin_one = 0.0
|
||||
price = float(row.get("price") or 0)
|
||||
main_code = (row.get("main_code") or "").strip()
|
||||
if ctp_connected and main_code and price > 0:
|
||||
ctp_margin = ctp_estimate_margin_one_lot(trading_mode, main_code, price)
|
||||
if ctp_margin and ctp_margin > 0:
|
||||
margin_one = ctp_margin
|
||||
row["margin_one_lot"] = ctp_margin
|
||||
row["margin_source"] = "ctp"
|
||||
if margin_one > 0 and budget > 0:
|
||||
lots = int(math.floor(budget / margin_one))
|
||||
else:
|
||||
@@ -84,13 +100,32 @@ def enrich_recommend_rows(
|
||||
row["max_margin_pct"] = pct
|
||||
status = row.get("status") or ""
|
||||
if lots >= 1 and status in ("ok", "margin_ok"):
|
||||
src = "柜台" if row.get("margin_source") == "ctp" else "估算"
|
||||
row["status_label"] = (
|
||||
f"最大 {lots} 手" if status == "ok" else f"最大 {lots} 手·止损偏宽"
|
||||
)
|
||||
if row.get("margin_source") == "ctp":
|
||||
row["status_label"] += f"({src}保证金)"
|
||||
elif lots < 1 and status in ("ok", "margin_ok"):
|
||||
row["status"] = "blocked"
|
||||
row["status_label"] = "资金不足"
|
||||
enriched.append(row)
|
||||
return enriched
|
||||
|
||||
|
||||
def filter_recommend_by_sizing(
|
||||
rows: list[dict],
|
||||
*,
|
||||
sizing_mode: str,
|
||||
fixed_lots: int = 1,
|
||||
) -> list[dict]:
|
||||
"""固定手数模式下:最大手数低于设定值的品种不展示。"""
|
||||
if (sizing_mode or "").strip().lower() != "fixed":
|
||||
return rows
|
||||
fl = max(1, int(fixed_lots or 1))
|
||||
return [r for r in rows if int(r.get("max_lots") or 0) >= fl]
|
||||
|
||||
|
||||
def refresh_recommend_cache(
|
||||
conn,
|
||||
capital: float,
|
||||
@@ -164,6 +199,9 @@ def recommend_payload(
|
||||
*,
|
||||
live_capital: float,
|
||||
max_margin_pct: float = 30.0,
|
||||
trading_mode: str = "simulation",
|
||||
sizing_mode: str = "fixed",
|
||||
fixed_lots: int = 1,
|
||||
) -> dict:
|
||||
"""读取缓存并附带当前权益(展示用,可能与缓存计算时不同)。"""
|
||||
payload = load_recommend_cache(conn)
|
||||
@@ -172,6 +210,10 @@ def recommend_payload(
|
||||
payload["capital"] = cap
|
||||
payload["max_margin_pct"] = pct
|
||||
rows = payload.get("rows") or []
|
||||
payload["rows"] = enrich_recommend_rows(rows, cap, max_margin_pct=pct)
|
||||
rows = enrich_recommend_rows(
|
||||
rows, cap, max_margin_pct=pct, trading_mode=trading_mode,
|
||||
)
|
||||
rows = filter_recommend_by_sizing(rows, sizing_mode=sizing_mode, fixed_lots=fixed_lots)
|
||||
payload["rows"] = rows
|
||||
payload["needs_refresh"] = recommend_cache_needs_refresh(payload, capital=cap)
|
||||
return payload
|
||||
|
||||
Reference in New Issue
Block a user