# Copyright (c) 2025-2026 马建军. All rights reserved. # 详见 LICENSE.zh-CN.txt """CTP 持仓均价:仅使用柜台持仓回报(vnpy pos.price = PositionCost 加权)。""" from __future__ import annotations from typing import Any, Optional from modules.core.contract_specs import get_contract_spec from modules.ctp.ctp_symbol import ths_to_vnpy_symbol from modules.core.symbols import ths_to_codes def symbols_match(ctp_sym: str, ths: str) -> bool: a = (ctp_sym or "").lower() b = (ths or "").lower() if a == b: return True if a and b and a.split(".")[0] == b.split(".")[0]: return True try: vnpy_sym, _ = ths_to_vnpy_symbol(ths) if a == vnpy_sym.lower(): return True except Exception: pass try: vnpy_sym, _ = ths_to_vnpy_symbol(ctp_sym) if vnpy_sym.lower() == b.split(".")[0]: return True except Exception: pass return False def _ths_code(sym: str) -> str: codes = ths_to_codes(sym) or {} return codes.get("ths_code") or sym def round_to_tick(price: float, sym: str) -> float: tick = float(get_contract_spec(_ths_code(sym)).get("tick_size") or 1.0) if tick <= 0: return round(price, 2) return round(round(price / tick) * tick, 4) def resolve_ctp_entry( sym: str, direction: str, ctp: Optional[dict[str, Any]], trades: Optional[list[dict[str, Any]]] = None, *, tick: Optional[float] = None, ) -> tuple[float, str]: """均价:仅柜台持仓价(trades/tick 参数保留兼容,不参与计算)。""" del direction, trades, tick if not ctp: return 0.0, "none" pos_avg = float(ctp.get("avg_price") or 0) if pos_avg > 0: return round_to_tick(pos_avg, sym), "ctp" return 0.0, "none"