mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-06 20:41:14 +08:00
Initial commit: NOFX AI Trading System
- Multi-AI competition mode (Qwen vs DeepSeek) - Binance Futures integration - AI self-learning mechanism - Professional web dashboard - Complete risk management system
This commit is contained in:
160
manager/trader_manager.go
Normal file
160
manager/trader_manager.go
Normal file
@@ -0,0 +1,160 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"nofx/config"
|
||||
"nofx/trader"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TraderManager 管理多个trader实例
|
||||
type TraderManager struct {
|
||||
traders map[string]*trader.AutoTrader // key: trader ID
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// NewTraderManager 创建trader管理器
|
||||
func NewTraderManager() *TraderManager {
|
||||
return &TraderManager{
|
||||
traders: make(map[string]*trader.AutoTrader),
|
||||
}
|
||||
}
|
||||
|
||||
// AddTrader 添加一个trader
|
||||
func (tm *TraderManager) AddTrader(cfg config.TraderConfig, coinPoolURL string, maxDailyLoss, maxDrawdown float64, stopTradingMinutes int) error {
|
||||
tm.mu.Lock()
|
||||
defer tm.mu.Unlock()
|
||||
|
||||
if _, exists := tm.traders[cfg.ID]; exists {
|
||||
return fmt.Errorf("trader ID '%s' 已存在", cfg.ID)
|
||||
}
|
||||
|
||||
// 构建AutoTraderConfig
|
||||
traderConfig := trader.AutoTraderConfig{
|
||||
ID: cfg.ID,
|
||||
Name: cfg.Name,
|
||||
AIModel: cfg.AIModel,
|
||||
BinanceAPIKey: cfg.BinanceAPIKey,
|
||||
BinanceSecretKey: cfg.BinanceSecretKey,
|
||||
CoinPoolAPIURL: coinPoolURL,
|
||||
UseQwen: cfg.AIModel == "qwen",
|
||||
DeepSeekKey: cfg.DeepSeekKey,
|
||||
QwenKey: cfg.QwenKey,
|
||||
ScanInterval: cfg.GetScanInterval(),
|
||||
InitialBalance: cfg.InitialBalance,
|
||||
MaxDailyLoss: maxDailyLoss,
|
||||
MaxDrawdown: maxDrawdown,
|
||||
StopTradingTime: time.Duration(stopTradingMinutes) * time.Minute,
|
||||
}
|
||||
|
||||
// 创建trader实例
|
||||
at, err := trader.NewAutoTrader(traderConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("创建trader失败: %w", err)
|
||||
}
|
||||
|
||||
tm.traders[cfg.ID] = at
|
||||
log.Printf("✓ Trader '%s' (%s) 已添加", cfg.Name, cfg.AIModel)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTrader 获取指定ID的trader
|
||||
func (tm *TraderManager) GetTrader(id string) (*trader.AutoTrader, error) {
|
||||
tm.mu.RLock()
|
||||
defer tm.mu.RUnlock()
|
||||
|
||||
t, exists := tm.traders[id]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("trader ID '%s' 不存在", id)
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// GetAllTraders 获取所有trader
|
||||
func (tm *TraderManager) GetAllTraders() map[string]*trader.AutoTrader {
|
||||
tm.mu.RLock()
|
||||
defer tm.mu.RUnlock()
|
||||
|
||||
result := make(map[string]*trader.AutoTrader)
|
||||
for id, t := range tm.traders {
|
||||
result[id] = t
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// GetTraderIDs 获取所有trader ID列表
|
||||
func (tm *TraderManager) GetTraderIDs() []string {
|
||||
tm.mu.RLock()
|
||||
defer tm.mu.RUnlock()
|
||||
|
||||
ids := make([]string, 0, len(tm.traders))
|
||||
for id := range tm.traders {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// StartAll 启动所有trader
|
||||
func (tm *TraderManager) StartAll() {
|
||||
tm.mu.RLock()
|
||||
defer tm.mu.RUnlock()
|
||||
|
||||
log.Println("🚀 启动所有Trader...")
|
||||
for id, t := range tm.traders {
|
||||
go func(traderID string, at *trader.AutoTrader) {
|
||||
log.Printf("▶️ 启动 %s...", at.GetName())
|
||||
if err := at.Run(); err != nil {
|
||||
log.Printf("❌ %s 运行错误: %v", at.GetName(), err)
|
||||
}
|
||||
}(id, t)
|
||||
}
|
||||
}
|
||||
|
||||
// StopAll 停止所有trader
|
||||
func (tm *TraderManager) StopAll() {
|
||||
tm.mu.RLock()
|
||||
defer tm.mu.RUnlock()
|
||||
|
||||
log.Println("⏹ 停止所有Trader...")
|
||||
for _, t := range tm.traders {
|
||||
t.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
// GetComparisonData 获取对比数据
|
||||
func (tm *TraderManager) GetComparisonData() (map[string]interface{}, error) {
|
||||
tm.mu.RLock()
|
||||
defer tm.mu.RUnlock()
|
||||
|
||||
comparison := make(map[string]interface{})
|
||||
traders := make([]map[string]interface{}, 0, len(tm.traders))
|
||||
|
||||
for _, t := range tm.traders {
|
||||
account, err := t.GetAccountInfo()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
status := t.GetStatus()
|
||||
|
||||
traders = append(traders, map[string]interface{}{
|
||||
"trader_id": t.GetID(),
|
||||
"trader_name": t.GetName(),
|
||||
"ai_model": t.GetAIModel(),
|
||||
"total_equity": account["total_equity"],
|
||||
"total_pnl": account["total_pnl"],
|
||||
"total_pnl_pct": account["total_pnl_pct"],
|
||||
"position_count": account["position_count"],
|
||||
"margin_used_pct": account["margin_used_pct"],
|
||||
"call_count": status["call_count"],
|
||||
"is_running": status["is_running"],
|
||||
})
|
||||
}
|
||||
|
||||
comparison["traders"] = traders
|
||||
comparison["count"] = len(traders)
|
||||
|
||||
return comparison, nil
|
||||
}
|
||||
Reference in New Issue
Block a user