"""成交价与手续费:滑点 = 1×f。""" from __future__ import annotations from dataclasses import asdict, dataclass @dataclass(slots=True) class PriceResult: base_px: float fill_px: float fee: float slip: float notional: float def to_dict(self) -> dict[str, float]: return asdict(self) def option_intrinsic(*, option_side: str, strike: float, spot: float) -> float: """多头期权内在价值(USDT/ETH)。call=max(S−K,0),put=max(K−S,0)。""" s = float(spot) k = float(strike) side = str(option_side).lower().strip() if side in ("call", "c"): return max(s - k, 0.0) if side in ("put", "p"): return max(k - s, 0.0) return 0.0 def resolve_option_close_bid( *, bid: float | None, mark: float | None, intrinsic: float | None, bypass_liquidity: bool, ) -> float | None: """ 平仓用买一价;多头卖出不得低于内在价值(SIM 防到期垃圾盘口)。 bypass 时:买一缺失可用标记/内在价值兜底。 """ candidates: list[float] = [] if bid is not None and bid >= 0: candidates.append(float(bid)) if bypass_liquidity and mark is not None and mark >= 0: candidates.append(float(mark)) if intrinsic is not None and intrinsic >= 0: candidates.append(float(intrinsic)) if not candidates: return None # 常规:有买一时,仍用 max(买一, 内在价值) 抬到合理底价 # bypass:max(买一, 标记, 内在价值) if bypass_liquidity: return max(candidates) if bid is None: return None if intrinsic is not None and intrinsic >= 0: return max(float(bid), float(intrinsic)) return float(bid) def perp_fill( *, side: str, action: str, bid: float, ask: float, qty_eth: float, fee_rate: float, ) -> PriceResult: """ side: long|short(持仓方向意图:开仓要建立的方向 / 平仓时原持仓方向) action: open|close 开多/平空: 吃卖一 ×(1+f) 开空/平多: 吃买一 ×(1-f) """ f = float(fee_rate) buying = (action == "open" and side == "long") or (action == "close" and side == "short") if buying: base = float(ask) fill = base * (1.0 + f) else: base = float(bid) fill = base * (1.0 - f) notional = abs(fill * qty_eth) fee = notional * f slip = abs(fill - base) * qty_eth return PriceResult(base_px=base, fill_px=fill, fee=fee, slip=slip, notional=notional) def option_fill( *, action: str, bid: float, ask: float, qty_eth: float, fee_rate: float, ) -> PriceResult: """开仓买入吃卖一;平仓卖出吃买一。""" f = float(fee_rate) if action == "open": base = float(ask) fill = base * (1.0 + f) else: base = float(bid) fill = base * (1.0 - f) notional = abs(fill * qty_eth) fee = notional * f slip = abs(fill - base) * qty_eth return PriceResult(base_px=base, fill_px=fill, fee=fee, slip=slip, notional=notional)