mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-15 00:36:56 +08:00
fix: 当API URL为空时使用默认币种列表,避免循环请求失败
- 添加默认主流币种列表(BTC、ETH、SOL、BNB、XRP、DOGE、ADA、HYPE) - 在GetCoinPool()中检查coin_pool_api_url,为空时直接返回默认列表 - 在GetOITopPositions()中检查oi_top_api_url,为空时跳过OI Top数据 - 更新README文档,说明API URL可选配置和默认币种列表 - 修复:避免空URL导致的循环请求和"unsupported protocol scheme"错误
This commit is contained in:
@@ -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
|
- `binance_api_key/secret_key`: Each trader uses independent Binance account
|
||||||
- `initial_balance`: Initial balance (for calculating P/L%)
|
- `initial_balance`: Initial balance (for calculating P/L%)
|
||||||
- `scan_interval_minutes`: Decision cycle (recommended 3-5 minutes)
|
- `scan_interval_minutes`: Decision cycle (recommended 3-5 minutes)
|
||||||
- `coin_pool_api_url`: AI500 coin pool 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)
|
- `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
|
### 5. Run the System
|
||||||
|
|
||||||
|
|||||||
@@ -250,8 +250,11 @@ cd ..
|
|||||||
- `binance_api_key/secret_key`: 每个trader使用独立的币安账户
|
- `binance_api_key/secret_key`: 每个trader使用独立的币安账户
|
||||||
- `initial_balance`: 初始余额(用于计算盈亏%)
|
- `initial_balance`: 初始余额(用于计算盈亏%)
|
||||||
- `scan_interval_minutes`: 决策周期(建议3-5分钟)
|
- `scan_interval_minutes`: 决策周期(建议3-5分钟)
|
||||||
- `coin_pool_api_url`: AI500币种池API(可选)
|
- `coin_pool_api_url`: AI500币种池API(可选,留空时使用默认主流币种)
|
||||||
- `oi_top_api_url`: OI Top持仓量API(可选)
|
- `oi_top_api_url`: OI Top持仓量API(可选,留空时跳过OI Top数据)
|
||||||
|
|
||||||
|
**默认币种列表**(当API未配置时使用):
|
||||||
|
- BTC、ETH、SOL、BNB、XRP、DOGE、ADA、HYPE
|
||||||
|
|
||||||
### 5. 运行系统
|
### 5. 运行系统
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,22 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// defaultMainstreamCoins 默认主流币种池(当AI500和OI Top都失败时使用)
|
||||||
|
var defaultMainstreamCoins = []string{
|
||||||
|
"BTCUSDT",
|
||||||
|
"ETHUSDT",
|
||||||
|
"SOLUSDT",
|
||||||
|
"BNBUSDT",
|
||||||
|
"XRPUSDT",
|
||||||
|
"DOGEUSDT",
|
||||||
|
"ADAUSDT",
|
||||||
|
"HYPEUSDT",
|
||||||
|
}
|
||||||
|
|
||||||
// CoinPoolConfig 币种池配置
|
// CoinPoolConfig 币种池配置
|
||||||
type CoinPoolConfig struct {
|
type CoinPoolConfig struct {
|
||||||
APIURL string
|
APIURL string
|
||||||
@@ -65,6 +78,12 @@ func SetOITopAPI(apiURL string) {
|
|||||||
|
|
||||||
// GetCoinPool 获取币种池列表(带重试和缓存机制)
|
// GetCoinPool 获取币种池列表(带重试和缓存机制)
|
||||||
func GetCoinPool() ([]CoinInfo, error) {
|
func GetCoinPool() ([]CoinInfo, error) {
|
||||||
|
// 检查API URL是否配置
|
||||||
|
if strings.TrimSpace(coinPoolConfig.APIURL) == "" {
|
||||||
|
log.Printf("⚠️ 未配置币种池API URL,使用默认主流币种列表")
|
||||||
|
return convertSymbolsToCoins(defaultMainstreamCoins), nil
|
||||||
|
}
|
||||||
|
|
||||||
maxRetries := 3
|
maxRetries := 3
|
||||||
var lastErr error
|
var lastErr error
|
||||||
|
|
||||||
@@ -99,8 +118,9 @@ func GetCoinPool() ([]CoinInfo, error) {
|
|||||||
return cachedCoins, nil
|
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 实际执行币种池请求
|
// fetchCoinPool 实际执行币种池请求
|
||||||
@@ -321,6 +341,19 @@ func endsWith(s, suffix string) bool {
|
|||||||
return s[len(s)-len(suffix):] == suffix
|
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)数据 ==========
|
// ========== OI Top(持仓量增长Top20)数据 ==========
|
||||||
|
|
||||||
// OIPosition 持仓量数据
|
// OIPosition 持仓量数据
|
||||||
@@ -366,6 +399,12 @@ var oiTopConfig = struct {
|
|||||||
|
|
||||||
// GetOITopPositions 获取持仓量增长Top20数据(带重试和缓存)
|
// GetOITopPositions 获取持仓量增长Top20数据(带重试和缓存)
|
||||||
func GetOITopPositions() ([]OIPosition, error) {
|
func GetOITopPositions() ([]OIPosition, error) {
|
||||||
|
// 检查API URL是否配置
|
||||||
|
if strings.TrimSpace(oiTopConfig.APIURL) == "" {
|
||||||
|
log.Printf("⚠️ 未配置OI Top API URL,跳过OI Top数据获取")
|
||||||
|
return []OIPosition{}, nil // 返回空列表,不是错误
|
||||||
|
}
|
||||||
|
|
||||||
maxRetries := 3
|
maxRetries := 3
|
||||||
var lastErr error
|
var lastErr error
|
||||||
|
|
||||||
@@ -400,8 +439,9 @@ func GetOITopPositions() ([]OIPosition, error) {
|
|||||||
return cachedPositions, nil
|
return cachedPositions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("❌ 无法加载OI Top缓存数据: %v", err)
|
// 缓存也失败,返回空列表(OI Top是可选的)
|
||||||
return nil, fmt.Errorf("获取OI Top数据失败(API重试%d次后,缓存也不可用): %w", maxRetries, lastErr)
|
log.Printf("⚠️ 无法加载OI Top缓存数据(最后错误: %v),跳过OI Top数据", lastErr)
|
||||||
|
return []OIPosition{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetchOITop 实际执行OI Top请求
|
// fetchOITop 实际执行OI Top请求
|
||||||
|
|||||||
Reference in New Issue
Block a user