Files
crypto_monitor/lib/hub/price_snapshot_lib.py
T
2026-07-06 22:19:42 +08:00

125 lines
4.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""price_snapshot 共用:订单行情价兜底,避免 get_price 失败时整单不入 order_prices。"""
from __future__ import annotations
from typing import Any, Callable, Mapping, Optional, Sequence
from lib.hub.hub_position_metrics import parse_position_mark_price
def resolve_order_snapshot_price(
symbol: str,
prices: Mapping[str, float],
*,
position_row: Optional[dict[str, Any]] = None,
order_leverage=None,
parse_position_metrics_fn: Callable[..., dict[str, Any] | None] | None = None,
get_mark_price_fn: Callable[[str], float | None] | None = None,
fallback_entry: float | None = None,
) -> float | None:
"""
解析下单监控轮询用的现价/标记价,优先级:
1. 已批量拉取的 ticker last
2. get_symbol_mark_price(含 mark
3. 交易所持仓 markparse_ccxt_position_metrics / parse_position_mark_price
4. 计划成交价 trigger_price
"""
sym = (symbol or "").strip()
if not sym:
return None
cached = prices.get(sym)
if cached is not None:
try:
v = float(cached)
if v > 0:
return v
except (TypeError, ValueError):
pass
if get_mark_price_fn is not None:
try:
mp = get_mark_price_fn(sym)
if mp is not None and float(mp) > 0:
return float(mp)
except Exception:
pass
if position_row:
mark = None
if parse_position_metrics_fn is not None:
try:
metrics = parse_position_metrics_fn(
position_row, order_leverage=order_leverage
)
if isinstance(metrics, dict) and metrics.get("mark_price") is not None:
mark = float(metrics["mark_price"])
except Exception:
mark = None
if mark is None or mark <= 0:
try:
mp = parse_position_mark_price(position_row)
if mp is not None and mp > 0:
mark = float(mp)
except Exception:
mark = None
if mark is not None and mark > 0:
return mark
if fallback_entry is not None:
try:
entry = float(fallback_entry)
if entry > 0:
return entry
except (TypeError, ValueError):
pass
return None
def seed_prices_from_positions(
prices: dict[str, float],
order_rows: Sequence[Any],
all_positions: Sequence[dict[str, Any]],
*,
resolve_ex_sym_fn: Callable[[Any], str],
) -> None:
"""用持仓标记价补全 prices 字典(symbol 与 order_monitors 行对齐)。"""
if not all_positions or not order_rows:
return
try:
from lib.hub.hub_symbol_lib import symbols_match
except Exception:
symbols_match = None
for r in order_rows:
try:
sym = str(r["symbol"] or "").strip()
except (KeyError, TypeError, IndexError):
sym = ""
if not sym or sym in prices:
continue
try:
ex_sym = resolve_ex_sym_fn(r)
except Exception:
ex_sym = sym
try:
direction = str(r["direction"] or "long").lower()
except (KeyError, TypeError, IndexError):
direction = "long"
for p in all_positions:
if not isinstance(p, dict):
continue
ps = p.get("symbol") or ""
if not ps:
continue
matched = ps == sym or ps == ex_sym
if not matched and symbols_match is not None:
matched = symbols_match(sym, ps) or symbols_match(ex_sym, ps)
if not matched:
continue
side = (p.get("side") or "").lower()
if side and side != direction:
continue
mp = parse_position_mark_price(p)
if mp is not None and mp > 0:
prices[sym] = float(mp)
break