From 590bd5eddcb08f22f541c515fe172f95fab1b0fe Mon Sep 17 00:00:00 2001 From: ZhouYongyou <128128010+zhouyongyou@users.noreply.github.com> Date: Tue, 4 Nov 2025 22:20:59 +0800 Subject: [PATCH] fix(hyperliquid): use Withdrawable field as primary source for available balance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 改进分析 之前的修复V1只是防止负数(设为0),但不够彻底: - 场景:用户有1000 USDC,totalMarginUsed=1050 - V1结果:availableBalance = 0 - 问题:用户想开100 USDT仓位仍会失败 ## 根本原因 Hyperliquid的TotalMarginUsed计算方式与Binance不同: - 可能包含维持保证金要求 - 不能简单用 accountValue - totalMarginUsed ## 正确解决方案 使用Hyperliquid API提供的Withdrawable字段: - 这是官方计算的真实可提现余额 - 已考虑所有持仓风险和保证金要求 - 准确反映用户真实可用资金 ## 实现 1. **优先策略**:使用accountState.Withdrawable字段 2. **后备策略**:Withdrawable不可用时,使用计算值(防负数) 3. **完整日志**:清晰显示使用哪个数据源 ## 参考 - Hyperliquid API文档:withdrawable字段表示可提现余额 - CCXT issues #23997, #26671:类似问题讨论 - 推荐做法:free = withdrawable 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- trader/hyperliquid_trader.go | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/trader/hyperliquid_trader.go b/trader/hyperliquid_trader.go index c59c5722..6acd8205 100644 --- a/trader/hyperliquid_trader.go +++ b/trader/hyperliquid_trader.go @@ -109,17 +109,31 @@ func (t *HyperliquidTrader) GetBalance() (map[string]interface{}, error) { // 需要返回"不包含未实现盈亏的钱包余额" walletBalanceWithoutUnrealized := accountValue - totalUnrealizedPnl - // ⚠️ 计算可用余额,确保不为负数(防止"没钱"误报) - availableBalance := accountValue - totalMarginUsed - if availableBalance < 0 { - log.Printf("⚠️ [Hyperliquid] 计算的可用余额为负 (%.2f - %.2f = %.2f),已调整为0。", - accountValue, totalMarginUsed, availableBalance) - log.Printf(" 提示:这可能是因为Hyperliquid的TotalMarginUsed计算方式不同,或持仓处于高风险状态") - availableBalance = 0 + // ⚠️ 优先使用Withdrawable字段(Hyperliquid API返回的真实可用余额) + availableBalance := 0.0 + if accountState.Withdrawable != "" { + withdrawable, err := strconv.ParseFloat(accountState.Withdrawable, 64) + if err == nil { + availableBalance = withdrawable + log.Printf("✓ 使用Hyperliquid API的Withdrawable字段: %.2f USDT", availableBalance) + } else { + log.Printf("⚠️ 解析Withdrawable字段失败: %v,将使用计算值", err) + } + } + + // 后备方案:如果Withdrawable不可用,使用计算值(确保不为负数) + if availableBalance == 0 && accountState.Withdrawable == "" { + availableBalance = accountValue - totalMarginUsed + if availableBalance < 0 { + log.Printf("⚠️ [Hyperliquid] 计算的可用余额为负 (%.2f - %.2f = %.2f),已调整为0。", + accountValue, totalMarginUsed, availableBalance) + log.Printf(" 提示:这可能是因为Hyperliquid的TotalMarginUsed计算方式不同,或持仓处于高风险状态") + availableBalance = 0 + } } result["totalWalletBalance"] = walletBalanceWithoutUnrealized // 钱包余额(不含未实现盈亏) - result["availableBalance"] = availableBalance // 可用余额(总净值 - 占用保证金,最小为0) + result["availableBalance"] = availableBalance // 可用余额(优先使用Withdrawable,最小为0) result["totalUnrealizedProfit"] = totalUnrealizedPnl // 未实现盈亏 log.Printf("✓ Hyperliquid 账户: 总净值=%.2f (钱包%.2f+未实现%.2f), 可用=%.2f, 保证金占用=%.2f",