feat(binance_client, position_manager): 优化对冲模式处理与持仓检查逻辑
在 `binance_client.py` 中增强了对冲模式的处理逻辑,添加了对对冲模式检测失败的处理,确保在尝试单向模式失败后再尝试对冲模式。同时,在 `position_manager.py` 中引入了持仓存在性检查,避免因持仓不存在或方向不匹配导致的错误,提升了系统的稳定性与风险控制能力。
This commit is contained in:
parent
d31c44a22a
commit
bfe3d8ec75
|
|
@ -2472,8 +2472,12 @@ class BinanceClient:
|
|||
}
|
||||
|
||||
# 对冲模式:必须指定 positionSide
|
||||
# ⚠️ 优化:如果对冲模式检测失败(dual is None),先尝试不传 positionSide(单向模式),失败再尝试传 positionSide
|
||||
if dual is True:
|
||||
params["positionSide"] = "LONG" if pd == "BUY" else "SHORT"
|
||||
elif dual is None:
|
||||
# 对冲模式检测失败:先尝试单向模式(不传 positionSide),如果失败再尝试对冲模式
|
||||
logger.debug(f"{symbol} 对冲模式检测失败(dual=None),先尝试单向模式(不传 positionSide)")
|
||||
|
||||
# 走 Algo Order 接口(避免 -4120)
|
||||
order = await self.futures_create_algo_order(params)
|
||||
|
|
@ -2493,7 +2497,8 @@ class BinanceClient:
|
|||
if retry_order:
|
||||
logger.info(f"{symbol} ✓ 重试成功(移除 positionSide)")
|
||||
return retry_order
|
||||
else:
|
||||
elif dual is False:
|
||||
# 单向模式首次失败:尝试添加 positionSide(可能是对冲模式但检测失败)
|
||||
retry = dict(params)
|
||||
retry["positionSide"] = "LONG" if pd == "BUY" else "SHORT"
|
||||
# 关键修复:重试时必须清除之前的 timestamp 和 signature
|
||||
|
|
@ -2504,6 +2509,27 @@ class BinanceClient:
|
|||
if retry_order:
|
||||
logger.info(f"{symbol} ✓ 重试成功(添加 positionSide)")
|
||||
return retry_order
|
||||
elif dual is None:
|
||||
# 对冲模式检测失败:先尝试单向模式失败后,再尝试对冲模式
|
||||
retry = dict(params)
|
||||
if "positionSide" in retry:
|
||||
retry.pop("positionSide", None)
|
||||
retry.pop("timestamp", None)
|
||||
retry.pop("signature", None)
|
||||
logger.debug(f"{symbol} 重试1: 移除 positionSide(对冲模式检测失败 -> 单向模式)")
|
||||
retry_order = await self.futures_create_algo_order(retry)
|
||||
if retry_order:
|
||||
logger.info(f"{symbol} ✓ 重试成功(移除 positionSide)")
|
||||
return retry_order
|
||||
else:
|
||||
retry["positionSide"] = "LONG" if pd == "BUY" else "SHORT"
|
||||
retry.pop("timestamp", None)
|
||||
retry.pop("signature", None)
|
||||
logger.debug(f"{symbol} 重试2: 添加 positionSide={retry['positionSide']}(单向模式失败 -> 对冲模式)")
|
||||
retry_order = await self.futures_create_algo_order(retry)
|
||||
if retry_order:
|
||||
logger.info(f"{symbol} ✓ 重试成功(添加 positionSide)")
|
||||
return retry_order
|
||||
|
||||
# 如果还是失败,记录详细参数用于调试
|
||||
logger.error(f"{symbol} ❌ 所有重试都失败,保护单挂单失败")
|
||||
|
|
|
|||
|
|
@ -1591,6 +1591,25 @@ class PositionManager:
|
|||
except Exception as e:
|
||||
logger.warning(f"{symbol} 验证止损价格时出错: {e}")
|
||||
|
||||
# ⚠️ 关键修复:挂单前先检查持仓是否真的存在,避免 -4509(没有持仓)和 -4061(positionSide 不匹配)
|
||||
try:
|
||||
positions = await self._get_open_positions()
|
||||
live_position = next((p for p in positions if p.get('symbol') == symbol), None)
|
||||
if not live_position:
|
||||
logger.warning(f"{symbol} ⚠️ 持仓已不存在(可能已平仓),跳过挂止损/止盈单,避免 -4509/-4061 错误")
|
||||
return
|
||||
position_amt = float(live_position.get('positionAmt', 0) or 0)
|
||||
if abs(position_amt) <= 0:
|
||||
logger.warning(f"{symbol} ⚠️ 持仓数量为0,跳过挂止损/止盈单")
|
||||
return
|
||||
# 验证持仓方向是否匹配(对冲模式下需要检查 positionSide)
|
||||
live_side = "BUY" if position_amt > 0 else "SELL"
|
||||
if live_side != side:
|
||||
logger.warning(f"{symbol} ⚠️ 持仓方向不匹配(本地记录: {side}, 实际: {live_side}),跳过挂单,避免 -4061")
|
||||
return
|
||||
except Exception as e:
|
||||
logger.warning(f"{symbol} 检查持仓存在性时出错,继续尝试挂单(可能误报): {e}")
|
||||
|
||||
# 防重复:先取消旧的保护单(仅取消特定类型,避免误伤普通挂单)
|
||||
try:
|
||||
await self.client.cancel_open_algo_orders_by_order_types(
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user