+112
-56
@@ -1658,6 +1658,97 @@ def _exchange_tpsl_from_hub_order(hub_orders: list, symbol: str, side: str) -> d
|
||||
return None
|
||||
|
||||
|
||||
def _order_price_op_indexes(order_prices: list) -> tuple[dict, list]:
|
||||
"""price_snapshot order_prices:id 可能为 int/str,需双键索引。"""
|
||||
by_id: dict = {}
|
||||
flat: list = []
|
||||
for op in order_prices:
|
||||
if not isinstance(op, dict):
|
||||
continue
|
||||
flat.append(op)
|
||||
oid = op.get("id")
|
||||
if oid is None:
|
||||
continue
|
||||
by_id[oid] = op
|
||||
by_id[str(oid)] = op
|
||||
try:
|
||||
by_id[int(oid)] = op
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
return by_id, flat
|
||||
|
||||
|
||||
def _match_order_price_op(
|
||||
order_row: dict,
|
||||
by_id: dict,
|
||||
order_prices: list,
|
||||
) -> dict | None:
|
||||
if not isinstance(order_row, dict):
|
||||
return None
|
||||
oid = order_row.get("id")
|
||||
if oid is not None:
|
||||
for key in (oid, str(oid)):
|
||||
op = by_id.get(key)
|
||||
if isinstance(op, dict):
|
||||
return op
|
||||
try:
|
||||
op = by_id.get(int(oid))
|
||||
if isinstance(op, dict):
|
||||
return op
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
sym = order_row.get("exchange_symbol") or order_row.get("symbol") or ""
|
||||
direction = (order_row.get("direction") or "").lower()
|
||||
for op in order_prices:
|
||||
if not isinstance(op, dict):
|
||||
continue
|
||||
if not _symbols_match(sym, op.get("symbol") or ""):
|
||||
continue
|
||||
op_dir = (op.get("direction") or "").lower()
|
||||
if direction and op_dir and direction != op_dir:
|
||||
continue
|
||||
return op
|
||||
return None
|
||||
|
||||
|
||||
_ORDER_PRICE_MERGE_KEYS = (
|
||||
"stop_loss",
|
||||
"take_profit",
|
||||
"stop_loss_display",
|
||||
"take_profit_display",
|
||||
"display_rr_ratio",
|
||||
"latest_risk_amount",
|
||||
"contracts",
|
||||
"exchange_initial_margin",
|
||||
"plan_margin",
|
||||
"time_close_enabled",
|
||||
"time_close_hours",
|
||||
"time_close_at_ms",
|
||||
"time_close_label",
|
||||
"time_close_countdown",
|
||||
"time_close_remaining_sec",
|
||||
)
|
||||
|
||||
|
||||
def _apply_order_price_op_fields(target: dict, op: dict) -> None:
|
||||
if not isinstance(target, dict) or not isinstance(op, dict):
|
||||
return
|
||||
if op.get("rr_ratio") is not None:
|
||||
target["rr_ratio"] = op["rr_ratio"]
|
||||
if "sl_breakeven_secured" in op:
|
||||
target["sl_breakeven_secured"] = bool(op["sl_breakeven_secured"])
|
||||
for key in _ORDER_PRICE_MERGE_KEYS:
|
||||
if key not in op:
|
||||
continue
|
||||
val = op[key]
|
||||
if key == "latest_risk_amount":
|
||||
if val is not None and val != "":
|
||||
target[key] = val
|
||||
continue
|
||||
if val not in (None, ""):
|
||||
target[key] = val
|
||||
|
||||
|
||||
def _find_exchange_tpsl_for_position(
|
||||
symbol: str,
|
||||
side: str,
|
||||
@@ -1665,11 +1756,7 @@ def _find_exchange_tpsl_for_position(
|
||||
hub_orders: list,
|
||||
) -> dict | None:
|
||||
side_l = (side or "").lower()
|
||||
op_by_id = {
|
||||
op.get("id"): op
|
||||
for op in order_prices
|
||||
if isinstance(op, dict) and op.get("id") is not None
|
||||
}
|
||||
by_id, flat = _order_price_op_indexes(order_prices)
|
||||
for o in hub_orders:
|
||||
if not isinstance(o, dict):
|
||||
continue
|
||||
@@ -1678,13 +1765,13 @@ def _find_exchange_tpsl_for_position(
|
||||
continue
|
||||
if (o.get("direction") or "").lower() != side_l:
|
||||
continue
|
||||
op = op_by_id.get(o.get("id"))
|
||||
op = _match_order_price_op(o, by_id, flat)
|
||||
if not isinstance(op, dict):
|
||||
continue
|
||||
et = op.get("exchange_tpsl")
|
||||
if isinstance(et, dict) and (et.get("sl") or et.get("tp")):
|
||||
return et
|
||||
for op in order_prices:
|
||||
for op in flat:
|
||||
if not isinstance(op, dict):
|
||||
continue
|
||||
if not _symbols_match(symbol, op.get("symbol") or ""):
|
||||
@@ -1700,47 +1787,21 @@ def _merge_flask_order_price_fields(hub_mon: dict | None, snap: dict | None) ->
|
||||
if not isinstance(hub_mon, dict) or not isinstance(snap, dict):
|
||||
return
|
||||
order_prices = snap.get("order_prices") or []
|
||||
op_by_id = {
|
||||
op.get("id"): op
|
||||
for op in order_prices
|
||||
if isinstance(op, dict) and op.get("id") is not None
|
||||
}
|
||||
by_id, flat = _order_price_op_indexes(order_prices)
|
||||
orders = hub_mon.get("orders") or []
|
||||
if not isinstance(orders, list):
|
||||
return
|
||||
for o in orders:
|
||||
if not isinstance(o, dict):
|
||||
continue
|
||||
op = op_by_id.get(o.get("id"))
|
||||
op = _match_order_price_op(o, by_id, flat)
|
||||
if not isinstance(op, dict):
|
||||
continue
|
||||
if op.get("rr_ratio") is not None:
|
||||
o["rr_ratio"] = op["rr_ratio"]
|
||||
if "sl_breakeven_secured" in op:
|
||||
o["sl_breakeven_secured"] = bool(op["sl_breakeven_secured"])
|
||||
for key in (
|
||||
"stop_loss",
|
||||
"take_profit",
|
||||
"stop_loss_display",
|
||||
"take_profit_display",
|
||||
"display_rr_ratio",
|
||||
"latest_risk_amount",
|
||||
"contracts",
|
||||
"exchange_initial_margin",
|
||||
"plan_margin",
|
||||
"time_close_enabled",
|
||||
"time_close_hours",
|
||||
"time_close_at_ms",
|
||||
"time_close_label",
|
||||
"time_close_countdown",
|
||||
"time_close_remaining_sec",
|
||||
):
|
||||
if key in op and op[key] not in (None, ""):
|
||||
o[key] = op[key]
|
||||
_apply_order_price_op_fields(o, op)
|
||||
|
||||
|
||||
def _merge_flask_position_breakeven(agent_row: dict, snap: dict | None, hub_mon: dict | None) -> None:
|
||||
"""将 price_snapshot 的已保本状态同步到 agent 持仓,供中控首页表格展示。"""
|
||||
"""将 price_snapshot 的已保本、最新风险、保证金等同步到 agent 持仓。"""
|
||||
ag = agent_row.get("agent")
|
||||
if not isinstance(ag, dict) or not isinstance(snap, dict):
|
||||
return
|
||||
@@ -1748,14 +1809,10 @@ def _merge_flask_position_breakeven(agent_row: dict, snap: dict | None, hub_mon:
|
||||
if not isinstance(positions, list) or not positions:
|
||||
return
|
||||
order_prices = snap.get("order_prices") or []
|
||||
by_id, flat = _order_price_op_indexes(order_prices)
|
||||
hub_orders = []
|
||||
if isinstance(hub_mon, dict):
|
||||
hub_orders = hub_mon.get("orders") or []
|
||||
op_by_id = {
|
||||
op.get("id"): op
|
||||
for op in order_prices
|
||||
if isinstance(op, dict) and op.get("id") is not None
|
||||
}
|
||||
for p in positions:
|
||||
if not isinstance(p, dict):
|
||||
continue
|
||||
@@ -1770,18 +1827,22 @@ def _merge_flask_position_breakeven(agent_row: dict, snap: dict | None, hub_mon:
|
||||
continue
|
||||
if (o.get("direction") or "").lower() != side:
|
||||
continue
|
||||
matched = op_by_id.get(o.get("id"))
|
||||
break
|
||||
matched = _match_order_price_op(o, by_id, flat)
|
||||
if isinstance(matched, dict):
|
||||
break
|
||||
if o.get("latest_risk_amount") is not None or o.get("exchange_initial_margin") is not None:
|
||||
matched = o
|
||||
break
|
||||
if matched is None:
|
||||
for op in order_prices:
|
||||
for op in flat:
|
||||
if not isinstance(op, dict):
|
||||
continue
|
||||
if not _symbols_match(sym, op.get("symbol") or ""):
|
||||
continue
|
||||
matched = op
|
||||
break
|
||||
if isinstance(matched, dict) and "sl_breakeven_secured" in matched:
|
||||
p["sl_breakeven_secured"] = bool(matched["sl_breakeven_secured"])
|
||||
if isinstance(matched, dict):
|
||||
_apply_order_price_op_fields(p, matched)
|
||||
|
||||
|
||||
def _agent_position_has_mark(p: dict) -> bool:
|
||||
@@ -1809,10 +1870,10 @@ def _find_matched_order_price_op(
|
||||
p: dict,
|
||||
order_prices: list,
|
||||
hub_orders: list,
|
||||
op_by_id: dict,
|
||||
) -> dict | None:
|
||||
sym = p.get("symbol") or ""
|
||||
side = (p.get("side") or "").lower()
|
||||
by_id, flat = _order_price_op_indexes(order_prices)
|
||||
for o in hub_orders:
|
||||
if not isinstance(o, dict):
|
||||
continue
|
||||
@@ -1821,11 +1882,11 @@ def _find_matched_order_price_op(
|
||||
continue
|
||||
if (o.get("direction") or "").lower() != side:
|
||||
continue
|
||||
matched = op_by_id.get(o.get("id"))
|
||||
matched = _match_order_price_op(o, by_id, flat)
|
||||
if isinstance(matched, dict):
|
||||
return matched
|
||||
break
|
||||
for op in order_prices:
|
||||
for op in flat:
|
||||
if not isinstance(op, dict):
|
||||
continue
|
||||
if not _symbols_match(sym, op.get("symbol") or ""):
|
||||
@@ -1848,15 +1909,10 @@ def _merge_flask_position_mark_price(
|
||||
hub_orders = []
|
||||
if isinstance(hub_mon, dict):
|
||||
hub_orders = hub_mon.get("orders") or []
|
||||
op_by_id = {
|
||||
op.get("id"): op
|
||||
for op in order_prices
|
||||
if isinstance(op, dict) and op.get("id") is not None
|
||||
}
|
||||
for p in positions:
|
||||
if not isinstance(p, dict) or _agent_position_has_mark(p):
|
||||
continue
|
||||
matched = _find_matched_order_price_op(p, order_prices, hub_orders, op_by_id)
|
||||
matched = _find_matched_order_price_op(p, order_prices, hub_orders)
|
||||
if isinstance(matched, dict):
|
||||
_apply_agent_mark_price(
|
||||
p,
|
||||
|
||||
Reference in New Issue
Block a user