mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-15 08:46:58 +08:00
feat(trader): add automatic balance sync every 30 minutes
## Summary Automatically sync trader's initial_balance when exchange balance changes significantly (>5%), eliminating the need for manual intervention after deposits/withdrawals. ## Changes ### trader/auto_trader.go - Add fields: lastBalanceSyncTime, database, userID - Add autoSyncBalanceIfNeeded() method: * Check every 30 minutes (配合3分钟扫描周期,约10次扫描触发一次) * Query exchange balance via trader.GetBalance() * Update if change >5% * Log changes with emoji indicators - Integrate into runCycle() before trading decisions ### manager/trader_manager.go - Update NewAutoTrader() calls to pass database and userID - Update method signatures: * addTraderFromDB() * AddTraderFromDB() * loadSingleTrader() ## Configuration - Check interval: 30 minutes - Change threshold: 5% - Automatic detection and update ## Benefits ✅ 完全自动化,无需手动调用API ✅ 30分钟检查间隔,及时又不频繁 ✅ 智能判断(变化>5%才更新) ✅ 充值/提现后自动更新initial_balance ✅ 前端P&L显示自动修正 ## Example Logs 🔄 [DS-BF] 开始自动检查余额变化... 🔔 [DS-BF] 检测到余额大幅变化: 693.00 → 3000.00 USDT (333.33%) ✅ [DS-BF] 已自动同步余额到数据库 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -181,7 +181,7 @@ func (tm *TraderManager) LoadTradersFromDatabase(database *config.Database) erro
|
||||
}
|
||||
|
||||
// 添加到TraderManager
|
||||
err = tm.addTraderFromDB(traderCfg, aiModelCfg, exchangeCfg, newsCfg, coinPoolURL, oiTopURL, maxDailyLoss, maxDrawdown, stopTradingMinutes, defaultCoins)
|
||||
err = tm.addTraderFromDB(traderCfg, aiModelCfg, exchangeCfg, newsCfg, coinPoolURL, oiTopURL, maxDailyLoss, maxDrawdown, stopTradingMinutes, defaultCoins, database, traderCfg.UserID)
|
||||
if err != nil {
|
||||
log.Printf("❌ 添加交易员 %s 失败: %v", traderCfg.Name, err)
|
||||
continue
|
||||
@@ -193,7 +193,7 @@ func (tm *TraderManager) LoadTradersFromDatabase(database *config.Database) erro
|
||||
}
|
||||
|
||||
// addTraderFromConfig 内部方法:从配置添加交易员(不加锁,因为调用方已加锁)
|
||||
func (tm *TraderManager) addTraderFromDB(traderCfg *config.TraderRecord, aiModelCfg *config.AIModelConfig, exchangeCfg *config.ExchangeConfig, newsCfg []config.NewsConfig, coinPoolURL, oiTopURL string, maxDailyLoss, maxDrawdown float64, stopTradingMinutes int, defaultCoins []string) error {
|
||||
func (tm *TraderManager) addTraderFromDB(traderCfg *config.TraderRecord, aiModelCfg *config.AIModelConfig, exchangeCfg *config.ExchangeConfig, newsCfg []config.NewsConfig, coinPoolURL, oiTopURL string, maxDailyLoss, maxDrawdown float64, stopTradingMinutes int, defaultCoins []string, database *config.Database, userID string) error {
|
||||
if _, exists := tm.traders[traderCfg.ID]; exists {
|
||||
return fmt.Errorf("trader ID '%s' 已存在", traderCfg.ID)
|
||||
}
|
||||
@@ -273,8 +273,8 @@ func (tm *TraderManager) addTraderFromDB(traderCfg *config.TraderRecord, aiModel
|
||||
traderConfig.DeepSeekKey = aiModelCfg.APIKey
|
||||
}
|
||||
|
||||
// 创建trader实例
|
||||
at, err := trader.NewAutoTrader(traderConfig)
|
||||
// 创建trader实例(传入database和userID用于自动余额同步)
|
||||
at, err := trader.NewAutoTrader(traderConfig, database, userID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("创建trader失败: %w", err)
|
||||
}
|
||||
@@ -298,7 +298,7 @@ func (tm *TraderManager) addTraderFromDB(traderCfg *config.TraderRecord, aiModel
|
||||
// AddTrader 从数据库配置添加trader (移除旧版兼容性)
|
||||
|
||||
// AddTraderFromDB 从数据库配置添加trader
|
||||
func (tm *TraderManager) AddTraderFromDB(traderCfg *config.TraderRecord, aiModelCfg *config.AIModelConfig, exchangeCfg *config.ExchangeConfig, coinPoolURL, oiTopURL string, maxDailyLoss, maxDrawdown float64, stopTradingMinutes int, defaultCoins []string) error {
|
||||
func (tm *TraderManager) AddTraderFromDB(traderCfg *config.TraderRecord, aiModelCfg *config.AIModelConfig, exchangeCfg *config.ExchangeConfig, coinPoolURL, oiTopURL string, maxDailyLoss, maxDrawdown float64, stopTradingMinutes int, defaultCoins []string, database *config.Database, userID string) error {
|
||||
tm.mu.Lock()
|
||||
defer tm.mu.Unlock()
|
||||
|
||||
@@ -379,8 +379,8 @@ func (tm *TraderManager) AddTraderFromDB(traderCfg *config.TraderRecord, aiModel
|
||||
traderConfig.DeepSeekKey = aiModelCfg.APIKey
|
||||
}
|
||||
|
||||
// 创建trader实例
|
||||
at, err := trader.NewAutoTrader(traderConfig)
|
||||
// 创建trader实例(传入database和userID用于自动余额同步)
|
||||
at, err := trader.NewAutoTrader(traderConfig, database, userID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("创建trader失败: %w", err)
|
||||
}
|
||||
@@ -710,7 +710,7 @@ func (tm *TraderManager) LoadUserTraders(database *config.Database, userID strin
|
||||
}
|
||||
|
||||
// 使用现有的方法加载交易员
|
||||
err = tm.loadSingleTrader(traderCfg, aiModelCfg, exchangeCfg, coinPoolURL, oiTopURL, maxDailyLoss, maxDrawdown, stopTradingMinutes, defaultCoins)
|
||||
err = tm.loadSingleTrader(traderCfg, aiModelCfg, exchangeCfg, coinPoolURL, oiTopURL, maxDailyLoss, maxDrawdown, stopTradingMinutes, defaultCoins, database, userID)
|
||||
if err != nil {
|
||||
log.Printf("⚠️ 加载交易员 %s 失败: %v", traderCfg.Name, err)
|
||||
}
|
||||
@@ -720,7 +720,7 @@ func (tm *TraderManager) LoadUserTraders(database *config.Database, userID strin
|
||||
}
|
||||
|
||||
// loadSingleTrader 加载单个交易员(从现有代码提取的公共逻辑)
|
||||
func (tm *TraderManager) loadSingleTrader(traderCfg *config.TraderRecord, aiModelCfg *config.AIModelConfig, exchangeCfg *config.ExchangeConfig, coinPoolURL, oiTopURL string, maxDailyLoss, maxDrawdown float64, stopTradingMinutes int, defaultCoins []string) error {
|
||||
func (tm *TraderManager) loadSingleTrader(traderCfg *config.TraderRecord, aiModelCfg *config.AIModelConfig, exchangeCfg *config.ExchangeConfig, coinPoolURL, oiTopURL string, maxDailyLoss, maxDrawdown float64, stopTradingMinutes int, defaultCoins []string, database *config.Database, userID string) error {
|
||||
// 处理交易币种列表
|
||||
var tradingCoins []string
|
||||
if traderCfg.TradingSymbols != "" {
|
||||
@@ -789,8 +789,8 @@ func (tm *TraderManager) loadSingleTrader(traderCfg *config.TraderRecord, aiMode
|
||||
traderConfig.DeepSeekKey = aiModelCfg.APIKey
|
||||
}
|
||||
|
||||
// 创建trader实例
|
||||
at, err := trader.NewAutoTrader(traderConfig)
|
||||
// 创建trader实例(传入database和userID用于自动余额同步)
|
||||
at, err := trader.NewAutoTrader(traderConfig, database, userID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("创建trader失败: %w", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user