Fix LIVE SoT P0/P1: closing state machine, OO exchange fills, BN balances.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-08-08 15:54:45 +08:00
parent 99e58910d3
commit 8d67f3fc6c
10 changed files with 864 additions and 167 deletions
+59
View File
@@ -356,6 +356,65 @@ class BinanceTradeClient:
return to_usdt(float(upl), "USDT")
return 0.0
def fetch_balances(self) -> dict[str, float | None]:
"""交易侧可用:USDT-M 钱包 USDT + 期权账户 USDT/USDC(尽力而为)。"""
out: dict[str, float | None] = {
"trading_usdt": None,
"trading_usdc": None,
}
try:
rows = self._signed(self._fapi, "GET", "/fapi/v2/balance")
if isinstance(rows, dict):
rows = [rows]
for row in rows or []:
if not isinstance(row, dict):
continue
asset = str(row.get("asset") or "").upper()
avail = safe_float(row.get("availableBalance"))
if avail is None:
avail = safe_float(row.get("balance"))
if asset == "USDT" and avail is not None:
out["trading_usdt"] = float(avail)
elif asset == "USDC" and avail is not None:
# 永续侧 USDC 少见;若有则记
if out["trading_usdc"] is None:
out["trading_usdc"] = float(avail)
except Exception as e:
logger.warning("binance fapi balance failed: %s", e)
try:
data = self._signed(self._eapi, "GET", "/eapi/v1/marginAccount")
asset_list = []
if isinstance(data, dict):
asset_list = data.get("asset") or data.get("assets") or []
if isinstance(asset_list, list):
for row in asset_list:
if not isinstance(row, dict):
continue
asset = str(
row.get("asset") or row.get("currency") or ""
).upper()
avail = (
safe_float(row.get("available"))
or safe_float(row.get("marginBalance"))
or safe_float(row.get("equity"))
)
if asset == "USDT" and avail is not None:
# 期权保证金常用 USDT;与 fapi 取较大可用
cur = out.get("trading_usdt")
out["trading_usdt"] = (
float(avail)
if cur is None
else max(float(cur), float(avail))
)
elif asset == "USDC" and avail is not None:
out["trading_usdc"] = float(avail)
except Exception as e:
logger.warning("binance eapi marginAccount failed: %s", e)
# 币安期权常用 USDT 保证金:eapi 无独立 USDC 时,用 USDT 作为期权侧可用
if out.get("trading_usdt") is not None and out.get("trading_usdc") is None:
out["trading_usdc"] = float(out["trading_usdt"])
return out
def get_perp_pos_sz(self, symbol: str, *, position_side: str | None = None) -> float | None:
"""当前永续绝对持仓(ETH)。"""
try: