fix(stock): 统计涨跌时过滤真停牌股,同步日志记录拉取数量

This commit is contained in:
2026-07-04 11:11:28 +08:00
parent 2d967f21ec
commit 1453088c0b
2 changed files with 11 additions and 5 deletions
+7 -5
View File
@@ -65,6 +65,8 @@ func (h *StockHandler) Overview(c *gin.Context) {
return return
} }
baseWhere := "trade_date = ? AND symbol NOT IN ? AND NOT (volume = 0 AND change_pct = 0)"
var counts marketCounts var counts marketCounts
if err := h.DB.WithContext(ctx).Model(&models.StockDailyQuote{}). if err := h.DB.WithContext(ctx).Model(&models.StockDailyQuote{}).
Select(` Select(`
@@ -73,7 +75,7 @@ func (h *StockHandler) Overview(c *gin.Context) {
SUM(CASE WHEN change_pct < 0 THEN 1 ELSE 0 END) AS down, SUM(CASE WHEN change_pct < 0 THEN 1 ELSE 0 END) AS down,
SUM(CASE WHEN change_pct = 0 THEN 1 ELSE 0 END) AS flat SUM(CASE WHEN change_pct = 0 THEN 1 ELSE 0 END) AS flat
`). `).
Where("trade_date = ? AND symbol NOT IN ?", latestDate, indexSymbolsList()). Where(baseWhere, latestDate, indexSymbolsList()).
Scan(&counts).Error; err != nil { Scan(&counts).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "统计涨跌失败"}) c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "统计涨跌失败"})
return return
@@ -82,12 +84,12 @@ func (h *StockHandler) Overview(c *gin.Context) {
var avgChange float64 var avgChange float64
h.DB.WithContext(ctx).Model(&models.StockDailyQuote{}). h.DB.WithContext(ctx).Model(&models.StockDailyQuote{}).
Select("COALESCE(AVG(change_pct), 0)"). Select("COALESCE(AVG(change_pct), 0)").
Where("trade_date = ? AND symbol NOT IN ?", latestDate, indexSymbolsList()). Where(baseWhere, latestDate, indexSymbolsList()).
Scan(&avgChange) Scan(&avgChange)
indices := h.topRows(ctx, latestDate, "symbol IN ?", indexSymbolsList(), 10, false) indices := h.topRows(ctx, latestDate, "symbol IN ?", indexSymbolsList(), 10, false)
gainers := h.topRows(ctx, latestDate, "symbol NOT IN ?", indexSymbolsList(), 10, true) gainers := h.topRows(ctx, latestDate, "symbol NOT IN ? AND NOT (volume = 0 AND change_pct = 0)", indexSymbolsList(), 10, true)
losers := h.topRows(ctx, latestDate, "symbol NOT IN ?", indexSymbolsList(), 10, false) losers := h.topRows(ctx, latestDate, "symbol NOT IN ? AND NOT (volume = 0 AND change_pct = 0)", indexSymbolsList(), 10, false)
turnover := h.topRowsByAmount(ctx, latestDate) turnover := h.topRowsByAmount(ctx, latestDate)
c.JSON(http.StatusOK, overviewResponse{ c.JSON(http.StatusOK, overviewResponse{
@@ -121,7 +123,7 @@ func (h *StockHandler) topRowsByAmount(ctx context.Context, tradeDate time.Time)
var rows []stockRow var rows []stockRow
h.DB.WithContext(ctx).Model(&models.StockDailyQuote{}). h.DB.WithContext(ctx).Model(&models.StockDailyQuote{}).
Select("symbol, name, close, change_pct, amount"). Select("symbol, name, close, change_pct, amount").
Where("trade_date = ? AND symbol NOT IN ?", tradeDate, indexSymbolsList()). Where("trade_date = ? AND symbol NOT IN ? AND NOT (volume = 0 AND change_pct = 0)", tradeDate, indexSymbolsList()).
Order("amount DESC"). Order("amount DESC").
Limit(10). Limit(10).
Scan(&rows) Scan(&rows)
+4
View File
@@ -3,6 +3,7 @@ package services
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"sync" "sync"
"time" "time"
@@ -87,6 +88,9 @@ func (s *StockSyncService) doSync(ctx context.Context) (int, error) {
return 0, fmt.Errorf("no quotes returned") return 0, fmt.Errorf("no quotes returned")
} }
log.Printf("[stock sync] fetched %d stock quotes from CN_Equity_A, %d index quotes, total %d",
len(stockQuotes), len(indexQuotes), len(quotes))
// 3. 归一化并写入 DB // 3. 归一化并写入 DB
records := make([]models.StockDailyQuote, 0, len(quotes)) records := make([]models.StockDailyQuote, 0, len(quotes))
for _, q := range quotes { for _, q := range quotes {