Add Binance live trading, anti-stuck open/close recovery, and configurable rate limits.
OKX/Binance LIVE share half_open and option_closed_perp_pending repair paths; private REST throttles default to 1s and are tunable in settings. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -27,15 +27,19 @@ class Ledger:
|
||||
kind: str,
|
||||
group_id: str | None = None,
|
||||
note: str = "",
|
||||
allow_negative: bool = False,
|
||||
) -> float:
|
||||
"""amount>0 入账;amount<0 出账。返回余额。"""
|
||||
"""amount>0 入账;amount<0 出账。返回余额。
|
||||
|
||||
LIVE 实盘成交后本地账本仅作镜像,须 allow_negative=True,避免「交易所已成交、本地拒记」导致卡仓。
|
||||
"""
|
||||
now = int(time.time() * 1000)
|
||||
with self.db._lock:
|
||||
row = self.db._conn.execute("SELECT * FROM ledger_meta WHERE id=1").fetchone()
|
||||
assert row is not None
|
||||
equity = float(row["equity"]) + float(amount)
|
||||
available = float(row["available"]) + float(amount)
|
||||
if available < -1e-9:
|
||||
if not allow_negative and available < -1e-9:
|
||||
raise RuntimeError("可用资金不足")
|
||||
self.db._conn.execute(
|
||||
"UPDATE ledger_meta SET equity=?, available=?, updated_at_ms=? WHERE id=1",
|
||||
|
||||
@@ -21,6 +21,11 @@ from .pricing import (
|
||||
resolve_option_close_bid,
|
||||
)
|
||||
|
||||
# 禁止新开仓的本地仓位状态(实盘防卡)
|
||||
BLOCKING_STATUSES = frozenset(
|
||||
{"open", "half_open", "option_closed_perp_pending"}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class OpenResult:
|
||||
@@ -67,8 +72,15 @@ class Matcher:
|
||||
return dict(row)
|
||||
|
||||
def has_open_position(self) -> bool:
|
||||
"""是否禁止新开:含 open / half_open / option_closed_perp_pending。"""
|
||||
pos = self.current_position()
|
||||
return pos.get("status") == "open" and bool(pos.get("group_id"))
|
||||
st = str(pos.get("status") or "")
|
||||
if st not in BLOCKING_STATUSES:
|
||||
return False
|
||||
return bool(pos.get("group_id") or pos.get("option_inst_id"))
|
||||
|
||||
def position_status(self) -> str:
|
||||
return str(self.current_position().get("status") or "flat")
|
||||
|
||||
def _liquidity_wait(self, group_id: str, detail: str) -> CloseResult:
|
||||
note = f"liquidity_wait:{int(time.time())}:{detail[:80]}"
|
||||
@@ -601,7 +613,9 @@ class Matcher:
|
||||
option_side=option_side, strike=float(strike), spot=float(spot)
|
||||
)
|
||||
|
||||
def close_perp_abandon_option(self, *, reason: str = "target_perp_only") -> CloseResult:
|
||||
def close_perp_abandon_option(
|
||||
self, *, reason: str = "target_perp_only", require_deep_otm: bool = True
|
||||
) -> CloseResult:
|
||||
"""
|
||||
目标平仓 B:只平永续,期权归档为到期残留(不再盯盘、不挡新开)。
|
||||
"""
|
||||
@@ -622,7 +636,7 @@ class Matcher:
|
||||
spot = self._close_spot_px(snap)
|
||||
if strike is None or spot is None:
|
||||
return CloseResult(ok=False, detail="无法判断远虚:缺行权价或标的价")
|
||||
if not is_deep_otm(
|
||||
if require_deep_otm and not is_deep_otm(
|
||||
option_side=option_side, strike=float(strike), spot=float(spot)
|
||||
):
|
||||
return CloseResult(ok=False, detail="期权非远虚,应走双腿全平")
|
||||
|
||||
Reference in New Issue
Block a user