From 87e7865cbb1a4075a1db68e36349023988285224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=87=E8=96=87=E5=AE=89?= Date: Wed, 21 Jan 2026 22:48:01 +0800 Subject: [PATCH] a --- trading_system/binance_client.py | 12 +++++-- trading_system/main.py | 60 +++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/trading_system/binance_client.py b/trading_system/binance_client.py index ffc89c6..e84c275 100644 --- a/trading_system/binance_client.py +++ b/trading_system/binance_client.py @@ -552,11 +552,12 @@ class BinanceClient: if usdt_asset: return { + 'ok': True, 'available': float(usdt_asset['availableBalance']), 'total': float(usdt_asset['walletBalance']), 'margin': float(usdt_asset['marginBalance']) } - return {'available': 0.0, 'total': 0.0, 'margin': 0.0} + return {'ok': True, 'available': 0.0, 'total': 0.0, 'margin': 0.0} except BinanceAPIException as e: error_code = e.code if hasattr(e, 'code') else None error_msg = str(e) @@ -599,7 +600,14 @@ class BinanceClient: logger.error("\n".join(lines)) - return {'available': 0.0, 'total': 0.0, 'margin': 0.0} + return { + 'ok': False, + 'available': 0.0, + 'total': 0.0, + 'margin': 0.0, + 'error_code': error_code, + 'error_msg': error_msg, + } async def get_open_positions(self) -> List[Dict]: """ diff --git a/trading_system/main.py b/trading_system/main.py index d3f6967..760756a 100644 --- a/trading_system/main.py +++ b/trading_system/main.py @@ -251,31 +251,51 @@ async def main(): ) await client.connect() - # 2. 检查账户余额 + # 2. 检查账户余额/权限 logger.info("检查账户余额...") balance = await client.get_account_balance() - - if balance['total'] == 0 and balance['available'] == 0: + + # 若底层调用失败(例如 -2015 / -1022 / IP白名单),这里给出明确错误并以 code=2 退出(supervisor 不会反复拉起) + if isinstance(balance, dict) and balance.get("ok") is False: + code = balance.get("error_code") + msg = balance.get("error_msg") or "" logger.error("=" * 60) - logger.error("无法获取账户余额,可能是API权限问题") + logger.error(f"获取账户余额失败(可能是权限/白名单/环境不匹配)。error_code={code}, error={msg}") logger.error("请检查:") - logger.error("1. API密钥是否正确") - logger.error("2. API密钥是否启用了'合约交易'权限") - logger.error("3. IP地址是否在白名单中(如果设置了IP限制)") - logger.error("4. 测试网/生产网环境是否匹配") + logger.error("1) API Key/Secret 是否正确(不要有空格/换行)") + logger.error("2) API Key 是否启用了【合约交易(USDT-M Futures)】权限") + logger.error("3) 若设置了 IP 白名单,请把服务器出口 IP 加进去") + logger.error("4) 测试网/生产网是否匹配(账号的 USE_TESTNET 设置要与 Key 所属环境一致)") logger.error("=" * 60) - return - - logger.info( - f"账户余额: 总余额 {balance['total']:.2f} USDT, " - f"可用余额 {balance['available']:.2f} USDT" - ) - - if balance['available'] <= 0: - logger.error("账户可用余额不足,无法交易") - logger.error(f"总余额: {balance['total']:.2f} USDT") - logger.error("请先充值到合约账户") - return + raise SystemExit(2) + + total = float((balance or {}).get("total") or 0.0) + available = float((balance or {}).get("available") or 0.0) + logger.info(f"账户余额: 总余额 {total:.2f} USDT, 可用余额 {available:.2f} USDT") + + # 若余额为 0:不直接退出,保持进程运行并周期性重试,便于充值后自动恢复 + if available <= 0: + logger.error("=" * 60) + logger.error("账户可用余额不足(<=0),交易策略不会启动,将每 60 秒重试一次余额读取。") + logger.error(f"当前余额: total={total:.2f} USDT, available={available:.2f} USDT") + logger.error("提示:若你确信余额不为 0,但仍显示为 0,请优先检查 API 权限/IP 白名单/测试网配置。") + logger.error("=" * 60) + while True: + await asyncio.sleep(60) + try: + b2 = await client.get_account_balance() + if isinstance(b2, dict) and b2.get("ok") is False: + logger.error(f"余额重试失败:error_code={b2.get('error_code')}, error={b2.get('error_msg')}") + continue + total = float((b2 or {}).get("total") or 0.0) + available = float((b2 or {}).get("available") or 0.0) + logger.info(f"余额重试: total={total:.2f}, available={available:.2f}") + if available > 0: + logger.info("检测到可用余额 > 0,开始启动交易策略。") + break + except Exception as e: + logger.error(f"余额重试异常: {e}", exc_info=True) + continue # 4. 初始化各个模块