diff --git a/crypto_monitor_binance/app.py b/crypto_monitor_binance/app.py index baa4a76..e77a41b 100644 --- a/crypto_monitor_binance/app.py +++ b/crypto_monitor_binance/app.py @@ -2599,23 +2599,65 @@ def exchange_private_api_configured(): return bool(BINANCE_API_KEY and BINANCE_API_SECRET) +def _float_balance_field(val): + if val is None or val == "": + return None + try: + return float(val) + except (TypeError, ValueError): + return None + + def _extract_usdt_total(balance): usdt_info = balance.get("USDT", {}) if isinstance(balance, dict) else {} total_map = balance.get("total", {}) if isinstance(balance, dict) else {} free_map = balance.get("free", {}) if isinstance(balance, dict) else {} + used_map = balance.get("used", {}) if isinstance(balance, dict) else {} total = usdt_info.get("total") if total is None: total = usdt_info.get("equity") if total is None: total = total_map.get("USDT") - if total is None: - total = usdt_info.get("free") - if total is None: - total = free_map.get("USDT") - try: - return float(total) if total is not None else None - except Exception: + if total is not None: + fv = _float_balance_field(total) + if fv is not None: + return fv + free = usdt_info.get("free") + if free is None: + free = free_map.get("USDT") + used = usdt_info.get("used") + if used is None: + used = used_map.get("USDT") + if used is None: + used = usdt_info.get("locked") + free_f = _float_balance_field(free) + used_f = _float_balance_field(used) or 0.0 + if free_f is not None: + return free_f + used_f + return None + + +def _parse_binance_funding_asset_rows(rows): + """解析 /sapi/v1/asset/get-funding-asset:USDT 总额 = free + freeze + locked + withdrawing。""" + if isinstance(rows, dict): + rows = [rows] + if not isinstance(rows, list): return None + for row in rows: + if not isinstance(row, dict): + continue + if str(row.get("asset") or "").upper() != "USDT": + continue + parts = [ + _float_balance_field(row.get("free")), + _float_balance_field(row.get("freeze")), + _float_balance_field(row.get("locked")), + _float_balance_field(row.get("withdrawing")), + ] + nums = [p for p in parts if p is not None] + if nums: + return sum(nums) + return None def _extract_usdt_free(balance): @@ -2690,7 +2732,7 @@ def _fetch_binance_swap_usdt_free(): def _fetch_binance_funding_usdt(): - """Binance 资金账户(Funding Wallet)USDT 总额。""" + """Binance 资金账户(Funding Wallet)USDT 总额(free+冻结+锁定,与 APP 资金账户一致)。""" try: ensure_markets_loaded() bal = exchange.fetch_balance(params={"type": "funding"}) @@ -2699,6 +2741,22 @@ def _fetch_binance_funding_usdt(): return float(val) except Exception: pass + try: + ensure_markets_loaded() + raw = exchange.sapiPostAssetGetFundingAsset({"asset": "USDT"}) + val = _parse_binance_funding_asset_rows(raw) + if val is not None: + return float(val) + except Exception: + pass + try: + ensure_markets_loaded() + raw = exchange.sapiPostAssetGetFundingAsset({}) + val = _parse_binance_funding_asset_rows(raw) + if val is not None: + return float(val) + except Exception: + pass return None