Use CTP contract margin rates for position margin and ratio display.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+64
-15
@@ -88,6 +88,7 @@ from vnpy_bridge import (
|
||||
_ctp_td_lock,
|
||||
ctp_cancel_order,
|
||||
ctp_connect,
|
||||
ctp_estimate_margin_one_lot,
|
||||
ctp_get_account,
|
||||
ctp_get_tick_price,
|
||||
ctp_list_active_orders,
|
||||
@@ -211,6 +212,41 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
||||
return codes.get("ths_code") or sym
|
||||
return sym
|
||||
|
||||
def _resolve_position_margin(
|
||||
*,
|
||||
sym: str,
|
||||
direction: str,
|
||||
lots: int,
|
||||
entry: float,
|
||||
mode: str,
|
||||
ctp: Optional[dict] = None,
|
||||
mon_margin: Optional[float] = None,
|
||||
est_margin: Optional[float] = None,
|
||||
) -> tuple[Optional[float], str]:
|
||||
"""占用保证金:柜台持仓 > CTP 合约率估算 > 本地规格估算 > 库内缓存。"""
|
||||
ctp_margin = float(ctp.get("margin") or 0) if ctp else 0.0
|
||||
if ctp_margin > 0:
|
||||
return round(ctp_margin, 2), "ctp"
|
||||
connected = bool(ctp_status(mode).get("connected"))
|
||||
ths_sym = sym
|
||||
if ctp:
|
||||
ths_sym = _ctp_pos_to_ths_code(ctp) or sym
|
||||
else:
|
||||
codes = ths_to_codes(sym)
|
||||
if codes and codes.get("ths_code"):
|
||||
ths_sym = codes["ths_code"]
|
||||
if connected and ths_sym and entry > 0 and lots > 0:
|
||||
per_lot = ctp_estimate_margin_one_lot(
|
||||
mode, ths_sym, entry, direction=direction,
|
||||
)
|
||||
if per_lot and per_lot > 0:
|
||||
return round(per_lot * lots, 2), "ctp"
|
||||
if est_margin and float(est_margin) > 0:
|
||||
return round(float(est_margin), 2), "estimate"
|
||||
if not connected and mon_margin and float(mon_margin) > 0:
|
||||
return round(float(mon_margin), 2), "db"
|
||||
return None, "estimate"
|
||||
|
||||
def _ensure_monitors_from_ctp(conn, mode: str) -> None:
|
||||
"""CTP 有持仓但本地无监控时,自动补写一条 active 记录供展示。"""
|
||||
if not ctp_status(mode).get("connected"):
|
||||
@@ -611,7 +647,18 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
||||
mark = ctp_get_tick_price(mode, sym)
|
||||
if mark is None or mark <= 0:
|
||||
mark = entry if entry else None
|
||||
margin = ctp_margin if ctp_margin > 0 else None
|
||||
est = calc_position_metrics(
|
||||
direction, entry, entry, entry, lots, mark or entry, capital, sym,
|
||||
).get("margin")
|
||||
margin, _src = _resolve_position_margin(
|
||||
sym=sym,
|
||||
direction=direction,
|
||||
lots=lots,
|
||||
entry=entry,
|
||||
mode=mode,
|
||||
ctp=p,
|
||||
est_margin=est,
|
||||
)
|
||||
position_pct = None
|
||||
if margin and capital > 0:
|
||||
position_pct = round(float(margin) / float(capital) * 100, 2)
|
||||
@@ -733,20 +780,22 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
|
||||
direction, entry, sl if sl is not None else entry,
|
||||
tp if tp is not None else entry, lots, mark, capital, sym,
|
||||
)
|
||||
if margin is None or float(margin or 0) <= 0:
|
||||
ctp_margin = float(ctp.get("margin") or 0) if ctp else 0.0
|
||||
est_margin = pos_metrics.get("margin")
|
||||
margin = ctp_margin if ctp_margin > 0 else est_margin
|
||||
margin_source = "ctp" if ctp_margin > 0 else "estimate"
|
||||
else:
|
||||
margin_source = "ctp"
|
||||
if position_pct is None or float(position_pct or 0) <= 0:
|
||||
position_pct = (
|
||||
round(float(margin) / capital * 100, 2)
|
||||
if capital > 0 and margin
|
||||
else pos_metrics.get("position_pct")
|
||||
)
|
||||
else:
|
||||
mon_margin = margin
|
||||
margin, margin_source = _resolve_position_margin(
|
||||
sym=sym,
|
||||
direction=direction,
|
||||
lots=lots,
|
||||
entry=entry,
|
||||
mode=mode,
|
||||
ctp=ctp,
|
||||
mon_margin=mon_margin if isinstance(mon_margin, (int, float)) else None,
|
||||
est_margin=pos_metrics.get("margin"),
|
||||
)
|
||||
if margin and capital > 0:
|
||||
position_pct = round(float(margin) / float(capital) * 100, 2)
|
||||
elif position_pct is None or float(position_pct or 0) <= 0:
|
||||
position_pct = pos_metrics.get("position_pct")
|
||||
elif position_pct is not None:
|
||||
position_pct = float(position_pct)
|
||||
order_st = monitor_order_status(
|
||||
mon or {}, mode=mode, ths_code=sym, direction=direction,
|
||||
|
||||
Reference in New Issue
Block a user