021b0d0a22
Co-authored-by: Cursor <cursoragent@cursor.com>
138 lines
3.7 KiB
Python
138 lines
3.7 KiB
Python
"""成交价与手续费:滑点 = 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 is_deep_otm(
|
||
*,
|
||
option_side: str,
|
||
strike: float,
|
||
spot: float,
|
||
max_intrinsic: float = 0.01,
|
||
) -> bool:
|
||
"""
|
||
远虚:内在价值≈0(多头期权已无行权价值)。
|
||
100×杠杆 ATM 在标的波动约1%后常落入此状态。
|
||
"""
|
||
return option_intrinsic(
|
||
option_side=option_side, strike=strike, spot=spot
|
||
) <= float(max_intrinsic)
|
||
|
||
|
||
def option_expiry_settle(
|
||
*,
|
||
intrinsic: float,
|
||
qty_eth: float,
|
||
fee_rate: float,
|
||
) -> PriceResult:
|
||
"""到期结算:按内在价值入账(对齐实盘),无买卖价差滑点,仅扣手续费。"""
|
||
base = max(float(intrinsic), 0.0)
|
||
fill = base
|
||
f = float(fee_rate)
|
||
notional = abs(fill * float(qty_eth))
|
||
fee = notional * f
|
||
return PriceResult(base_px=base, fill_px=fill, fee=fee, slip=0.0, notional=notional)
|
||
|
||
|
||
def resolve_option_close_bid(
|
||
*,
|
||
bid: float | None,
|
||
mark: float | None,
|
||
intrinsic: float | None,
|
||
bypass_liquidity: bool,
|
||
) -> float | None:
|
||
"""
|
||
非到期平仓价(SIM)。
|
||
- 常规:买一,且多头卖出不低于内在价值。
|
||
- 紧急 bypass:对齐 OKX 市价卖,**只按买一**(不用标记/内在价值抬价;
|
||
标记无法在交易所成交)。bypass 只绕过深度/偏差闸门。
|
||
到期请用 option_expiry_settle,不要走本函数。
|
||
"""
|
||
_ = mark # 保留参数兼容调用方;紧急不再用标记定价
|
||
if bypass_liquidity:
|
||
if bid is None or bid < 0:
|
||
return None
|
||
return float(bid)
|
||
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)
|