feat(binance_client): 优化超时设置与错误处理逻辑

在 `binance_client.py` 中调整了 API 请求的超时设置,首次请求超时为 25 秒,后续请求为 35 秒,以适应币安的响应时间。同时,增加了重试机制的等待时间,首次重试为 4 秒,后续重试为 5 秒,确保在网络波动时能更好地恢复。此外,新增了止盈价合理性校验,避免因错误数据导致的挂单被拒,提升了交易逻辑的稳定性与风险控制能力。
This commit is contained in:
薇薇安 2026-02-20 11:23:11 +08:00
parent 9299d70a31
commit 22830355c6

View File

@ -417,8 +417,8 @@ class BinanceClient:
import aiohttp
url = f"{self._futures_base_url()}/fapi/v1/listenKey"
headers = {"X-MBX-APIKEY": self.api_key}
# ⚠️ 优化使用较短的超时时间15秒失败后快速重试
timeout_sec = 15 if attempt == 0 else 20
# 超时:首次 25s后续 35s币安有时较慢避免 20s 超时)
timeout_sec = 25 if attempt == 0 else 35
async with aiohttp.ClientSession() as session:
async with session.post(url, headers=headers, timeout=aiohttp.ClientTimeout(total=timeout_sec)) as resp:
text = await resp.text()
@ -428,7 +428,7 @@ class BinanceClient:
resp.status, (text[:500] if text else ""), attempt + 1, max_retries + 1,
)
if attempt < max_retries:
await asyncio.sleep(2) # 等待 2 秒后重试
await asyncio.sleep(4) # 等待 4 秒后重试,给币安/网络恢复时间
continue
return None
try:
@ -446,7 +446,7 @@ class BinanceClient:
last_error, attempt + 1, max_retries + 1,
)
if attempt < max_retries:
await asyncio.sleep(2) # 等待 2 秒后重试
await asyncio.sleep(5) # 等待 5 秒后重试
continue
except Exception as e:
last_error = getattr(e, "message", str(e)) or repr(e)
@ -455,7 +455,7 @@ class BinanceClient:
type(e).__name__, last_error, attempt + 1, max_retries + 1,
)
if attempt < max_retries:
await asyncio.sleep(2) # 等待 2 秒后重试
await asyncio.sleep(5) # 等待 5 秒后重试
continue
logger.error(f"create_futures_listen_key (REST) 重试 {max_retries + 1} 次后仍失败: {last_error}")
@ -2420,6 +2420,27 @@ class BinanceClient:
if sp <= 0:
return None
# 触发价合理性:止盈价不能偏离当前价过远(避免错误数据导致挂单被拒或 -4509
if cp and cp > 0 and ttype == "TAKE_PROFIT_MARKET":
if pd == "SELL":
# 做空止盈:触发价应 < 当前价,且不应低于当前价的 1%(避免错用成 0.001 等错误数值)
if sp >= cp:
pass # 下方会做“止盈修正”
elif sp < cp * 0.01:
logger.warning(
f"{symbol} [止盈校验] SELL 止盈价 {sp:.8f} 远低于当前价 {cp:.8f},疑似数据错误,跳过挂单"
)
return None
else:
# 做多止盈:触发价应 > 当前价,且不应超过当前价的 100 倍
if sp <= cp:
pass
elif sp > cp * 100:
logger.warning(
f"{symbol} [止盈校验] BUY 止盈价 {sp:.8f} 远高于当前价 {cp:.8f},疑似数据错误,跳过挂单"
)
return None
# 触发方向约束(避免立即触发):
# - long 止损:价格 <= stopPricestopPrice 应 < current至少差一个 min_step
# - short 止损:价格 >= stopPricestopPrice 应 > current至少差一个 min_step
@ -2509,8 +2530,13 @@ class BinanceClient:
except BinanceAPIException as e:
error_code = e.code if hasattr(e, 'code') else None
error_msg = str(e)
# 详细错误日志
# -4509/-4061持仓已平或方向不匹配仅打一条 warning不刷详细日志
if error_code in (-4509, -4061):
logger.warning(
f"{symbol} 保护单挂单被拒({error_code}): 持仓可能已平或方向不匹配,已跳过"
)
return None
# 其他错误:详细错误日志
logger.error(f"{symbol} ❌ 挂保护单失败({trigger_type}): {error_msg}")
logger.error(f" 错误代码: {error_code}")
logger.error(f" 触发价格: {stop_price:.8f} (格式化后: {stop_price_str})")
@ -2521,7 +2547,7 @@ class BinanceClient:
if symbol_info:
logger.error(f" 价格精度: {pp}, 价格步长: {tick}")
# 常见错误码处理
# 常见错误码说明
if error_code == -4014:
logger.error(f" 原因: 价格步长错误,需要调整到 tickSize 的倍数")
elif error_code == -4164: