This commit is contained in:
薇薇安 2026-01-18 19:52:30 +08:00
parent e3ecaf1232
commit 69145c4345

View File

@ -978,8 +978,16 @@ class BinanceClient:
# 如果是平仓订单,添加 reduceOnly 参数
# 根据币安API文档reduceOnly 应该是字符串 "true" 或 "false"
if reduce_only:
order_params['reduceOnly'] = "true" # 使用字符串格式符合币安API要求
logger.info(f"{symbol} 使用 reduceOnly=true 平仓订单")
# 实测:某些账户/模式下(尤其是对冲模式 + positionSide会报
# APIError(code=-1106): Parameter 'reduceonly' sent when not required.
# 因此:当我们已经明确指定 positionSide=LONG/SHORT 时,不再传 reduceOnly
# 其余情况仍保留 reduceOnly 以避免反向开仓。
if order_params.get("positionSide") in {"LONG", "SHORT"}:
logger.info(f"{symbol} 对冲模式平仓:已指定 positionSide跳过 reduceOnly避免 -1106")
else:
# python-binance 可以接受 bool同时后面也做 -1106 自动兜底重试
order_params['reduceOnly'] = True
logger.info(f"{symbol} 使用 reduceOnly=true 平仓订单")
async def _submit(params: Dict[str, Any]) -> Dict[str, Any]:
if order_type == 'MARKET':
@ -991,19 +999,31 @@ class BinanceClient:
params['price'] = price
return await self.client.futures_create_order(**params)
# 提交订单;若遇到 -4061则在“带/不带 positionSide”之间做一次兜底重试
# 提交订单;若遇到:
# -4061: positionSide 与账户模式不匹配 → 在“带/不带 positionSide”之间兜底切换重试
# -1106: reduceOnly not required → 去掉 reduceOnly 重试(避免自动平仓失败)
try:
order = await _submit(order_params)
except BinanceAPIException as e:
if getattr(e, "code", None) == -4061:
logger.error(f"{symbol} 触发 -4061持仓模式不匹配尝试自动兜底重试一次")
code = getattr(e, "code", None)
if code in (-4061, -1106):
retry_params = dict(order_params)
if "positionSide" in retry_params:
retry_params.pop("positionSide", None)
else:
ps = await self._resolve_position_side_for_order(symbol, side, reduce_only, position_side)
if ps:
retry_params["positionSide"] = ps
if code == -4061:
logger.error(f"{symbol} 触发 -4061持仓模式不匹配尝试自动兜底重试一次")
if "positionSide" in retry_params:
retry_params.pop("positionSide", None)
else:
ps = await self._resolve_position_side_for_order(symbol, side, reduce_only, position_side)
if ps:
retry_params["positionSide"] = ps
elif code == -1106:
# 常见Parameter 'reduceonly' sent when not required.
msg = str(e).lower()
if "reduceonly" in msg or "reduce only" in msg:
logger.error(f"{symbol} 触发 -1106reduceOnly 不被接受),去掉 reduceOnly 后重试一次")
retry_params.pop("reduceOnly", None)
else:
raise
order = await _submit(retry_params)
else:
raise