feat: 修改委托后展示最新风险,四所持仓卡增加张数

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-02 22:08:27 +08:00
parent 9d9d0af31e
commit 687a34474d
14 changed files with 505 additions and 5 deletions
+152
View File
@@ -175,6 +175,66 @@ def resolve_live_tpsl_prices(
return disp_sl, disp_tp, ex_sl, ex_tp
def calc_risk_fraction(direction: str, entry_price: Any, stop_loss: Any) -> Optional[float]:
"""|入场-止损|/入场;盈利侧止损返回 0。"""
entry = _positive_float(entry_price)
sl = _positive_float(stop_loss)
if entry is None or sl is None:
return None
d = (direction or "long").strip().lower()
if d == "short":
risk = sl - entry
else:
risk = entry - sl
if risk <= 0:
return 0.0
return risk / entry
def calc_latest_risk_amount(
direction: str,
entry_price: Any,
stop_loss: Any,
*,
margin_capital: Any = None,
leverage: Any = None,
exchange_notional: Any = None,
contracts: Any = None,
contract_size: Any = None,
mark_price: Any = None,
funds_decimals: int = 2,
) -> Optional[float]:
"""按当前止损与持仓名义价值估算最新风险(U)。"""
rf = calc_risk_fraction(direction, entry_price, stop_loss)
if rf is None:
return None
if rf <= 0:
return 0.0
notional = _positive_float(exchange_notional)
if notional is None:
try:
mc = float(margin_capital or 0)
lev = float(leverage or 0)
if mc > 0 and lev > 0:
notional = mc * lev
except (TypeError, ValueError):
pass
if notional is None:
try:
c = abs(float(contracts or 0))
cs = float(contract_size or 1)
if cs <= 0:
cs = 1.0
px = _positive_float(mark_price) or _positive_float(entry_price)
if c > 0 and px is not None:
notional = c * cs * px
except (TypeError, ValueError):
pass
if notional is None or notional <= 0:
return None
return round(notional * rf, funds_decimals)
def order_monitor_tpsl_needs_sync(
plan_sl: Any,
plan_tp: Any,
@@ -210,8 +270,17 @@ def apply_order_price_display_fields(
exchange_tpsl: Any = None,
format_price_fn: Optional[Callable[[Any, Any], str]] = None,
symbol: Any = None,
margin_capital: Any = None,
leverage: Any = None,
exchange_notional: Any = None,
contracts: Any = None,
contract_size: Any = None,
mark_price: Any = None,
funds_decimals: int = 2,
) -> dict[str, Any]:
disp_sl, disp_tp, _, _ = resolve_live_tpsl_prices(stop_loss, take_profit, exchange_tpsl)
payload["stop_loss_raw"] = _positive_float(stop_loss)
payload["take_profit_raw"] = _positive_float(take_profit)
payload["rr_ratio"] = snapshot_rr(
calc_rr_ratio_fn,
direction,
@@ -231,6 +300,25 @@ def apply_order_price_display_fields(
)
else:
payload["display_rr_ratio"] = None
if contracts is not None:
try:
c = abs(float(contracts))
if c > 0:
payload["contracts"] = c
except (TypeError, ValueError):
pass
payload["latest_risk_amount"] = calc_latest_risk_amount(
direction,
entry_price,
disp_sl if disp_sl is not None else stop_loss,
margin_capital=margin_capital,
leverage=leverage,
exchange_notional=exchange_notional,
contracts=payload.get("contracts") if payload.get("contracts") is not None else contracts,
contract_size=contract_size,
mark_price=mark_price,
funds_decimals=funds_decimals,
)
if format_price_fn is not None and symbol is not None:
payload["stop_loss_display"] = (
format_price_fn(symbol, disp_sl) if disp_sl is not None else ""
@@ -239,3 +327,67 @@ def apply_order_price_display_fields(
format_price_fn(symbol, disp_tp) if disp_tp is not None else ""
)
return payload
def enrich_active_monitor_tpsl_json(
row: Any,
stop_loss: Any,
take_profit: Any,
exchange_tpsl: Any,
*,
position_row: Any = None,
exchange_notional: Any = None,
contracts: Any = None,
contract_size: float = 1.0,
mark_price: Any = None,
calc_rr_ratio_fn: Callable[..., Optional[float]],
format_price_fn: Optional[Callable[[Any, Any], str]] = None,
symbol: Any = None,
funds_decimals: int = 2,
) -> dict[str, Any]:
"""place_tpsl 响应:展示用 TP/SL、最新风险、当前盈亏比。"""
def _row_val(key: str, default=None):
try:
if hasattr(row, "keys") and key in row.keys():
return row[key]
except Exception:
pass
if isinstance(row, dict):
return row.get(key, default)
return default
direction = _row_val("direction") or "long"
entry = _row_val("trigger_price")
init_sl = _row_val("initial_stop_loss")
margin = _row_val("margin_capital")
leverage = _row_val("leverage")
if position_row is not None:
from lib.hub.hub_position_metrics import position_contracts
live_c = position_contracts(position_row)
if abs(live_c) >= 1e-12:
contracts = abs(live_c)
payload: dict[str, Any] = {
"stop_loss": stop_loss,
"take_profit": take_profit,
}
apply_order_price_display_fields(
payload,
direction=direction,
entry_price=entry,
initial_stop_loss=init_sl,
stop_loss=stop_loss,
take_profit=take_profit,
calc_rr_ratio_fn=calc_rr_ratio_fn,
exchange_tpsl=exchange_tpsl,
format_price_fn=format_price_fn,
symbol=symbol or _row_val("symbol"),
margin_capital=margin,
leverage=leverage,
exchange_notional=exchange_notional,
contracts=contracts,
contract_size=contract_size,
mark_price=mark_price,
funds_decimals=funds_decimals,
)
return payload