mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-07 13:00:59 +08:00
fix: OI Top API response parsing and quant data URL validation
- Fix OITopAPIResponse struct to use Code int (0=success) instead of Success bool
- Add all response fields from actual API (time_range_param, rank_type, limit)
- Add {symbol} placeholder validation warning in FetchQuantData
- Add API-level validation in strategy create/update to warn about missing {symbol}
This commit is contained in:
@@ -8,12 +8,27 @@ import (
|
||||
"nofx/market"
|
||||
"nofx/mcp"
|
||||
"nofx/store"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// validateStrategyConfig validates strategy configuration and returns warnings
|
||||
func validateStrategyConfig(config *store.StrategyConfig) []string {
|
||||
var warnings []string
|
||||
|
||||
// Validate quant data URL if enabled
|
||||
if config.Indicators.EnableQuantData && config.Indicators.QuantDataAPIURL != "" {
|
||||
if !strings.Contains(config.Indicators.QuantDataAPIURL, "{symbol}") {
|
||||
warnings = append(warnings, "Quant data URL does not contain {symbol} placeholder. The same data will be used for all coins, which may not be correct.")
|
||||
}
|
||||
}
|
||||
|
||||
return warnings
|
||||
}
|
||||
|
||||
// handleGetStrategies Get strategy list
|
||||
func (s *Server) handleGetStrategies(c *gin.Context) {
|
||||
userID := c.GetString("user_id")
|
||||
@@ -123,10 +138,18 @@ func (s *Server) handleCreateStrategy(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
// Validate configuration and collect warnings
|
||||
warnings := validateStrategyConfig(&req.Config)
|
||||
|
||||
response := gin.H{
|
||||
"id": strategy.ID,
|
||||
"message": "Strategy created successfully",
|
||||
})
|
||||
}
|
||||
if len(warnings) > 0 {
|
||||
response["warnings"] = warnings
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// handleUpdateStrategy Update strategy
|
||||
@@ -181,7 +204,15 @@ func (s *Server) handleUpdateStrategy(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Strategy updated successfully"})
|
||||
// Validate configuration and collect warnings
|
||||
warnings := validateStrategyConfig(&req.Config)
|
||||
|
||||
response := gin.H{"message": "Strategy updated successfully"}
|
||||
if len(warnings) > 0 {
|
||||
response["warnings"] = warnings
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// handleDeleteStrategy Delete strategy
|
||||
|
||||
@@ -215,8 +215,14 @@ func (e *StrategyEngine) FetchQuantData(symbol string) (*QuantData, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Check if URL contains {symbol} placeholder
|
||||
apiURL := e.config.Indicators.QuantDataAPIURL
|
||||
if !strings.Contains(apiURL, "{symbol}") {
|
||||
logger.Infof("⚠️ Quant data URL does not contain {symbol} placeholder, data may be incorrect for %s", symbol)
|
||||
}
|
||||
|
||||
// Replace {symbol} placeholder
|
||||
url := strings.Replace(e.config.Indicators.QuantDataAPIURL, "{symbol}", symbol, -1)
|
||||
url := strings.Replace(apiURL, "{symbol}", symbol, -1)
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
resp, err := client.Get(url)
|
||||
|
||||
@@ -392,12 +392,15 @@ type OIPosition struct {
|
||||
|
||||
// OITopAPIResponse data structure returned by OI Top API
|
||||
type OITopAPIResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Data struct {
|
||||
Positions []OIPosition `json:"positions"`
|
||||
Count int `json:"count"`
|
||||
Exchange string `json:"exchange"`
|
||||
TimeRange string `json:"time_range"`
|
||||
Code int `json:"code"` // 0 = success
|
||||
Data struct {
|
||||
Positions []OIPosition `json:"positions"`
|
||||
Count int `json:"count"`
|
||||
Exchange string `json:"exchange"`
|
||||
TimeRange string `json:"time_range"`
|
||||
TimeRangeParam string `json:"time_range_param"`
|
||||
RankType string `json:"rank_type"`
|
||||
Limit int `json:"limit"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
@@ -494,16 +497,16 @@ func fetchOITop() ([]OIPosition, error) {
|
||||
return nil, fmt.Errorf("OI Top JSON parsing failed: %w", err)
|
||||
}
|
||||
|
||||
if !response.Success {
|
||||
return nil, fmt.Errorf("OI Top API returned failure status")
|
||||
if response.Code != 0 {
|
||||
return nil, fmt.Errorf("OI Top API returned error code: %d", response.Code)
|
||||
}
|
||||
|
||||
if len(response.Data.Positions) == 0 {
|
||||
return nil, fmt.Errorf("OI Top position list is empty")
|
||||
}
|
||||
|
||||
log.Printf("✓ Successfully fetched %d OI Top coins (time range: %s)",
|
||||
len(response.Data.Positions), response.Data.TimeRange)
|
||||
log.Printf("✓ Successfully fetched %d OI Top coins (time range: %s, type: %s)",
|
||||
len(response.Data.Positions), response.Data.TimeRange, response.Data.RankType)
|
||||
return response.Data.Positions, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user