Files
nofx/config/config.go
PorunC ac3a2b0e8d Feat: Add configurable leverage settings for BTC/ETH and altcoins (v2.0.3)
- Add LeverageConfig struct with btc_eth_leverage and altcoin_leverage fields
- Set default leverage to 5x (safe for Binance subaccounts)
- Add validation warnings for leverage >5x (subaccount restrictions)
- Update config.json.example with leverage configuration

Breaking changes:
- None (backward compatible with default 5x leverage)

Migration:
- Existing configs will auto-default to 5x leverage (safe)
- Main accounts can increase to 20x (altcoins) or 50x (BTC/ETH) in config.json
- Subaccounts must keep leverage ≤5x to avoid trade failures

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: tinkle-community <tinklefund@gmail.com>
2025-10-29 20:29:51 +08:00

131 lines
4.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package config
import (
"encoding/json"
"fmt"
"os"
"time"
)
// TraderConfig 单个trader的配置
type TraderConfig struct {
ID string `json:"id"`
Name string `json:"name"`
AIModel string `json:"ai_model"` // "qwen" or "deepseek"
BinanceAPIKey string `json:"binance_api_key"`
BinanceSecretKey string `json:"binance_secret_key"`
QwenKey string `json:"qwen_key,omitempty"`
DeepSeekKey string `json:"deepseek_key,omitempty"`
InitialBalance float64 `json:"initial_balance"`
ScanIntervalMinutes int `json:"scan_interval_minutes"`
}
// LeverageConfig 杠杆配置
type LeverageConfig struct {
BTCETHLeverage int `json:"btc_eth_leverage"` // BTC和ETH的杠杆倍数主账户建议5-50子账户≤5
AltcoinLeverage int `json:"altcoin_leverage"` // 山寨币的杠杆倍数主账户建议5-20子账户≤5
}
// Config 总配置
type Config struct {
Traders []TraderConfig `json:"traders"`
UseDefaultCoins bool `json:"use_default_coins"` // 是否使用默认主流币种列表
CoinPoolAPIURL string `json:"coin_pool_api_url"`
OITopAPIURL string `json:"oi_top_api_url"`
APIServerPort int `json:"api_server_port"`
MaxDailyLoss float64 `json:"max_daily_loss"`
MaxDrawdown float64 `json:"max_drawdown"`
StopTradingMinutes int `json:"stop_trading_minutes"`
Leverage LeverageConfig `json:"leverage"` // 杠杆配置
}
// LoadConfig 从文件加载配置
func LoadConfig(filename string) (*Config, error) {
data, err := os.ReadFile(filename)
if err != nil {
return nil, fmt.Errorf("读取配置文件失败: %w", err)
}
var config Config
if err := json.Unmarshal(data, &config); err != nil {
return nil, fmt.Errorf("解析配置文件失败: %w", err)
}
// 设置默认值如果use_default_coins未设置为false且没有配置coin_pool_api_url则默认使用默认币种列表
if !config.UseDefaultCoins && config.CoinPoolAPIURL == "" {
config.UseDefaultCoins = true
}
// 验证配置
if err := config.Validate(); err != nil {
return nil, fmt.Errorf("配置验证失败: %w", err)
}
return &config, nil
}
// Validate 验证配置有效性
func (c *Config) Validate() error {
if len(c.Traders) == 0 {
return fmt.Errorf("至少需要配置一个trader")
}
traderIDs := make(map[string]bool)
for i, trader := range c.Traders {
if trader.ID == "" {
return fmt.Errorf("trader[%d]: ID不能为空", i)
}
if traderIDs[trader.ID] {
return fmt.Errorf("trader[%d]: ID '%s' 重复", i, trader.ID)
}
traderIDs[trader.ID] = true
if trader.Name == "" {
return fmt.Errorf("trader[%d]: Name不能为空", i)
}
if trader.AIModel != "qwen" && trader.AIModel != "deepseek" {
return fmt.Errorf("trader[%d]: ai_model必须是 'qwen' 或 'deepseek'", i)
}
if trader.BinanceAPIKey == "" || trader.BinanceSecretKey == "" {
return fmt.Errorf("trader[%d]: 币安API密钥不能为空", i)
}
if trader.AIModel == "qwen" && trader.QwenKey == "" {
return fmt.Errorf("trader[%d]: 使用Qwen时必须配置qwen_key", i)
}
if trader.AIModel == "deepseek" && trader.DeepSeekKey == "" {
return fmt.Errorf("trader[%d]: 使用DeepSeek时必须配置deepseek_key", i)
}
if trader.InitialBalance <= 0 {
return fmt.Errorf("trader[%d]: initial_balance必须大于0", i)
}
if trader.ScanIntervalMinutes <= 0 {
trader.ScanIntervalMinutes = 3 // 默认3分钟
}
}
if c.APIServerPort <= 0 {
c.APIServerPort = 8080 // 默认8080端口
}
// 设置杠杆默认值适配币安子账户限制最大5倍
if c.Leverage.BTCETHLeverage <= 0 {
c.Leverage.BTCETHLeverage = 5 // 默认5倍安全值适配子账户
}
if c.Leverage.BTCETHLeverage > 5 {
fmt.Printf("⚠️ 警告: BTC/ETH杠杆设置为%dx如果使用子账户可能会失败子账户限制≤5x\n", c.Leverage.BTCETHLeverage)
}
if c.Leverage.AltcoinLeverage <= 0 {
c.Leverage.AltcoinLeverage = 5 // 默认5倍安全值适配子账户
}
if c.Leverage.AltcoinLeverage > 5 {
fmt.Printf("⚠️ 警告: 山寨币杠杆设置为%dx如果使用子账户可能会失败子账户限制≤5x\n", c.Leverage.AltcoinLeverage)
}
return nil
}
// GetScanInterval 获取扫描间隔
func (tc *TraderConfig) GetScanInterval() time.Duration {
return time.Duration(tc.ScanIntervalMinutes) * time.Minute
}