mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-14 00:07:01 +08:00
Merge pull request #9 from hrzisme/fix/empty-api-url-default-coins
fix: 当API URL为空时使用默认币种列表,避免循环请求失败
This commit is contained in:
@@ -250,8 +250,12 @@ 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)
|
- `use_default_coins`: **true** = Use default 8 mainstream coins | **false** = Use API coin pool (recommended for beginners: true)
|
||||||
- `oi_top_api_url`: OI Top open interest API (optional)
|
- `coin_pool_api_url`: AI500 coin pool API (optional, ignored when use_default_coins=true)
|
||||||
|
- `oi_top_api_url`: OI Top open interest API (optional, if empty, OI Top data is skipped)
|
||||||
|
|
||||||
|
**Default Coin List** (when `use_default_coins: true`):
|
||||||
|
- BTC, ETH, SOL, BNB, XRP, DOGE, ADA, HYPE
|
||||||
|
|
||||||
### 5. Run the System
|
### 5. Run the System
|
||||||
|
|
||||||
|
|||||||
15
README.ru.md
15
README.ru.md
@@ -173,12 +173,27 @@ cd ..
|
|||||||
"initial_balance": 1000.0
|
"initial_balance": 1000.0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"use_default_coins": false,
|
||||||
"coin_pool_api_url": "http://x.x.x.x:xxx/api/ai500/list?auth=ВАШ_AUTH",
|
"coin_pool_api_url": "http://x.x.x.x:xxx/api/ai500/list?auth=ВАШ_AUTH",
|
||||||
"oi_top_api_url": "http://x.x.x.x:xxx/api/oi/top?auth=ВАШ_AUTH",
|
"oi_top_api_url": "http://x.x.x.x:xxx/api/oi/top?auth=ВАШ_AUTH",
|
||||||
"api_server_port": 8080
|
"api_server_port": 8080
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Примечания к конфигурации:**
|
||||||
|
- `traders`: Настройте 1-N трейдеров (один AI или соревнование нескольких AI)
|
||||||
|
- `id`: Уникальный идентификатор трейдера (используется для директории логов)
|
||||||
|
- `ai_model`: "qwen" или "deepseek"
|
||||||
|
- `binance_api_key/secret_key`: Каждый трейдер использует независимый аккаунт Binance
|
||||||
|
- `initial_balance`: Начальный баланс (для расчета P/L%)
|
||||||
|
- `scan_interval_minutes`: Цикл принятия решений (рекомендуется 3-5 минут)
|
||||||
|
- `use_default_coins`: **true** = Использовать 8 основных монет по умолчанию | **false** = Использовать API пул монет (рекомендуется для новичков: true)
|
||||||
|
- `coin_pool_api_url`: API пула монет AI500 (опционально, игнорируется при use_default_coins=true)
|
||||||
|
- `oi_top_api_url`: API открытого интереса OI Top (опционально, если пусто, данные OI Top пропускаются)
|
||||||
|
|
||||||
|
**Список монет по умолчанию** (когда `use_default_coins: true`):
|
||||||
|
- BTC, ETH, SOL, BNB, XRP, DOGE, ADA, HYPE
|
||||||
|
|
||||||
### 5. Запуск системы
|
### 5. Запуск системы
|
||||||
|
|
||||||
**Запуск backend (система AI торговли + API сервер):**
|
**Запуск backend (система AI торговли + API сервер):**
|
||||||
|
|||||||
15
README.uk.md
15
README.uk.md
@@ -173,12 +173,27 @@ cd ..
|
|||||||
"initial_balance": 1000.0
|
"initial_balance": 1000.0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"use_default_coins": false,
|
||||||
"coin_pool_api_url": "http://x.x.x.x:xxx/api/ai500/list?auth=ВАШ_AUTH",
|
"coin_pool_api_url": "http://x.x.x.x:xxx/api/ai500/list?auth=ВАШ_AUTH",
|
||||||
"oi_top_api_url": "http://x.x.x.x:xxx/api/oi/top?auth=ВАШ_AUTH",
|
"oi_top_api_url": "http://x.x.x.x:xxx/api/oi/top?auth=ВАШ_AUTH",
|
||||||
"api_server_port": 8080
|
"api_server_port": 8080
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Примітки до конфігурації:**
|
||||||
|
- `traders`: Налаштуйте 1-N трейдерів (один AI або змагання кількох AI)
|
||||||
|
- `id`: Унікальний ідентифікатор трейдера (використовується для директорії логів)
|
||||||
|
- `ai_model`: "qwen" або "deepseek"
|
||||||
|
- `binance_api_key/secret_key`: Кожен трейдер використовує незалежний акаунт Binance
|
||||||
|
- `initial_balance`: Початковий баланс (для розрахунку P/L%)
|
||||||
|
- `scan_interval_minutes`: Цикл прийняття рішень (рекомендується 3-5 хвилин)
|
||||||
|
- `use_default_coins`: **true** = Використовувати 8 основних монет за замовчуванням | **false** = Використовувати API пул монет (рекомендується для новачків: true)
|
||||||
|
- `coin_pool_api_url`: API пулу монет AI500 (опціонально, ігнорується при use_default_coins=true)
|
||||||
|
- `oi_top_api_url`: API відкритого інтересу OI Top (опціонально, якщо порожньо, дані OI Top пропускаються)
|
||||||
|
|
||||||
|
**Список монет за замовчуванням** (коли `use_default_coins: true`):
|
||||||
|
- BTC, ETH, SOL, BNB, XRP, DOGE, ADA, HYPE
|
||||||
|
|
||||||
### 5. Запуск системи
|
### 5. Запуск системи
|
||||||
|
|
||||||
**Запуск backend (система AI торгівлі + API сервер):**
|
**Запуск backend (система AI торгівлі + API сервер):**
|
||||||
|
|||||||
@@ -250,8 +250,12 @@ 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(可选)
|
- `use_default_coins`: **true** = 使用默认8个主流币种 | **false** = 使用API币种池(新手推荐:true)
|
||||||
- `oi_top_api_url`: OI Top持仓量API(可选)
|
- `coin_pool_api_url`: AI500币种池API(可选,当use_default_coins=true时忽略)
|
||||||
|
- `oi_top_api_url`: OI Top持仓量API(可选,留空时跳过OI Top数据)
|
||||||
|
|
||||||
|
**默认币种列表**(当 `use_default_coins: true` 时):
|
||||||
|
- BTC、ETH、SOL、BNB、XRP、DOGE、ADA、HYPE
|
||||||
|
|
||||||
### 5. 运行系统
|
### 5. 运行系统
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"scan_interval_minutes": 3
|
"scan_interval_minutes": 3
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"use_default_coins": false,
|
||||||
"coin_pool_api_url": "http://x.x.x.x:x/api/ai500/list?auth=",
|
"coin_pool_api_url": "http://x.x.x.x:x/api/ai500/list?auth=",
|
||||||
"oi_top_api_url": "http://x.x.x.x:x/api/oi/top?auth=",
|
"oi_top_api_url": "http://x.x.x.x:x/api/oi/top?auth=",
|
||||||
"api_server_port": 8080,
|
"api_server_port": 8080,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ type TraderConfig struct {
|
|||||||
// Config 总配置
|
// Config 总配置
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Traders []TraderConfig `json:"traders"`
|
Traders []TraderConfig `json:"traders"`
|
||||||
|
UseDefaultCoins bool `json:"use_default_coins"` // 是否使用默认主流币种列表
|
||||||
CoinPoolAPIURL string `json:"coin_pool_api_url"`
|
CoinPoolAPIURL string `json:"coin_pool_api_url"`
|
||||||
OITopAPIURL string `json:"oi_top_api_url"`
|
OITopAPIURL string `json:"oi_top_api_url"`
|
||||||
APIServerPort int `json:"api_server_port"`
|
APIServerPort int `json:"api_server_port"`
|
||||||
|
|||||||
6
main.go
6
main.go
@@ -34,6 +34,12 @@ func main() {
|
|||||||
log.Printf("✓ 配置加载成功,共%d个trader参赛", len(cfg.Traders))
|
log.Printf("✓ 配置加载成功,共%d个trader参赛", len(cfg.Traders))
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
|
// 设置是否使用默认主流币种
|
||||||
|
pool.SetUseDefaultCoins(cfg.UseDefaultCoins)
|
||||||
|
if cfg.UseDefaultCoins {
|
||||||
|
log.Printf("✓ 已启用默认主流币种列表(BTC、ETH、SOL、BNB、XRP、DOGE、ADA、HYPE)")
|
||||||
|
}
|
||||||
|
|
||||||
// 设置币种池API URL
|
// 设置币种池API URL
|
||||||
if cfg.CoinPoolAPIURL != "" {
|
if cfg.CoinPoolAPIURL != "" {
|
||||||
pool.SetCoinPoolAPI(cfg.CoinPoolAPIURL)
|
pool.SetCoinPoolAPI(cfg.CoinPoolAPIURL)
|
||||||
|
|||||||
@@ -8,20 +8,35 @@ 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
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
CacheDir string
|
CacheDir string
|
||||||
|
UseDefaultCoins bool // 是否使用默认主流币种
|
||||||
}
|
}
|
||||||
|
|
||||||
var coinPoolConfig = CoinPoolConfig{
|
var coinPoolConfig = CoinPoolConfig{
|
||||||
APIURL: "",
|
APIURL: "",
|
||||||
Timeout: 30 * time.Second, // 增加到30秒
|
Timeout: 30 * time.Second, // 增加到30秒
|
||||||
CacheDir: "coin_pool_cache",
|
CacheDir: "coin_pool_cache",
|
||||||
|
UseDefaultCoins: false, // 默认不使用
|
||||||
}
|
}
|
||||||
|
|
||||||
// CoinPoolCache 币种池缓存
|
// CoinPoolCache 币种池缓存
|
||||||
@@ -63,8 +78,25 @@ func SetOITopAPI(apiURL string) {
|
|||||||
oiTopConfig.APIURL = apiURL
|
oiTopConfig.APIURL = apiURL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetUseDefaultCoins 设置是否使用默认主流币种
|
||||||
|
func SetUseDefaultCoins(useDefault bool) {
|
||||||
|
coinPoolConfig.UseDefaultCoins = useDefault
|
||||||
|
}
|
||||||
|
|
||||||
// GetCoinPool 获取币种池列表(带重试和缓存机制)
|
// GetCoinPool 获取币种池列表(带重试和缓存机制)
|
||||||
func GetCoinPool() ([]CoinInfo, error) {
|
func GetCoinPool() ([]CoinInfo, error) {
|
||||||
|
// 优先检查是否启用默认币种列表
|
||||||
|
if coinPoolConfig.UseDefaultCoins {
|
||||||
|
log.Printf("✓ 已启用默认主流币种列表")
|
||||||
|
return convertSymbolsToCoins(defaultMainstreamCoins), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查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 +131,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 +354,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 +412,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 +452,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