This commit is contained in:
薇薇安 2026-02-25 23:19:48 +08:00
parent ac022bd62a
commit 34e276474a

View File

@ -282,7 +282,7 @@ class BinanceClient:
# 连接前刷新API密钥确保使用最新值支持热更新 # 连接前刷新API密钥确保使用最新值支持热更新
# 但如果 API 密钥为空(只用于获取公开行情),则跳过 # 但如果 API 密钥为空(只用于获取公开行情),则跳过
if self.api_key and self.api_secret: if self.api_key and self.api_secret:
self._refresh_api_credentials() self._refresh_api_credentials()
else: else:
logger.info("BinanceClient: 使用公开 API无需认证只能获取行情数据") logger.info("BinanceClient: 使用公开 API无需认证只能获取行情数据")
@ -322,7 +322,7 @@ class BinanceClient:
# 验证API密钥权限仅当提供了有效的 API key 时) # 验证API密钥权限仅当提供了有效的 API key 时)
if self.api_key and self.api_secret: if self.api_key and self.api_secret:
await self._verify_api_permissions() await self._verify_api_permissions()
else: else:
logger.info("✓ 使用公开 API跳过权限验证只能获取行情数据") logger.info("✓ 使用公开 API跳过权限验证只能获取行情数据")
@ -755,13 +755,13 @@ class BinanceClient:
self._display_to_api_symbol.update(display_to_api) self._display_to_api_symbol.update(display_to_api)
if display_to_api: if display_to_api:
logger.info(f"已映射 {len(display_to_api)} 个中文/非ASCII交易对到英文 symbol均可正常下单") logger.info(f"已映射 {len(display_to_api)} 个中文/非ASCII交易对到英文 symbol均可正常下单")
logger.info(f"获取到 {len(usdt_pairs)} 个USDT永续合约交易对") logger.info(f"获取到 {len(usdt_pairs)} 个USDT永续合约交易对")
# 回写 DB 供下次使用 # 回写 DB 供下次使用
try: try:
await loop.run_in_executor(None, lambda: _save_exchange_info_to_db(exchange_info)) await loop.run_in_executor(None, lambda: _save_exchange_info_to_db(exchange_info))
except Exception as e: except Exception as e:
logger.debug("exchange_info 写入 DB 失败: %s", e) logger.debug("exchange_info 写入 DB 失败: %s", e)
return usdt_pairs return usdt_pairs
except asyncio.TimeoutError: except asyncio.TimeoutError:
if attempt < max_retries: if attempt < max_retries:
@ -772,9 +772,9 @@ class BinanceClient:
logger.error(f"获取交易对失败:{max_retries}次重试后仍然超时") logger.error(f"获取交易对失败:{max_retries}次重试后仍然超时")
return [] return []
except BinanceAPIException as e: except BinanceAPIException as e:
logger.error(f"获取交易对失败API错误: {e}") logger.error(f"获取交易对失败API错误: {e}")
return [] return []
except Exception as e: except Exception as e:
if attempt < max_retries: if attempt < max_retries:
@ -870,7 +870,7 @@ class BinanceClient:
from .market_ws_leader import KEY_KLINE_PREFIX from .market_ws_leader import KEY_KLINE_PREFIX
shared_key = f"{KEY_KLINE_PREFIX}{symbol.upper()}:{interval.lower()}" shared_key = f"{KEY_KLINE_PREFIX}{symbol.upper()}:{interval.lower()}"
# 使用较长的 TTL因为这是共享缓存多个账号都会使用 # 使用较长的 TTL因为这是共享缓存多个账号都会使用
ttl_map = { ttl_map = {
'1m': 60, '3m': 120, '5m': 180, '15m': 300, '30m': 600, '1m': 60, '3m': 120, '5m': 180, '15m': 300, '30m': 600,
'1h': 900, '2h': 1800, '4h': 3600, '6h': 5400, '8h': 7200, '12h': 10800, '1d': 21600 '1h': 900, '2h': 1800, '4h': 3600, '6h': 5400, '8h': 7200, '12h': 10800, '1d': 21600
} }
@ -1292,7 +1292,7 @@ class BinanceClient:
f"获取持仓: 过滤掉 {len(skipped_low)} 个名义价值 < {min_notional} USDT 的仓位 {skipped_low}" f"获取持仓: 过滤掉 {len(skipped_low)} 个名义价值 < {min_notional} USDT 的仓位 {skipped_low}"
"与仪表板不一致时可设 POSITION_MIN_NOTIONAL_USDT=0 或更小" "与仪表板不一致时可设 POSITION_MIN_NOTIONAL_USDT=0 或更小"
) )
return open_positions return open_positions
except (asyncio.TimeoutError, BinanceAPIException) as e: except (asyncio.TimeoutError, BinanceAPIException) as e:
last_error = e last_error = e
# 如果是API异常检查是否是网络相关或服务器错误 # 如果是API异常检查是否是网络相关或服务器错误
@ -1389,7 +1389,7 @@ class BinanceClient:
if isinstance(cached, dict) and ("tickSize" not in cached or "pricePrecision" not in cached): if isinstance(cached, dict) and ("tickSize" not in cached or "pricePrecision" not in cached):
logger.info(f"{symbol} symbol_info 缓存缺少 tickSize/pricePrecision自动刷新一次") logger.info(f"{symbol} symbol_info 缓存缺少 tickSize/pricePrecision自动刷新一次")
else: else:
return cached return cached
# 2. 降级到进程内存(仅当 Redis 不可用时会有数据) # 2. 降级到进程内存(仅当 Redis 不可用时会有数据)
if symbol in self._symbol_info_cache: if symbol in self._symbol_info_cache:
cached_mem = self._symbol_info_cache[symbol] cached_mem = self._symbol_info_cache[symbol]
@ -1873,8 +1873,8 @@ class BinanceClient:
position = positions[0] position = positions[0]
# 优先使用 API 返回的 leverage不再限制必须有持仓 # 优先使用 API 返回的 leverage不再限制必须有持仓
leverage_bracket = position.get('leverage') leverage_bracket = position.get('leverage')
if leverage_bracket: if leverage_bracket:
current_leverage = int(leverage_bracket) current_leverage = int(leverage_bracket)
except Exception as e: except Exception as e:
logger.debug(f"无法获取 {symbol} 的杠杆信息,使用默认值: {current_leverage}x ({e})") logger.debug(f"无法获取 {symbol} 的杠杆信息,使用默认值: {current_leverage}x ({e})")
@ -2099,7 +2099,7 @@ class BinanceClient:
if reduce_only: if reduce_only:
logger.warning(f"下单被拒绝 {symbol} {side}: ReduceOnly(-2022)可能仓位已为0/方向腿不匹配),将由上层做幂等处理") logger.warning(f"下单被拒绝 {symbol} {side}: ReduceOnly(-2022)可能仓位已为0/方向腿不匹配),将由上层做幂等处理")
else: else:
logger.error(f"下单失败 {symbol} {side}: ReduceOnly 订单被拒绝 - {e}") logger.error(f"下单失败 {symbol} {side}: ReduceOnly 订单被拒绝 - {e}")
elif "reduceOnly" in error_msg.lower() or "reduce only" in error_msg.lower(): elif "reduceOnly" in error_msg.lower() or "reduce only" in error_msg.lower():
logger.error(f"下单失败 {symbol} {side}: ReduceOnly 相关错误 - {e}") logger.error(f"下单失败 {symbol} {side}: ReduceOnly 相关错误 - {e}")
logger.error(f" 错误码: {error_code}") logger.error(f" 错误码: {error_code}")
@ -2677,8 +2677,8 @@ class BinanceClient:
else: else:
logger.error(f"设置杠杆请求超时 ({symbol} {target_leverage}x),已重试 2 次仍失败") logger.error(f"设置杠杆请求超时 ({symbol} {target_leverage}x),已重试 2 次仍失败")
return 0 return 0
except BinanceAPIException as e: except BinanceAPIException as e:
error_msg = str(e).lower() error_msg = str(e).lower()
logger.warning(f"设置杠杆 {target_leverage}x 失败: {e},尝试降低杠杆...") logger.warning(f"设置杠杆 {target_leverage}x 失败: {e},尝试降低杠杆...")
# 如果是 leverage 相关错误,尝试降级 # 如果是 leverage 相关错误,尝试降级
if 'leverage' in error_msg or 'invalid' in error_msg or 'max' in error_msg: if 'leverage' in error_msg or 'invalid' in error_msg or 'max' in error_msg:
@ -2687,12 +2687,12 @@ class BinanceClient:
continue continue
try: try:
await self.client.futures_change_leverage(symbol=symbol, leverage=fallback) await self.client.futures_change_leverage(symbol=symbol, leverage=fallback)
logger.warning( logger.warning(
f"{symbol} 杠杆降级成功: {target_leverage}x -> {fallback}x" f"{symbol} 杠杆降级成功: {target_leverage}x -> {fallback}x"
) )
return fallback return fallback
except (TimeoutError, asyncio.TimeoutError, BinanceAPIException): except (TimeoutError, asyncio.TimeoutError, BinanceAPIException):
continue continue
logger.error(f"设置杠杆最终失败: {symbol} (目标: {target_leverage}x)") logger.error(f"设置杠杆最终失败: {symbol} (目标: {target_leverage}x)")
return 0 return 0