Split exchange and strategy modules for future Binance support.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-25 08:43:09 +08:00
parent 3957a83761
commit e19bb452f9
27 changed files with 1504 additions and 1048 deletions
+19 -19
View File
@@ -7,8 +7,9 @@ from dataclasses import dataclass
from typing import Any
from ..config import get_settings
from ..market import get_gateway
from ..exchange import get_exchange
from ..models.db import Database, get_db
from ..strategy.session import get_session
from .ledger import Ledger
from .liquidity import bid_covers_eth, contracts_for_eth
from .pricing import option_fill, perp_fill
@@ -39,18 +40,11 @@ class Matcher:
return self.ledger.get_setting_float("fee_rate", get_settings().fee_rate)
def _ct_mult(self, option_inst_id: str) -> float:
# 尝试 REST meta;失败用默认
s = get_settings()
try:
gw = get_gateway()
rows = gw.rest.fetch_instruments(inst_type="OPTION", inst_family=s.option_inst_family)
for r in rows:
if str(r.get("instId")) == option_inst_id:
from ..market.instruments import safe_float
m = safe_float(r.get("ctMult"))
if m and m > 0:
return float(m)
return get_exchange().get_ct_mult(
option_inst_id, s.option_inst_family, s.option_ct_mult_default
)
except Exception:
pass
return float(s.option_ct_mult_default)
@@ -77,11 +71,15 @@ class Matcher:
if pos.get("status") == "open" and pos.get("group_id"):
return OpenResult(ok=False, detail="已有持仓组,请先平仓")
gw = get_gateway()
snap = gw.snapshot()
sess = get_session()
snap = sess.snapshot()
if not snap.perp or snap.perp.bid is None or snap.perp.ask is None:
return OpenResult(ok=False, detail="永续盘口不可用")
oq = snap.call if option_side == "call" else snap.put
# 若 ATM 对与持仓合约不一致,直接取持仓合约盘口
held = get_exchange().quote(option_inst_id)
if held and held.ask is not None:
oq = held
if not oq or oq.ask is None:
return OpenResult(ok=False, detail="期权卖一不可用")
@@ -228,14 +226,16 @@ class Matcher:
return CloseResult(ok=False, detail="无持仓可平")
group_id = str(pos["group_id"])
gw = get_gateway()
snap = gw.snapshot()
sess = get_session()
snap = sess.snapshot()
if not snap.perp or snap.perp.bid is None or snap.perp.ask is None:
return CloseResult(ok=False, detail="永续盘口不可用")
option_inst_id = str(pos["option_inst_id"])
option_side = str(pos["option_side"])
oq = snap.call if option_side == "call" else snap.put
oq = get_exchange().quote(option_inst_id) or (
snap.call if option_side == "call" else snap.put
)
if not oq or oq.bid is None:
return CloseResult(ok=False, detail="期权买一不可用", liquidity_wait=True)
@@ -388,8 +388,8 @@ class Matcher:
"move_pct": 0.0,
"premium_gap": None,
}
gw = get_gateway()
snap = gw.snapshot()
sess = get_session()
snap = sess.snapshot()
s = get_settings()
index_px = snap.index_px
if index_px is None and snap.perp:
@@ -415,7 +415,7 @@ class Matcher:
option_side = str(pos["option_side"])
# 优先用持仓合约盘口,避免 ATM 切换后盯错合约
opt_inst = str(pos.get("option_inst_id") or "")
oq = gw.cache.get(opt_inst) if opt_inst else None
oq = get_exchange().quote(opt_inst) if opt_inst else None
if oq is None:
oq = snap.call if option_side == "call" else snap.put
opt_mark = None