mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-12 15:26:55 +08:00
fix: 修复InitialBalance配置错误导致的P&L统计不准确问题
用户在使用Aster交易员时发现,即使没有开始交易,P&L统计也显示了12.5 USDT (83.33%)的盈亏。经过调查发现: **根本原因**: - 实际Aster账户余额:27.5 USDT - Web界面配置的InitialBalance:15 USDT ❌ - 错误的P&L计算:27.5 - 15 = 12.5 USDT (83.33%) **问题根源**: 1. Web界面创建交易员时默认initial_balance为1000 USDT 2. 用户手动修改时容易输入错误的值 3. 缺少自动获取实际余额的功能 4. 缺少明确的警告提示 **文件**: `trader/aster_trader.go` - ✅ 验证Aster API完全兼容Binance格式 - 添加详细的注释说明字段含义 - 添加调试日志以便排查问题 - 确认balance字段不包含未实现盈亏(与Binance一致) **关键确认**: ```go // ✅ Aster API完全兼容Binance API格式 // balance字段 = wallet balance(不包含未实现盈亏) // crossUnPnl = unrealized profit(未实现盈亏) // crossWalletBalance = balance + crossUnPnl(全仓钱包余额,包含盈亏) ``` **文件**: `web/src/components/TraderConfigModal.tsx` **新增功能**: 1. **编辑模式**:添加"获取当前余额"按钮 - 一键从交易所API获取当前账户净值 - 自动填充到InitialBalance字段 - 显示加载状态和错误提示 2. **创建模式**:添加警告提示 - ⚠️ 提醒用户必须输入交易所的当前实际余额 - 警告:如果输入不准确,P&L统计将会错误 3. **改进输入体验**: - 支持小数输入(step="0.01") - 必填字段标记(创建模式) - 实时错误提示 **代码实现**: ```typescript const handleFetchCurrentBalance = async () => { const response = await fetch(`/api/account?trader_id=${traderData.trader_id}`); const data = await response.json(); const currentBalance = data.total_equity; // 当前净值 setFormData(prev => ({ ...prev, initial_balance: currentBalance })); }; ``` 通过查阅Binance官方文档确认: | 项目 | Binance | Aster (修复后) | |------|---------|----------------| | **余额字段** | balance = 钱包余额(不含盈亏) | ✅ 相同 | | **盈亏字段** | crossUnPnl = 未实现盈亏 | ✅ 相同 | | **总权益** | balance + crossUnPnl | ✅ 相同 | | **P&L计算** | totalEquity - initialBalance | ✅ 相同 | 1. 编辑交易员配置 2. 点击"获取当前余额"按钮 3. 系统自动填充正确的InitialBalance 4. 保存配置 1. 查看交易所账户的实际余额 2. 准确输入到InitialBalance字段 3. 注意查看警告提示 4. 完成创建 - [x] 确认Aster API返回格式与Binance一致 - [x] 验证"获取当前余额"功能正常工作 - [x] 确认P&L计算公式正确 - [x] 前端构建成功 - [x] 警告提示正常显示 - **修复**: 解决InitialBalance配置错误导致的P&L统计不准确问题 - **改进**: 提升用户体验,减少配置错误 - **兼容**: 完全向后兼容,不影响现有功能 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: tinkle-community <tinklefund@gmail.com>
This commit is contained in:
@@ -438,13 +438,23 @@ func (t *AsterTrader) GetBalance() (map[string]interface{}, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 🔍 调试:打印原始API响应
|
||||
log.Printf("🔍 Aster API原始响应: %s", string(body))
|
||||
|
||||
// 查找USDT余额
|
||||
totalBalance := 0.0
|
||||
availableBalance := 0.0
|
||||
crossUnPnl := 0.0
|
||||
|
||||
for _, bal := range balances {
|
||||
// 🔍 调试:打印每条余额记录
|
||||
log.Printf("🔍 余额记录: %+v", bal)
|
||||
|
||||
if asset, ok := bal["asset"].(string); ok && asset == "USDT" {
|
||||
// 🔍 调试:打印USDT余额详情
|
||||
log.Printf("🔍 USDT余额详情: balance=%v, availableBalance=%v, crossUnPnl=%v",
|
||||
bal["balance"], bal["availableBalance"], bal["crossUnPnl"])
|
||||
|
||||
if wb, ok := bal["balance"].(string); ok {
|
||||
totalBalance, _ = strconv.ParseFloat(wb, 64)
|
||||
}
|
||||
@@ -458,11 +468,25 @@ func (t *AsterTrader) GetBalance() (map[string]interface{}, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ Aster API完全兼容Binance API格式
|
||||
// balance字段 = wallet balance(不包含未实现盈亏)
|
||||
// crossUnPnl = unrealized profit(未实现盈亏)
|
||||
// crossWalletBalance = balance + crossUnPnl(全仓钱包余额,包含盈亏)
|
||||
//
|
||||
// 参考Binance官方文档:
|
||||
// - Account Information V2: marginBalance = walletBalance + unrealizedProfit
|
||||
// - Balance V3: crossWalletBalance = balance + crossUnPnl
|
||||
|
||||
log.Printf("✓ Aster API返回: 钱包余额=%.2f, 未实现盈亏=%.2f, 可用余额=%.2f",
|
||||
totalBalance,
|
||||
crossUnPnl,
|
||||
availableBalance)
|
||||
|
||||
// 返回与Binance相同的字段名,确保AutoTrader能正确解析
|
||||
return map[string]interface{}{
|
||||
"totalWalletBalance": totalBalance,
|
||||
"totalWalletBalance": totalBalance, // 钱包余额(不含未实现盈亏)
|
||||
"availableBalance": availableBalance,
|
||||
"totalUnrealizedProfit": crossUnPnl,
|
||||
"totalUnrealizedProfit": crossUnPnl, // 未实现盈亏
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user