feat(binance_client, config): 添加单向持仓模式配置以优化交易逻辑
在 `binance_client.py` 中引入了 `ONE_WAY_POSITION_ONLY` 配置,确保在单向持仓模式下不传递 `positionSide`,避免对冲模式检测。同时,更新了 `config.py`,新增该配置项以支持该功能,提升了交易策略的灵活性与风险控制能力。
This commit is contained in:
parent
bfe3d8ec75
commit
2c5524bdcf
|
|
@ -600,7 +600,13 @@ class BinanceClient:
|
|||
获取币安合约持仓模式:
|
||||
- True: 对冲模式(Hedge Mode,需要下单时传 positionSide=LONG/SHORT)
|
||||
- False: 单向模式(One-way Mode,不应传 positionSide=LONG/SHORT)
|
||||
若配置 ONE_WAY_POSITION_ONLY=True,直接返回 False,不请求 API。
|
||||
"""
|
||||
one_way_only = bool(config.TRADING_CONFIG.get("ONE_WAY_POSITION_ONLY", True))
|
||||
if one_way_only:
|
||||
self._dual_side_position = False
|
||||
return False
|
||||
|
||||
if not self.client:
|
||||
return None
|
||||
|
||||
|
|
@ -2372,11 +2378,13 @@ class BinanceClient:
|
|||
"""
|
||||
try:
|
||||
symbol_info = await self.get_symbol_info(symbol)
|
||||
one_way_only = bool(config.TRADING_CONFIG.get("ONE_WAY_POSITION_ONLY", True))
|
||||
dual = None
|
||||
try:
|
||||
dual = await self._get_dual_side_position()
|
||||
except Exception:
|
||||
dual = None
|
||||
if not one_way_only:
|
||||
try:
|
||||
dual = await self._get_dual_side_position()
|
||||
except Exception:
|
||||
dual = None
|
||||
|
||||
pd = (position_direction or "").upper()
|
||||
if pd not in {"BUY", "SELL"}:
|
||||
|
|
@ -2471,70 +2479,31 @@ class BinanceClient:
|
|||
"closePosition": True,
|
||||
}
|
||||
|
||||
# 对冲模式:必须指定 positionSide
|
||||
# ⚠️ 优化:如果对冲模式检测失败(dual is None),先尝试不传 positionSide(单向模式),失败再尝试传 positionSide
|
||||
if dual is True:
|
||||
# 单向持仓模式(ONE_WAY_POSITION_ONLY):不传 positionSide;否则按检测结果处理
|
||||
if not one_way_only and 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)
|
||||
if order:
|
||||
return order
|
||||
|
||||
# 兜底:对冲/单向模式可能导致 positionSide 误判,尝试切换一次
|
||||
logger.warning(f"{symbol} 首次挂保护单失败,尝试切换 positionSide 重试...")
|
||||
if dual is True:
|
||||
|
||||
# 仅在对冲模式且未配置 ONE_WAY_POSITION_ONLY 时,尝试移除 positionSide 重试一次
|
||||
if not one_way_only and dual is True:
|
||||
logger.warning(f"{symbol} 首次挂保护单失败,尝试移除 positionSide 重试...")
|
||||
retry = dict(params)
|
||||
retry.pop("positionSide", None)
|
||||
# 关键修复:重试时必须清除之前的 timestamp 和 signature
|
||||
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
|
||||
elif dual is False:
|
||||
# 单向模式首次失败:尝试添加 positionSide(可能是对冲模式但检测失败)
|
||||
retry = dict(params)
|
||||
retry["positionSide"] = "LONG" if pd == "BUY" else "SHORT"
|
||||
# 关键修复:重试时必须清除之前的 timestamp 和 signature
|
||||
retry.pop("timestamp", None)
|
||||
retry.pop("signature", None)
|
||||
logger.debug(f"{symbol} 重试1: 添加 positionSide={retry['positionSide']}(单向模式 -> 对冲模式)")
|
||||
retry_order = await self.futures_create_algo_order(retry)
|
||||
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} ❌ 所有重试都失败,保护单挂单失败")
|
||||
|
||||
logger.error(f"{symbol} ❌ 保护单挂单失败")
|
||||
logger.error(f" 参数: {params}")
|
||||
logger.error(f" 对冲模式: {dual}(None 表示无法读取持仓模式,请检查网络或 API 权限)")
|
||||
if not one_way_only:
|
||||
logger.error(f" 对冲模式: {dual}(None 表示无法读取持仓模式,请检查网络或 API 权限)")
|
||||
return None
|
||||
|
||||
except BinanceAPIException as e:
|
||||
|
|
|
|||
|
|
@ -186,6 +186,7 @@ DEFAULT_TRADING_CONFIG = {
|
|||
'AUTO_TRADE_ENABLED': True, # 自动交易总开关
|
||||
'MAX_OPEN_POSITIONS': 4, # 同时持仓数量上限(总仓位12% / 单笔1.5% = 最多4个)
|
||||
'MAX_DAILY_ENTRIES': 15, # 每日最多15笔(快速验证模式:提高上限以快速验证策略)
|
||||
'ONE_WAY_POSITION_ONLY': True, # 账号固定为单向持仓模式,不传 positionSide,不检测对冲模式(避免 -4061)
|
||||
|
||||
'MAX_POSITION_PERCENT': 0.20, # 单笔仓位上限20%(作为风控熔断,实际仓位由固定风险模型决定)
|
||||
'MAX_TOTAL_POSITION_PERCENT': 0.80, # 总仓位80%(避免满仓,留有余地)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user