fix: sync live TP/SL to position cards after entrust changes
Use exchange TP/SL for display and DB sync on price_snapshot polls, refresh instance UI cells on each tick, and merge live values into hub monitor board. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -146,6 +146,44 @@ def apply_order_live_price_display(
|
||||
return payload
|
||||
|
||||
|
||||
def resolve_live_tpsl_prices(
|
||||
plan_sl: Any,
|
||||
plan_tp: Any,
|
||||
exchange_tpsl: Any,
|
||||
) -> tuple[Optional[float], Optional[float], Optional[float], Optional[float]]:
|
||||
"""返回 (展示用止损, 展示用止盈, 交易所止损, 交易所止盈)。"""
|
||||
ex_sl = ex_tp = None
|
||||
if isinstance(exchange_tpsl, dict):
|
||||
ex_sl = tpsl_slot_trigger_price(exchange_tpsl.get("sl"))
|
||||
ex_tp = tpsl_slot_trigger_price(exchange_tpsl.get("tp"))
|
||||
disp_sl = ex_sl if ex_sl is not None else _positive_float(plan_sl)
|
||||
disp_tp = ex_tp if ex_tp is not None else _positive_float(plan_tp)
|
||||
return disp_sl, disp_tp, ex_sl, ex_tp
|
||||
|
||||
|
||||
def order_monitor_tpsl_needs_sync(
|
||||
plan_sl: Any,
|
||||
plan_tp: Any,
|
||||
exchange_tpsl: Any,
|
||||
*,
|
||||
eps: float = 1e-12,
|
||||
) -> tuple[Optional[float], Optional[float], bool]:
|
||||
"""若交易所 TP/SL 与库中不一致,返回应写回的 (sl, tp) 及是否需更新。"""
|
||||
_, _, ex_sl, ex_tp = resolve_live_tpsl_prices(plan_sl, plan_tp, exchange_tpsl)
|
||||
try:
|
||||
cur_sl = float(plan_sl or 0)
|
||||
cur_tp = float(plan_tp or 0)
|
||||
except (TypeError, ValueError):
|
||||
cur_sl, cur_tp = 0.0, 0.0
|
||||
new_sl = ex_sl if ex_sl is not None else cur_sl
|
||||
new_tp = ex_tp if ex_tp is not None else cur_tp
|
||||
changed = (
|
||||
(ex_sl is not None and abs(new_sl - cur_sl) > eps)
|
||||
or (ex_tp is not None and abs(new_tp - cur_tp) > eps)
|
||||
)
|
||||
return new_sl, new_tp, changed
|
||||
|
||||
|
||||
def apply_order_price_display_fields(
|
||||
payload: dict[str, Any],
|
||||
*,
|
||||
@@ -156,7 +194,10 @@ def apply_order_price_display_fields(
|
||||
take_profit: Any,
|
||||
calc_rr_ratio_fn: Callable[..., Optional[float]],
|
||||
exchange_tpsl: Any = None,
|
||||
format_price_fn: Optional[Callable[[Any, Any], str]] = None,
|
||||
symbol: Any = None,
|
||||
) -> dict[str, Any]:
|
||||
disp_sl, disp_tp, _, _ = resolve_live_tpsl_prices(stop_loss, take_profit, exchange_tpsl)
|
||||
payload["rr_ratio"] = snapshot_rr(
|
||||
calc_rr_ratio_fn,
|
||||
direction,
|
||||
@@ -168,4 +209,19 @@ def apply_order_price_display_fields(
|
||||
payload["sl_breakeven_secured"] = sl_breakeven_from_exchange_tpsl(
|
||||
direction, entry_price, exchange_tpsl
|
||||
)
|
||||
payload["stop_loss"] = disp_sl
|
||||
payload["take_profit"] = disp_tp
|
||||
if disp_sl is not None and disp_tp is not None:
|
||||
payload["display_rr_ratio"] = calc_rr_ratio_fn(
|
||||
direction or "long", entry_price, disp_sl, disp_tp
|
||||
)
|
||||
else:
|
||||
payload["display_rr_ratio"] = None
|
||||
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 "—"
|
||||
)
|
||||
payload["take_profit_display"] = (
|
||||
format_price_fn(symbol, disp_tp) if disp_tp is not None else "—"
|
||||
)
|
||||
return payload
|
||||
|
||||
Reference in New Issue
Block a user