feat: add OI ranking data support and fix trader config update issues

- Add OI ranking data fetching and formatting for AI prompts
- Fix trader update not saving strategy_id, ai_model_id, initial_balance
- Fix AI API key not set for non-qwen/deepseek providers
- Add strategy_id to trader config API response
- Remove old trader from memory before reloading on update
- Clean up unused useTraderActions.ts
This commit is contained in:
tinkle-community
2025-12-12 16:08:21 +08:00
parent f5ae22d85c
commit cc390706d0
16 changed files with 476 additions and 716 deletions
+55 -46
View File
@@ -792,19 +792,24 @@ func (s *Server) handleUpdateTrader(c *gin.Context) {
}
// Update database
logger.Infof("🔄 Updating trader: ID=%s, Name=%s, AIModelID=%s, StrategyID=%s, req.StrategyID=%s",
traderRecord.ID, traderRecord.Name, traderRecord.AIModelID, traderRecord.StrategyID, req.StrategyID)
err = s.store.Trader().Update(traderRecord)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to update trader: %v", err)})
return
}
// Reload traders into memory
// Remove old trader from memory first to ensure fresh config is loaded
s.traderManager.RemoveTrader(traderID)
// Reload traders into memory with fresh config
err = s.traderManager.LoadUserTradersFromStore(s.store, userID)
if err != nil {
logger.Infof("⚠️ Failed to reload user traders into memory: %v", err)
}
logger.Infof("✓ Trader updated successfully: %s (model: %s, exchange: %s)", req.Name, req.AIModelID, req.ExchangeID)
logger.Infof("✓ Trader updated successfully: %s (model: %s, exchange: %s, strategy: %s)", req.Name, req.AIModelID, req.ExchangeID, strategyID)
c.JSON(http.StatusOK, gin.H{
"trader_id": traderID,
@@ -854,54 +859,57 @@ func (s *Server) handleStartTrader(c *gin.Context) {
return
}
trader, err := s.traderManager.GetTrader(traderID)
if err != nil {
// Trader not in memory, try loading from database
logger.Infof("🔄 Trader %s not in memory, trying to load...", traderID)
if loadErr := s.traderManager.LoadUserTradersFromStore(s.store, userID); loadErr != nil {
logger.Infof("❌ Failed to load user traders: %v", loadErr)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load trader: " + loadErr.Error()})
return
}
// Try to get trader again
trader, err = s.traderManager.GetTrader(traderID)
if err != nil {
// Check detailed reason
fullCfg, _ := s.store.Trader().GetFullConfig(userID, traderID)
if fullCfg != nil && fullCfg.Trader != nil {
// Check strategy
if fullCfg.Strategy == nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Trader has no strategy configured, please create a strategy in Strategy Studio and associate it with the trader"})
return
}
// Check AI model
if fullCfg.AIModel == nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Trader's AI model does not exist, please check AI model configuration"})
return
}
if !fullCfg.AIModel.Enabled {
c.JSON(http.StatusBadRequest, gin.H{"error": "Trader's AI model is not enabled, please enable the AI model first"})
return
}
// Check exchange
if fullCfg.Exchange == nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Trader's exchange does not exist, please check exchange configuration"})
return
}
if !fullCfg.Exchange.Enabled {
c.JSON(http.StatusBadRequest, gin.H{"error": "Trader's exchange is not enabled, please enable the exchange first"})
return
}
}
c.JSON(http.StatusNotFound, gin.H{"error": "Failed to load trader, please check AI model, exchange and strategy configuration"})
// Check if trader exists in memory and if it's running
existingTrader, _ := s.traderManager.GetTrader(traderID)
if existingTrader != nil {
status := existingTrader.GetStatus()
if isRunning, ok := status["is_running"].(bool); ok && isRunning {
c.JSON(http.StatusBadRequest, gin.H{"error": "Trader is already running"})
return
}
// Trader exists but is stopped - remove from memory to reload fresh config
logger.Infof("🔄 Removing stopped trader %s from memory to reload config...", traderID)
s.traderManager.RemoveTrader(traderID)
}
// Check if trader is already running
status := trader.GetStatus()
if isRunning, ok := status["is_running"].(bool); ok && isRunning {
c.JSON(http.StatusBadRequest, gin.H{"error": "Trader is already running"})
// Load trader from database (always reload to get latest config)
logger.Infof("🔄 Loading trader %s from database...", traderID)
if loadErr := s.traderManager.LoadUserTradersFromStore(s.store, userID); loadErr != nil {
logger.Infof("❌ Failed to load user traders: %v", loadErr)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load trader: " + loadErr.Error()})
return
}
trader, err := s.traderManager.GetTrader(traderID)
if err != nil {
// Check detailed reason
fullCfg, _ := s.store.Trader().GetFullConfig(userID, traderID)
if fullCfg != nil && fullCfg.Trader != nil {
// Check strategy
if fullCfg.Strategy == nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Trader has no strategy configured, please create a strategy in Strategy Studio and associate it with the trader"})
return
}
// Check AI model
if fullCfg.AIModel == nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Trader's AI model does not exist, please check AI model configuration"})
return
}
if !fullCfg.AIModel.Enabled {
c.JSON(http.StatusBadRequest, gin.H{"error": "Trader's AI model is not enabled, please enable the AI model first"})
return
}
// Check exchange
if fullCfg.Exchange == nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Trader's exchange does not exist, please check exchange configuration"})
return
}
if !fullCfg.Exchange.Enabled {
c.JSON(http.StatusBadRequest, gin.H{"error": "Trader's exchange is not enabled, please enable the exchange first"})
return
}
}
c.JSON(http.StatusNotFound, gin.H{"error": "Failed to load trader, please check AI model, exchange and strategy configuration"})
return
}
@@ -1730,6 +1738,7 @@ func (s *Server) handleGetTraderConfig(c *gin.Context) {
"trader_name": traderConfig.Name,
"ai_model": aiModelID,
"exchange_id": traderConfig.ExchangeID,
"strategy_id": traderConfig.StrategyID,
"initial_balance": traderConfig.InitialBalance,
"scan_interval_minutes": traderConfig.ScanIntervalMinutes,
"btc_eth_leverage": traderConfig.BTCETHLeverage,