From 6843c93a86398ab8ef8cc5eff337547bc4bb8545 Mon Sep 17 00:00:00 2001 From: SkywalkerJi Date: Fri, 31 Oct 2025 18:30:36 +0800 Subject: [PATCH 1/5] Ignore the database to avoid submitting sensitive data. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d501f8dd..4dc2afc9 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ Thumbs.db # 环境变量 .env config.json +config.db # 决策日志 decision_logs/ From e75c8343727deb7c31d601357231c35b603e7a33 Mon Sep 17 00:00:00 2001 From: SkywalkerJi Date: Fri, 31 Oct 2025 18:34:48 +0800 Subject: [PATCH 2/5] Change the minimum amount to 50 and remove the maximum amount limit. --- web/src/components/AITradersPage.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/src/components/AITradersPage.tsx b/web/src/components/AITradersPage.tsx index b42a79bd..456c7404 100644 --- a/web/src/components/AITradersPage.tsx +++ b/web/src/components/AITradersPage.tsx @@ -758,8 +758,7 @@ function CreateTraderModal({ type="number" value={initialBalance} onChange={(e) => setInitialBalance(Number(e.target.value))} - min="100" - max="100000" + min="50" className="w-full px-3 py-2 rounded" style={{ background: '#0B0E11', border: '1px solid #2B3139', color: '#EAECEF' }} required From f58c874aaf7e34ef7bf1a49cd0dd74e8172fd10c Mon Sep 17 00:00:00 2001 From: SkywalkerJi Date: Fri, 31 Oct 2025 21:05:13 +0800 Subject: [PATCH 3/5] Fix leverage settings --- manager/trader_manager.go | 40 ++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/manager/trader_manager.go b/manager/trader_manager.go index f6253a5d..bfa15f20 100644 --- a/manager/trader_manager.go +++ b/manager/trader_manager.go @@ -48,6 +48,8 @@ func (tm *TraderManager) LoadTradersFromDatabase(database *config.Database) erro maxDailyLossStr, _ := database.GetSystemConfig("max_daily_loss") maxDrawdownStr, _ := database.GetSystemConfig("max_drawdown") stopTradingMinutesStr, _ := database.GetSystemConfig("stop_trading_minutes") + btcEthLeverageStr, _ := database.GetSystemConfig("btc_eth_leverage") + altcoinLeverageStr, _ := database.GetSystemConfig("altcoin_leverage") // 解析配置 maxDailyLoss := 10.0 // 默认值 @@ -65,6 +67,16 @@ func (tm *TraderManager) LoadTradersFromDatabase(database *config.Database) erro stopTradingMinutes = val } + btcEthLeverage := 5 // 默认值 + if val, err := strconv.Atoi(btcEthLeverageStr); err == nil && val > 0 { + btcEthLeverage = val + } + + altcoinLeverage := 5 // 默认值 + if val, err := strconv.Atoi(altcoinLeverageStr); err == nil && val > 0 { + altcoinLeverage = val + } + // 为每个交易员获取AI模型和交易所配置 for _, traderCfg := range traders { // 获取AI模型配置 @@ -118,7 +130,7 @@ func (tm *TraderManager) LoadTradersFromDatabase(database *config.Database) erro } // 添加到TraderManager - err = tm.addTraderFromDB(traderCfg, aiModelCfg, exchangeCfg, coinPoolURL, maxDailyLoss, maxDrawdown, stopTradingMinutes) + err = tm.addTraderFromDB(traderCfg, aiModelCfg, exchangeCfg, coinPoolURL, maxDailyLoss, maxDrawdown, stopTradingMinutes, btcEthLeverage, altcoinLeverage) if err != nil { log.Printf("❌ 添加交易员 %s 失败: %v", traderCfg.Name, err) continue @@ -130,7 +142,7 @@ func (tm *TraderManager) LoadTradersFromDatabase(database *config.Database) erro } // addTraderFromConfig 内部方法:从配置添加交易员(不加锁,因为调用方已加锁) -func (tm *TraderManager) addTraderFromDB(traderCfg *config.TraderRecord, aiModelCfg *config.AIModelConfig, exchangeCfg *config.ExchangeConfig, coinPoolURL string, maxDailyLoss, maxDrawdown float64, stopTradingMinutes int) error { +func (tm *TraderManager) addTraderFromDB(traderCfg *config.TraderRecord, aiModelCfg *config.AIModelConfig, exchangeCfg *config.ExchangeConfig, coinPoolURL string, maxDailyLoss, maxDrawdown float64, stopTradingMinutes, btcEthLeverage, altcoinLeverage int) error { if _, exists := tm.traders[traderCfg.ID]; exists { return fmt.Errorf("trader ID '%s' 已存在", traderCfg.ID) } @@ -151,6 +163,8 @@ func (tm *TraderManager) addTraderFromDB(traderCfg *config.TraderRecord, aiModel QwenKey: "", ScanInterval: time.Duration(traderCfg.ScanIntervalMinutes) * time.Minute, InitialBalance: traderCfg.InitialBalance, + BTCETHLeverage: btcEthLeverage, + AltcoinLeverage: altcoinLeverage, MaxDailyLoss: maxDailyLoss, MaxDrawdown: maxDrawdown, StopTradingTime: time.Duration(stopTradingMinutes) * time.Minute, @@ -202,7 +216,7 @@ func (tm *TraderManager) addTraderFromDB(traderCfg *config.TraderRecord, aiModel // AddTrader 从数据库配置添加trader (移除旧版兼容性) // AddTraderFromDB 从数据库配置添加trader -func (tm *TraderManager) AddTraderFromDB(traderCfg *config.TraderRecord, aiModelCfg *config.AIModelConfig, exchangeCfg *config.ExchangeConfig, coinPoolURL string, maxDailyLoss, maxDrawdown float64, stopTradingMinutes int) error { +func (tm *TraderManager) AddTraderFromDB(traderCfg *config.TraderRecord, aiModelCfg *config.AIModelConfig, exchangeCfg *config.ExchangeConfig, coinPoolURL string, maxDailyLoss, maxDrawdown float64, stopTradingMinutes, btcEthLeverage, altcoinLeverage int) error { tm.mu.Lock() defer tm.mu.Unlock() @@ -226,6 +240,8 @@ func (tm *TraderManager) AddTraderFromDB(traderCfg *config.TraderRecord, aiModel QwenKey: "", ScanInterval: time.Duration(traderCfg.ScanIntervalMinutes) * time.Minute, InitialBalance: traderCfg.InitialBalance, + BTCETHLeverage: btcEthLeverage, + AltcoinLeverage: altcoinLeverage, MaxDailyLoss: maxDailyLoss, MaxDrawdown: maxDrawdown, StopTradingTime: time.Duration(stopTradingMinutes) * time.Minute, @@ -463,6 +479,8 @@ func (tm *TraderManager) LoadUserTraders(database *config.Database, userID strin maxDailyLossStr, _ := database.GetSystemConfig("max_daily_loss") maxDrawdownStr, _ := database.GetSystemConfig("max_drawdown") stopTradingMinutesStr, _ := database.GetSystemConfig("stop_trading_minutes") + btcEthLeverageStr, _ := database.GetSystemConfig("btc_eth_leverage") + altcoinLeverageStr, _ := database.GetSystemConfig("altcoin_leverage") // 解析配置 maxDailyLoss := 10.0 // 默认值 @@ -480,6 +498,16 @@ func (tm *TraderManager) LoadUserTraders(database *config.Database, userID strin stopTradingMinutes = val } + btcEthLeverage := 5 // 默认值 + if val, err := strconv.Atoi(btcEthLeverageStr); err == nil && val > 0 { + btcEthLeverage = val + } + + altcoinLeverage := 5 // 默认值 + if val, err := strconv.Atoi(altcoinLeverageStr); err == nil && val > 0 { + altcoinLeverage = val + } + // 为每个交易员获取AI模型和交易所配置 for _, traderCfg := range traders { // 检查是否已经加载过这个交易员 @@ -539,7 +567,7 @@ func (tm *TraderManager) LoadUserTraders(database *config.Database, userID strin } // 使用现有的方法加载交易员 - err = tm.loadSingleTrader(traderCfg, aiModelCfg, exchangeCfg, coinPoolURL, maxDailyLoss, maxDrawdown, stopTradingMinutes) + err = tm.loadSingleTrader(traderCfg, aiModelCfg, exchangeCfg, coinPoolURL, maxDailyLoss, maxDrawdown, stopTradingMinutes, btcEthLeverage, altcoinLeverage) if err != nil { log.Printf("⚠️ 加载交易员 %s 失败: %v", traderCfg.Name, err) } @@ -549,7 +577,7 @@ func (tm *TraderManager) LoadUserTraders(database *config.Database, userID strin } // loadSingleTrader 加载单个交易员(从现有代码提取的公共逻辑) -func (tm *TraderManager) loadSingleTrader(traderCfg *config.TraderRecord, aiModelCfg *config.AIModelConfig, exchangeCfg *config.ExchangeConfig, coinPoolURL string, maxDailyLoss, maxDrawdown float64, stopTradingMinutes int) error { +func (tm *TraderManager) loadSingleTrader(traderCfg *config.TraderRecord, aiModelCfg *config.AIModelConfig, exchangeCfg *config.ExchangeConfig, coinPoolURL string, maxDailyLoss, maxDrawdown float64, stopTradingMinutes, btcEthLeverage, altcoinLeverage int) error { // 构建AutoTraderConfig traderConfig := trader.AutoTraderConfig{ ID: traderCfg.ID, @@ -559,6 +587,8 @@ func (tm *TraderManager) loadSingleTrader(traderCfg *config.TraderRecord, aiMode InitialBalance: traderCfg.InitialBalance, ScanInterval: time.Duration(traderCfg.ScanIntervalMinutes) * time.Minute, CoinPoolAPIURL: coinPoolURL, + BTCETHLeverage: btcEthLeverage, + AltcoinLeverage: altcoinLeverage, MaxDailyLoss: maxDailyLoss, MaxDrawdown: maxDrawdown, StopTradingTime: time.Duration(stopTradingMinutes) * time.Minute, From 91fcfb0ec5eb08cfa21d51279d1f1e838c417a1a Mon Sep 17 00:00:00 2001 From: SkywalkerJi Date: Fri, 31 Oct 2025 21:05:53 +0800 Subject: [PATCH 4/5] Fix coin settings --- main.go | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 547c0677..33c93878 100644 --- a/main.go +++ b/main.go @@ -160,14 +160,30 @@ func main() { log.Printf("✓ 配置数据库初始化成功") fmt.Println() - // 设置默认主流币种列表 - defaultCoins := []string{"BTC", "ETH", "SOL", "BNB", "XRP", "DOGE", "ADA", "HYPE"} + // 从数据库读取默认主流币种列表 + defaultCoinsJSON, _ := database.GetSystemConfig("default_coins") + var defaultCoins []string + + if defaultCoinsJSON != "" { + // 尝试从JSON解析 + if err := json.Unmarshal([]byte(defaultCoinsJSON), &defaultCoins); err != nil { + log.Printf("⚠️ 解析default_coins配置失败: %v,使用硬编码默认值", err) + defaultCoins = []string{"BTCUSDT", "ETHUSDT", "SOLUSDT", "BNBUSDT", "XRPUSDT", "DOGEUSDT", "ADAUSDT", "HYPEUSDT"} + } else { + log.Printf("✓ 从数据库加载默认币种列表(共%d个): %v", len(defaultCoins), defaultCoins) + } + } else { + // 如果数据库中没有配置,使用硬编码默认值 + defaultCoins = []string{"BTCUSDT", "ETHUSDT", "SOLUSDT", "BNBUSDT", "XRPUSDT", "DOGEUSDT", "ADAUSDT", "HYPEUSDT"} + log.Printf("⚠️ 数据库中未配置default_coins,使用硬编码默认值") + } + pool.SetDefaultCoins(defaultCoins) // 设置是否使用默认主流币种 pool.SetUseDefaultCoins(useDefaultCoins) if useDefaultCoins { - log.Printf("✓ 已启用默认主流币种列表(BTC、ETH、SOL、BNB、XRP、DOGE、ADA、HYPE)") + log.Printf("✓ 已启用默认主流币种列表") } // 设置币种池API URL From 748cca07d782f25fb5f626271f957ef57869b550 Mon Sep 17 00:00:00 2001 From: Ember <197652334@qq.com> Date: Fri, 31 Oct 2025 21:40:21 +0800 Subject: [PATCH 5/5] Fix: Add proper validation for Aster DEX exchange in trader creation - Add specific field validation for Aster exchange (asterUser, asterSigner, asterPrivateKey) - Add specific field validation for Hyperliquid exchange (apiKey, hyperliquidWalletAddr) - Keep existing validation for Binance (apiKey, secretKey) - Remove debug console logs - Fix issue where Aster exchange was not appearing in trader creation dropdown This ensures all three supported exchanges can be properly selected when creating a new AI trader. --- web/src/components/AITradersPage.tsx | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/web/src/components/AITradersPage.tsx b/web/src/components/AITradersPage.tsx index 456c7404..d76d45f7 100644 --- a/web/src/components/AITradersPage.tsx +++ b/web/src/components/AITradersPage.tsx @@ -53,23 +53,18 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) { useEffect(() => { const loadConfigs = async () => { try { - console.log('🔄 开始加载模型和交易所配置...'); const [modelConfigs, exchangeConfigs, supportedModels, supportedExchanges] = await Promise.all([ api.getModelConfigs(), api.getExchangeConfigs(), api.getSupportedModels(), api.getSupportedExchanges() ]); - console.log('✅ 用户模型配置加载成功:', modelConfigs); - console.log('✅ 用户交易所配置加载成功:', exchangeConfigs); - console.log('✅ 支持的模型加载成功:', supportedModels); - console.log('✅ 支持的交易所加载成功:', supportedExchanges); setAllModels(modelConfigs); setAllExchanges(exchangeConfigs); setSupportedModels(supportedModels); setSupportedExchanges(supportedExchanges); } catch (error) { - console.error('❌ 加载配置失败:', error); + console.error('Failed to load configs:', error); } }; loadConfigs(); @@ -82,11 +77,20 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) { // 只在创建交易员时使用已启用且配置完整的 const enabledModels = allModels?.filter(m => m.enabled && m.apiKey) || []; const enabledExchanges = allExchanges?.filter(e => { - if (!e.enabled || !e.apiKey) return false; + if (!e.enabled) return false; + + // Aster 交易所需要特殊字段 + if (e.id === 'aster') { + return e.asterUser && e.asterSigner && e.asterPrivateKey; + } + // Hyperliquid 只需要私钥(作为apiKey),不需要secretKey - if (e.id === 'hyperliquid') return true; - // 其他交易所需要secretKey - return e.secretKey && e.secretKey.trim() !== ''; + if (e.id === 'hyperliquid') { + return e.apiKey && e.hyperliquidWalletAddr; + } + + // Binance 等其他交易所需要 apiKey 和 secretKey + return e.apiKey && e.apiKey.trim() !== '' && e.secretKey && e.secretKey.trim() !== ''; }) || []; // 检查模型是否正在被运行中的交易员使用