Fix dashboard TP profit display; add options ROI column.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1060,27 +1060,73 @@ def resolve_position_monitor_source(pos: dict, hub_mon: Optional[dict]) -> str:
|
||||
|
||||
|
||||
def resolve_position_reward_at_tp(pos: dict, hub_mon: Optional[dict]) -> Optional[float]:
|
||||
"""与监控区「盈利金额」一致:优先匹配下单监控 reward_at_tp_usdt,否则仓位自身字段."""
|
||||
"""与监控区「盈利金额」一致:有字段用字段,否则按止盈价×张数推算."""
|
||||
sym = str(pos.get("symbol") or "")
|
||||
side = str(pos.get("side") or "")
|
||||
side = str(pos.get("side") or "").lower()
|
||||
if side in ("buy",):
|
||||
side = "long"
|
||||
elif side in ("sell",):
|
||||
side = "short"
|
||||
matched: Optional[dict] = None
|
||||
if isinstance(hub_mon, dict) and hub_mon.get("ok") is not False and sym:
|
||||
# 与前端 findMonitorOrder 一致:先扫 orders
|
||||
for o in hub_mon.get("orders") or []:
|
||||
if isinstance(o, dict) and _monitor_item_matches_position(o, sym, side):
|
||||
for bucket in ("orders", "rolls", "trends"):
|
||||
for o in hub_mon.get(bucket) or []:
|
||||
if not isinstance(o, dict):
|
||||
continue
|
||||
o_sym = o.get("exchange_symbol") or o.get("symbol") or ""
|
||||
if not _symbols_match(sym, str(o_sym)):
|
||||
continue
|
||||
o_side = str(o.get("direction") or "").lower()
|
||||
# 与前端 findMonitorOrder 一致:方向为空也可匹配
|
||||
if o_side and o_side != side:
|
||||
continue
|
||||
matched = o
|
||||
v = _safe_float(o.get("reward_at_tp_usdt"))
|
||||
if v is not None:
|
||||
return v
|
||||
for r in hub_mon.get("rolls") or []:
|
||||
if isinstance(r, dict) and _monitor_item_matches_position(r, sym, side):
|
||||
v = _safe_float(r.get("reward_at_tp_usdt"))
|
||||
if v is not None:
|
||||
return v
|
||||
for t in hub_mon.get("trends") or []:
|
||||
if isinstance(t, dict) and _monitor_item_matches_position(t, sym, side):
|
||||
v = _safe_float(t.get("reward_at_tp_usdt"))
|
||||
if v is not None:
|
||||
return v
|
||||
return _safe_float(pos.get("reward_at_tp_usdt"))
|
||||
break
|
||||
if matched is not None:
|
||||
break
|
||||
|
||||
v = _safe_float(pos.get("reward_at_tp_usdt"))
|
||||
if v is not None:
|
||||
return v
|
||||
|
||||
entry = _safe_float(pos.get("entry_price"))
|
||||
if entry is None and matched is not None:
|
||||
entry = _safe_float(
|
||||
matched.get("avg_entry_price")
|
||||
or matched.get("entry_price")
|
||||
or matched.get("avg_px")
|
||||
)
|
||||
tp = None
|
||||
if matched is not None:
|
||||
tp = _safe_float(matched.get("take_profit"))
|
||||
if tp is None:
|
||||
tp = _safe_float(matched.get("take_profit_display"))
|
||||
if tp is None:
|
||||
tpsl = _resolve_position_tpsl(pos, hub_mon)
|
||||
tp = tpsl.get("tp")
|
||||
contracts = pos.get("contracts")
|
||||
if contracts is None:
|
||||
contracts = pos.get("size")
|
||||
if contracts is None and matched is not None:
|
||||
contracts = matched.get("contracts")
|
||||
try:
|
||||
qty = abs(float(contracts)) if contracts is not None else None
|
||||
except (TypeError, ValueError):
|
||||
qty = None
|
||||
cs = _safe_float(pos.get("contract_size"))
|
||||
if cs is None or cs <= 0:
|
||||
cs = 1.0
|
||||
if entry is None or tp is None or not qty:
|
||||
return None
|
||||
try:
|
||||
from lib.strategy.strategy_roll_ui_lib import reward_at_tp_usdt
|
||||
|
||||
return reward_at_tp_usdt(side or "long", float(entry), float(tp), float(qty), contract_size=float(cs))
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def _options_source_label(p: dict) -> str:
|
||||
|
||||
Reference in New Issue
Block a user