From 47f34f75a21f14bebba9d03aa67320a410ff6e1f Mon Sep 17 00:00:00 2001 From: CoderMageFox Date: Wed, 5 Nov 2025 12:37:04 +0800 Subject: [PATCH 1/5] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DInitialBalance?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E9=94=99=E8=AF=AF=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?P&L=E7=BB=9F=E8=AE=A1=E4=B8=8D=E5=87=86=E7=A1=AE=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户在使用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: Claude --- trader/aster_trader.go | 28 ++++++++- web/src/components/TraderConfigModal.tsx | 76 ++++++++++++++++++++++-- 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/trader/aster_trader.go b/trader/aster_trader.go index d9ba82a6..15128e13 100644 --- a/trader/aster_trader.go +++ b/trader/aster_trader.go @@ -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 } diff --git a/web/src/components/TraderConfigModal.tsx b/web/src/components/TraderConfigModal.tsx index f96c9070..e0c7c0bf 100644 --- a/web/src/components/TraderConfigModal.tsx +++ b/web/src/components/TraderConfigModal.tsx @@ -68,6 +68,8 @@ export function TraderConfigModal({ const [selectedCoins, setSelectedCoins] = useState([]) const [showCoinSelector, setShowCoinSelector] = useState(false) const [promptTemplates, setPromptTemplates] = useState<{ name: string }[]>([]) + const [isFetchingBalance, setIsFetchingBalance] = useState(false) + const [balanceFetchError, setBalanceFetchError] = useState('') useEffect(() => { if (traderData) { @@ -182,6 +184,45 @@ export function TraderConfigModal({ }) } + const handleFetchCurrentBalance = async () => { + if (!isEditMode || !traderData?.trader_id) { + setBalanceFetchError('只有在编辑模式下才能获取当前余额'); + return; + } + + setIsFetchingBalance(true); + setBalanceFetchError(''); + + try { + const token = localStorage.getItem('token'); + const response = await fetch(`/api/account?trader_id=${traderData.trader_id}`, { + headers: { + 'Authorization': `Bearer ${token}` + } + }); + + if (!response.ok) { + throw new Error('获取账户余额失败'); + } + + const data = await response.json(); + + // total_equity = 当前账户净值(包含未实现盈亏) + // 这应该作为新的初始余额 + const currentBalance = data.total_equity || data.balance || 0; + + setFormData(prev => ({ ...prev, initial_balance: currentBalance })); + + // 显示成功提示 + console.log('已获取当前余额:', currentBalance); + } catch (error) { + console.error('获取余额失败:', error); + setBalanceFetchError('获取余额失败,请检查网络连接'); + } finally { + setIsFetchingBalance(false); + } + }; + const handleSave = async () => { if (!onSave) return @@ -346,9 +387,22 @@ export function TraderConfigModal({
- +
+ + {isEditMode && ( + + )} +
+ {!isEditMode && ( +

+ + 请输入您交易所账户的当前实际余额。如果输入不准确,P&L统计将会错误。 +

+ )} + {isEditMode && ( +

+ 点击"获取当前余额"按钮可自动获取您交易所账户的当前净值 +

+ )} + {balanceFetchError && ( +

{balanceFetchError}

+ )}
From a03e4269ce5d781c015fa47097394856d770b9b6 Mon Sep 17 00:00:00 2001 From: CoderMageFox Date: Wed, 5 Nov 2025 13:03:41 +0800 Subject: [PATCH 2/5] feat: add help tooltips for Aster exchange configuration fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added interactive help icons with tooltips for Aster exchange fields (user, signer, privateKey) to guide users through correct configuration. Changes: - Added HelpCircle icon from lucide-react - Created reusable Tooltip component with hover/click interaction - Added bilingual help descriptions in translations.ts - User field: explains main wallet address (login address) - Signer field: explains API wallet address generation - Private Key field: clarifies local-only usage, never transmitted This prevents user confusion and configuration errors when setting up Aster exchange. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- web/src/components/AITradersPage.tsx | 70 ++++++++++++++++++++++++++-- web/src/i18n/translations.ts | 14 +++++- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/web/src/components/AITradersPage.tsx b/web/src/components/AITradersPage.tsx index e1c73699..f3d4353e 100644 --- a/web/src/components/AITradersPage.tsx +++ b/web/src/components/AITradersPage.tsx @@ -23,6 +23,7 @@ import { Users, AlertTriangle, BookOpen, + HelpCircle, } from 'lucide-react' // 获取友好的AI模型名称 @@ -1064,6 +1065,51 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) { ) } +// Tooltip Helper Component +function Tooltip({ + content, + children, +}: { + content: string + children: React.ReactNode +}) { + const [show, setShow] = useState(false) + + return ( +
+
setShow(true)} + onMouseLeave={() => setShow(false)} + onClick={() => setShow(!show)} + > + {children} +
+ {show && ( +
+ {content} +
+
+ )} +
+ ) +} + // Signal Source Configuration Modal Component function SignalSourceModal({ coinPoolUrl, @@ -1772,10 +1818,16 @@ function ExchangeConfigModal({ <>
Date: Wed, 5 Nov 2025 13:15:49 +0800 Subject: [PATCH 3/5] feat: add USDT warning for Aster exchange configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added warning message to inform users that Aster only tracks USDT balance, preventing P&L calculation errors from asset price fluctuations. Why this is important: - Aster trader only tracks USDT balance (aster_trader.go:453) - If users use BNB/ETH as margin, price fluctuations will cause: * Initial balance becomes inaccurate * P&L statistics will be wrong * Example: 10 BNB @ $100 = $1000, if BNB drops to $90, real equity is $900 but system still shows $1000 Changes: - Added asterUsdtWarning translation in both EN and ZH - Added red warning box below Aster private key field - Clear message: "Please use USDT as margin currency" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- web/src/components/AITradersPage.tsx | 20 ++++++++++++++++++++ web/src/i18n/translations.ts | 4 ++++ 2 files changed, 24 insertions(+) diff --git a/web/src/components/AITradersPage.tsx b/web/src/components/AITradersPage.tsx index f3d4353e..03912051 100644 --- a/web/src/components/AITradersPage.tsx +++ b/web/src/components/AITradersPage.tsx @@ -1899,6 +1899,26 @@ function ExchangeConfigModal({ required />
+ + {/* USDT 警告提示 */} +
+
+ + {t('securityWarning', language)} +
+
+ {t('asterUsdtWarning', language)} +
+
)} diff --git a/web/src/i18n/translations.ts b/web/src/i18n/translations.ts index 5322cd72..25eb75d5 100644 --- a/web/src/i18n/translations.ts +++ b/web/src/i18n/translations.ts @@ -203,6 +203,8 @@ export const translations = { 'API wallet address - Generate from Aster API Wallet page', asterPrivateKeyDesc: 'API wallet private key - Only used locally for signing, never transmitted', + asterUsdtWarning: + 'Important: Aster only tracks USDT balance. Please ensure you use USDT as margin currency to avoid P&L calculation errors caused by price fluctuations of other assets (BNB, ETH, etc.)', testnetDescription: 'Enable to connect to exchange test environment for simulated trading', securityWarning: 'Security Warning', @@ -670,6 +672,8 @@ export const translations = { 'API 钱包地址 - 从 Aster API 钱包页面生成', asterPrivateKeyDesc: 'API 钱包私钥 - 仅在本地用于签名,不会被传输', + asterUsdtWarning: + '重要提示:Aster 仅统计 USDT 余额。请确保您使用 USDT 作为保证金币种,避免其他资产(BNB、ETH等)的价格波动导致盈亏统计错误', testnetDescription: '启用后将连接到交易所测试环境,用于模拟交易', securityWarning: '安全提示', saveConfiguration: '保存配置', From cf2314c2666003402af7d97a992aafb5e174df66 Mon Sep 17 00:00:00 2001 From: CoderMageFox Date: Wed, 5 Nov 2025 13:19:39 +0800 Subject: [PATCH 4/5] refactor: merge USDT warning into security warning box MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merged standalone USDT warning into existing security warning section for cleaner UI. Changes: - Removed separate red warning box for USDT - Added USDT warning as first item in security warning box (conditional on Aster exchange) - Now shows 4 warnings for Aster: USDT requirement + 3 general security warnings - Cleaner, more organized warning presentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- web/src/components/AITradersPage.tsx | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/web/src/components/AITradersPage.tsx b/web/src/components/AITradersPage.tsx index 03912051..a19e7097 100644 --- a/web/src/components/AITradersPage.tsx +++ b/web/src/components/AITradersPage.tsx @@ -1899,26 +1899,6 @@ function ExchangeConfigModal({ required />
- - {/* USDT 警告提示 */} -
-
- - {t('securityWarning', language)} -
-
- {t('asterUsdtWarning', language)} -
-
)} @@ -1957,6 +1937,9 @@ function ExchangeConfigModal({
+ {selectedExchange.id === 'aster' && ( +
{t('asterUsdtWarning', language)}
+ )}
{t('exchangeConfigWarning1', language)}
{t('exchangeConfigWarning2', language)}
{t('exchangeConfigWarning3', language)}
From ba31078d92c5c2ae9b8d9b7de692293fc04c1aa5 Mon Sep 17 00:00:00 2001 From: CoderMageFox Date: Wed, 5 Nov 2025 13:26:05 +0800 Subject: [PATCH 5/5] feat: add Aster API wallet links to help tooltips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added direct links to Aster API wallet page in help tooltips for easier access. Changes: - Added English link: https://www.asterdex.com/en/api-wallet - Added Chinese link: https://www.asterdex.com/zh-CN/api-wallet - Updated asterSignerDesc with API wallet URL - Updated asterPrivateKeyDesc with API wallet URL and security note - Users can now directly access the API wallet page from tooltips 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- web/src/i18n/translations.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/src/i18n/translations.ts b/web/src/i18n/translations.ts index 25eb75d5..a48b96b1 100644 --- a/web/src/i18n/translations.ts +++ b/web/src/i18n/translations.ts @@ -200,9 +200,9 @@ export const translations = { asterUserDesc: 'Main wallet address - The EVM wallet address you use to log in to Aster', asterSignerDesc: - 'API wallet address - Generate from Aster API Wallet page', + 'API wallet address - Generate from https://www.asterdex.com/en/api-wallet', asterPrivateKeyDesc: - 'API wallet private key - Only used locally for signing, never transmitted', + 'API wallet private key - Get from https://www.asterdex.com/en/api-wallet (only used locally for signing, never transmitted)', asterUsdtWarning: 'Important: Aster only tracks USDT balance. Please ensure you use USDT as margin currency to avoid P&L calculation errors caused by price fluctuations of other assets (BNB, ETH, etc.)', testnetDescription: @@ -669,9 +669,9 @@ export const translations = { asterUserDesc: '主钱包地址 - 您用于登录 Aster 的 EVM 钱包地址', asterSignerDesc: - 'API 钱包地址 - 从 Aster API 钱包页面生成', + 'API 钱包地址 - 从 https://www.asterdex.com/zh-CN/api-wallet 生成', asterPrivateKeyDesc: - 'API 钱包私钥 - 仅在本地用于签名,不会被传输', + 'API 钱包私钥 - 从 https://www.asterdex.com/zh-CN/api-wallet 获取(仅在本地用于签名,不会被传输)', asterUsdtWarning: '重要提示:Aster 仅统计 USDT 余额。请确保您使用 USDT 作为保证金币种,避免其他资产(BNB、ETH等)的价格波动导致盈亏统计错误', testnetDescription: '启用后将连接到交易所测试环境,用于模拟交易',