feat(binance_client): 优化超时设置与错误处理逻辑
在 `binance_client.py` 中调整了 API 请求的超时设置,首次请求超时为 25 秒,后续请求为 35 秒,以适应币安的响应时间。同时,增加了重试机制的等待时间,首次重试为 4 秒,后续重试为 5 秒,确保在网络波动时能更好地恢复。此外,新增了止盈价合理性校验,避免因错误数据导致的挂单被拒,提升了交易逻辑的稳定性与风险控制能力。
This commit is contained in:
parent
9299d70a31
commit
22830355c6
|
|
@ -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 止损:价格 <= stopPrice(stopPrice 应 < current,至少差一个 min_step)
|
||||
# - short 止损:价格 >= stopPrice(stopPrice 应 > 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:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user