diff --git a/trading_system/binance_client.py b/trading_system/binance_client.py index 43b3798..1ef4abb 100644 --- a/trading_system/binance_client.py +++ b/trading_system/binance_client.py @@ -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: diff --git a/trading_system/config.py b/trading_system/config.py index d781cf1..e573455 100644 --- a/trading_system/config.py +++ b/trading_system/config.py @@ -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%(避免满仓,留有余地)