diff --git a/api/server.go b/api/server.go index 29df97c4..7753d5da 100644 --- a/api/server.go +++ b/api/server.go @@ -2010,43 +2010,28 @@ func (s *Server) initUserDefaultConfigs(userID string) error { // handleGetSupportedModels Get list of AI models supported by the system func (s *Server) handleGetSupportedModels(c *gin.Context) { - // Return system-supported AI models (get from default user) - models, err := s.store.AIModel().List("default") - if err != nil { - logger.Infof("❌ Failed to get supported AI models: %v", err) - c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get supported AI models"}) - return + // Return static list of supported AI models + supportedModels := []map[string]interface{}{ + {"id": "deepseek", "name": "DeepSeek", "provider": "deepseek"}, + {"id": "qwen", "name": "Qwen", "provider": "qwen"}, } - c.JSON(http.StatusOK, models) + c.JSON(http.StatusOK, supportedModels) } // handleGetSupportedExchanges Get list of exchanges supported by the system func (s *Server) handleGetSupportedExchanges(c *gin.Context) { - // Return system-supported exchanges (get from default user) - exchanges, err := s.store.Exchange().List("default") - if err != nil { - logger.Infof("❌ Failed to get supported exchanges: %v", err) - c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get supported exchanges"}) - return + // Return static list of supported exchanges + supportedExchanges := []SafeExchangeConfig{ + {ID: "binance", Name: "Binance Futures", Type: "binance"}, + {ID: "bybit", Name: "Bybit Futures", Type: "bybit"}, + {ID: "okx", Name: "OKX Futures", Type: "okx"}, + {ID: "hyperliquid", Name: "Hyperliquid", Type: "hyperliquid"}, + {ID: "aster", Name: "Aster DEX", Type: "aster"}, + {ID: "lighter", Name: "LIGHTER DEX", Type: "lighter"}, } - // Convert to safe response structure, remove sensitive information - safeExchanges := make([]SafeExchangeConfig, len(exchanges)) - for i, exchange := range exchanges { - safeExchanges[i] = SafeExchangeConfig{ - ID: exchange.ID, - Name: exchange.Name, - Type: exchange.Type, - Enabled: exchange.Enabled, - Testnet: exchange.Testnet, - HyperliquidWalletAddr: "", // Default config does not include wallet address - AsterUser: "", // Default config does not include user info - AsterSigner: "", - } - } - - c.JSON(http.StatusOK, safeExchanges) + c.JSON(http.StatusOK, supportedExchanges) } // Start Start server diff --git a/api/strategy.go b/api/strategy.go index 8b50a7ef..3eea7266 100644 --- a/api/strategy.go +++ b/api/strategy.go @@ -283,75 +283,14 @@ func (s *Server) handleGetActiveStrategy(c *gin.Context) { // handleGetDefaultStrategyConfig Get default strategy configuration template func (s *Server) handleGetDefaultStrategyConfig(c *gin.Context) { - // Return default configuration structure for frontend to use when creating new strategies - defaultConfig := store.StrategyConfig{ - CoinSource: store.CoinSourceConfig{ - SourceType: "coinpool", - UseCoinPool: true, - CoinPoolLimit: 30, - UseOITop: true, - OITopLimit: 20, - StaticCoins: []string{}, - }, - Indicators: store.IndicatorConfig{ - Klines: store.KlineConfig{ - PrimaryTimeframe: "5m", - PrimaryCount: 30, - LongerTimeframe: "4h", - LongerCount: 10, - EnableMultiTimeframe: true, - SelectedTimeframes: []string{"5m", "15m", "1h", "4h"}, - }, - EnableEMA: true, - EnableMACD: true, - EnableRSI: true, - EnableATR: true, - EnableVolume: true, - EnableOI: true, - EnableFundingRate: true, - EMAPeriods: []int{20, 50}, - RSIPeriods: []int{7, 14}, - ATRPeriods: []int{14}, - }, - RiskControl: store.RiskControlConfig{ - MaxPositions: 3, - BTCETHMaxLeverage: 5, - AltcoinMaxLeverage: 5, - MinRiskRewardRatio: 3.0, - MaxMarginUsage: 0.9, - MaxPositionRatio: 1.5, - MinPositionSize: 12, - MinConfidence: 75, - }, - PromptSections: store.PromptSectionsConfig{ - RoleDefinition: `# You are a professional cryptocurrency trading AI - -You focus on technical analysis and risk management, making rational trading decisions based on market data. -Your goal is to capture high-probability trading opportunities while controlling risk.`, - TradingFrequency: `# ⏱️ Trading Frequency Awareness - -- Excellent traders: 2-4 trades per day ≈ 0.1-0.2 trades per hour -- >2 trades per hour = overtrading -- Single position holding time ≥30-60 minutes -If you find yourself trading every cycle → standards too low; if closing positions <30 minutes → too impatient.`, - EntryStandards: `# 🎯 Entry Standards (Strict) - -Only enter when multiple signals align: -- Clear trend direction (EMA alignment, price position) -- Momentum confirmation (MACD, RSI cooperation) -- Moderate volatility (ATR reasonable range) -- Volume-price coordination (volume supports direction) - -Avoid: single indicator, conflicting signals, sideways consolidation, reopening immediately after closing.`, - DecisionProcess: `# 📋 Decision Process - -1. Check positions → Should take profit/stop loss -2. Scan candidate coins + multiple timeframes → Are there strong signals -3. Evaluate risk-reward ratio → Does it meet minimum requirements -4. Write chain of thought first, then output structured JSON`, - }, + // Get language from query parameter, default to "en" + lang := c.Query("lang") + if lang != "zh" { + lang = "en" } + // Return default configuration with i18n support + defaultConfig := store.GetDefaultStrategyConfig(lang) c.JSON(http.StatusOK, defaultConfig) } diff --git a/store/ai_model.go b/store/ai_model.go index 6a1e19d0..37be8a54 100644 --- a/store/ai_model.go +++ b/store/ai_model.go @@ -69,22 +69,7 @@ func (s *AIModelStore) initTables() error { } func (s *AIModelStore) initDefaultData() error { - models := []struct { - id, name, provider string - }{ - {"deepseek", "DeepSeek", "deepseek"}, - {"qwen", "Qwen", "qwen"}, - } - - for _, model := range models { - _, err := s.db.Exec(` - INSERT OR IGNORE INTO ai_models (id, user_id, name, provider, enabled) - VALUES (?, 'default', ?, ?, 0) - `, model.id, model.name, model.provider) - if err != nil { - return fmt.Errorf("failed to initialize AI model: %w", err) - } - } + // No longer pre-populate AI models - create on demand when user configures return nil } diff --git a/store/exchange.go b/store/exchange.go index a4819ff1..6ea21013 100644 --- a/store/exchange.go +++ b/store/exchange.go @@ -80,26 +80,7 @@ func (s *ExchangeStore) initTables() error { } func (s *ExchangeStore) initDefaultData() error { - exchanges := []struct { - id, name, typ string - }{ - {"binance", "Binance Futures", "binance"}, - {"bybit", "Bybit Futures", "bybit"}, - {"okx", "OKX Futures", "okx"}, - {"hyperliquid", "Hyperliquid", "hyperliquid"}, - {"aster", "Aster DEX", "aster"}, - {"lighter", "LIGHTER DEX", "lighter"}, - } - - for _, exchange := range exchanges { - _, err := s.db.Exec(` - INSERT OR IGNORE INTO exchanges (id, user_id, name, type, enabled) - VALUES (?, 'default', ?, ?, 0) - `, exchange.id, exchange.name, exchange.typ) - if err != nil { - return fmt.Errorf("failed to initialize exchange: %w", err) - } - } + // No longer pre-populate exchanges - create on demand when user configures return nil } @@ -117,38 +98,8 @@ func (s *ExchangeStore) decrypt(encrypted string) string { return encrypted } -// EnsureUserExchanges ensures user has records for all supported exchanges -func (s *ExchangeStore) EnsureUserExchanges(userID string) error { - exchanges := []struct { - id, name, typ string - }{ - {"binance", "Binance Futures", "binance"}, - {"bybit", "Bybit Futures", "bybit"}, - {"okx", "OKX Futures", "okx"}, - {"hyperliquid", "Hyperliquid", "hyperliquid"}, - {"aster", "Aster DEX", "aster"}, - {"lighter", "LIGHTER DEX", "lighter"}, - } - - for _, exchange := range exchanges { - _, err := s.db.Exec(` - INSERT OR IGNORE INTO exchanges (id, user_id, name, type, enabled) - VALUES (?, ?, ?, ?, 0) - `, exchange.id, userID, exchange.name, exchange.typ) - if err != nil { - return fmt.Errorf("failed to ensure user exchanges: %w", err) - } - } - return nil -} - // List gets user's exchange list func (s *ExchangeStore) List(userID string) ([]*Exchange, error) { - // Ensure user has records for all supported exchanges - if err := s.EnsureUserExchanges(userID); err != nil { - logger.Debugf("Warning: failed to ensure user exchange records: %v", err) - } - rows, err := s.db.Query(` SELECT id, user_id, name, type, enabled, api_key, secret_key, COALESCE(passphrase, '') as passphrase, testnet, diff --git a/store/strategy.go b/store/strategy.go index 9a66be51..23432a40 100644 --- a/store/strategy.go +++ b/store/strategy.go @@ -178,15 +178,13 @@ func (s *StrategyStore) initTables() error { } func (s *StrategyStore) initDefaultData() error { - // check if default strategy already exists - var count int - s.db.QueryRow(`SELECT COUNT(*) FROM strategies WHERE is_default = 1`).Scan(&count) - if count > 0 { - return nil - } + // No longer pre-populate strategies - create on demand when user configures + return nil +} - // create system default strategy - defaultConfig := StrategyConfig{ +// GetDefaultStrategyConfig returns the default strategy configuration for the given language +func GetDefaultStrategyConfig(lang string) StrategyConfig { + config := StrategyConfig{ CoinSource: CoinSourceConfig{ SourceType: "coinpool", UseCoinPool: true, @@ -214,8 +212,8 @@ func (s *StrategyStore) initDefaultData() error { EMAPeriods: []int{20, 50}, RSIPeriods: []int{7, 14}, ATRPeriods: []int{14}, - EnableQuantData: true, - QuantDataAPIURL: "http://nofxaios.com:30006/api/coin/{symbol}?include=netflow,oi,price&auth=cm_568c67eae410d912c54c", + EnableQuantData: true, + QuantDataAPIURL: "http://nofxaios.com:30006/api/coin/{symbol}?include=netflow,oi,price&auth=cm_568c67eae410d912c54c", }, RiskControl: RiskControlConfig{ MaxPositions: 3, @@ -227,7 +225,30 @@ func (s *StrategyStore) initDefaultData() error { MinPositionSize: 12, MinConfidence: 75, }, - PromptSections: PromptSectionsConfig{ + } + + if lang == "zh" { + config.PromptSections = PromptSectionsConfig{ + RoleDefinition: `# 你是一个专业的加密货币交易AI + +你的任务是根据提供的市场数据做出交易决策。你是一个经验丰富的量化交易员,擅长技术分析和风险管理。`, + TradingFrequency: `# ⏱️ 交易频率意识 + +- 优秀交易员:每天2-4笔 ≈ 每小时0.1-0.2笔 +- 每小时超过2笔 = 过度交易 +- 单笔持仓时间 ≥ 30-60分钟 +如果你发现自己每个周期都在交易 → 标准太低;如果持仓不到30分钟就平仓 → 太冲动。`, + EntryStandards: `# 🎯 入场标准(严格) + +只在多个信号共振时入场。自由使用任何有效的分析方法,避免单一指标、信号矛盾、横盘震荡、或平仓后立即重新开仓等低质量行为。`, + DecisionProcess: `# 📋 决策流程 + +1. 检查持仓 → 是否止盈/止损 +2. 扫描候选币种 + 多时间框架 → 是否存在强信号 +3. 先写思维链,再输出结构化JSON`, + } + } else { + config.PromptSections = PromptSectionsConfig{ RoleDefinition: `# You are a professional cryptocurrency trading AI Your task is to make trading decisions based on the provided market data. You are an experienced quantitative trader skilled in technical analysis and risk management.`, @@ -245,17 +266,10 @@ Only enter positions when multiple signals resonate. Freely use any effective an 1. Check positions → whether to take profit/stop loss 2. Scan candidate coins + multi-timeframe → whether strong signals exist 3. Write chain of thought first, then output structured JSON`, - }, + } } - configJSON, _ := json.Marshal(defaultConfig) - - _, err := s.db.Exec(` - INSERT INTO strategies (id, user_id, name, description, is_active, is_default, config) - VALUES ('default', 'system', 'Default Altcoin Strategy', 'System default altcoin trading strategy, uses AI500 coin pool, includes complete technical indicators', 0, 1, ?) - `, string(configJSON)) - - return err + return config } // Create create a strategy diff --git a/web/src/pages/StrategyStudioPage.tsx b/web/src/pages/StrategyStudioPage.tsx index a333d11e..783dd035 100644 --- a/web/src/pages/StrategyStudioPage.tsx +++ b/web/src/pages/StrategyStudioPage.tsx @@ -150,7 +150,7 @@ export function StrategyStudioPage() { if (!token) return try { const configResponse = await fetch( - `${API_BASE}/api/strategies/default-config`, + `${API_BASE}/api/strategies/default-config?lang=${language}`, { headers: { Authorization: `Bearer ${token}` } } ) const defaultConfig = await configResponse.json()