diff --git a/README.md b/README.md index 08dbd4ef..5c5fb6d0 100644 --- a/README.md +++ b/README.md @@ -250,8 +250,11 @@ Create `config.json` file (use `config.json.example` as template): - `binance_api_key/secret_key`: Each trader uses independent Binance account - `initial_balance`: Initial balance (for calculating P/L%) - `scan_interval_minutes`: Decision cycle (recommended 3-5 minutes) -- `coin_pool_api_url`: AI500 coin pool API (optional) -- `oi_top_api_url`: OI Top open interest API (optional) +- `coin_pool_api_url`: AI500 coin pool API (optional, if empty, uses default mainstream coins) +- `oi_top_api_url`: OI Top open interest API (optional, if empty, OI Top data is skipped) + +**Default Coin List** (used when APIs are not configured): +- BTC, ETH, SOL, BNB, XRP, DOGE, ADA, HYPE ### 5. Run the System diff --git a/README.zh-CN.md b/README.zh-CN.md index 4684f8d4..20c0f50a 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -250,8 +250,11 @@ cd .. - `binance_api_key/secret_key`: 每个trader使用独立的币安账户 - `initial_balance`: 初始余额(用于计算盈亏%) - `scan_interval_minutes`: 决策周期(建议3-5分钟) -- `coin_pool_api_url`: AI500币种池API(可选) -- `oi_top_api_url`: OI Top持仓量API(可选) +- `coin_pool_api_url`: AI500币种池API(可选,留空时使用默认主流币种) +- `oi_top_api_url`: OI Top持仓量API(可选,留空时跳过OI Top数据) + +**默认币种列表**(当API未配置时使用): +- BTC、ETH、SOL、BNB、XRP、DOGE、ADA、HYPE ### 5. 运行系统 diff --git a/pool/coin_pool.go b/pool/coin_pool.go index b88b865b..35c4bc64 100644 --- a/pool/coin_pool.go +++ b/pool/coin_pool.go @@ -8,9 +8,22 @@ import ( "net/http" "os" "path/filepath" + "strings" "time" ) +// defaultMainstreamCoins 默认主流币种池(当AI500和OI Top都失败时使用) +var defaultMainstreamCoins = []string{ + "BTCUSDT", + "ETHUSDT", + "SOLUSDT", + "BNBUSDT", + "XRPUSDT", + "DOGEUSDT", + "ADAUSDT", + "HYPEUSDT", +} + // CoinPoolConfig 币种池配置 type CoinPoolConfig struct { APIURL string @@ -65,6 +78,12 @@ func SetOITopAPI(apiURL string) { // GetCoinPool 获取币种池列表(带重试和缓存机制) func GetCoinPool() ([]CoinInfo, error) { + // 检查API URL是否配置 + if strings.TrimSpace(coinPoolConfig.APIURL) == "" { + log.Printf("⚠️ 未配置币种池API URL,使用默认主流币种列表") + return convertSymbolsToCoins(defaultMainstreamCoins), nil + } + maxRetries := 3 var lastErr error @@ -99,8 +118,9 @@ func GetCoinPool() ([]CoinInfo, error) { return cachedCoins, nil } - log.Printf("❌ 无法加载缓存数据: %v", err) - return nil, fmt.Errorf("获取币种池失败(API重试%d次后,缓存也不可用): %w", maxRetries, lastErr) + // 缓存也失败,使用默认主流币种 + log.Printf("⚠️ 无法加载缓存数据(最后错误: %v),使用默认主流币种列表", lastErr) + return convertSymbolsToCoins(defaultMainstreamCoins), nil } // fetchCoinPool 实际执行币种池请求 @@ -321,6 +341,19 @@ func endsWith(s, suffix string) bool { return s[len(s)-len(suffix):] == suffix } +// convertSymbolsToCoins 将币种符号列表转换为CoinInfo列表 +func convertSymbolsToCoins(symbols []string) []CoinInfo { + coins := make([]CoinInfo, 0, len(symbols)) + for _, symbol := range symbols { + coins = append(coins, CoinInfo{ + Pair: symbol, + Score: 0, + IsAvailable: true, + }) + } + return coins +} + // ========== OI Top(持仓量增长Top20)数据 ========== // OIPosition 持仓量数据 @@ -366,6 +399,12 @@ var oiTopConfig = struct { // GetOITopPositions 获取持仓量增长Top20数据(带重试和缓存) func GetOITopPositions() ([]OIPosition, error) { + // 检查API URL是否配置 + if strings.TrimSpace(oiTopConfig.APIURL) == "" { + log.Printf("⚠️ 未配置OI Top API URL,跳过OI Top数据获取") + return []OIPosition{}, nil // 返回空列表,不是错误 + } + maxRetries := 3 var lastErr error @@ -400,8 +439,9 @@ func GetOITopPositions() ([]OIPosition, error) { return cachedPositions, nil } - log.Printf("❌ 无法加载OI Top缓存数据: %v", err) - return nil, fmt.Errorf("获取OI Top数据失败(API重试%d次后,缓存也不可用): %w", maxRetries, lastErr) + // 缓存也失败,返回空列表(OI Top是可选的) + log.Printf("⚠️ 无法加载OI Top缓存数据(最后错误: %v),跳过OI Top数据", lastErr) + return []OIPosition{}, nil } // fetchOITop 实际执行OI Top请求