From 42b227083900f80cf6c2da9a163b0acb4764b225 Mon Sep 17 00:00:00 2001 From: fish Date: Sat, 4 Jul 2026 11:29:56 +0800 Subject: [PATCH] =?UTF-8?q?chore(stock):=20=E8=B0=83=E8=AF=95=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=A2=9E=E5=8A=A0=E4=BA=A4=E6=98=93=E6=89=80=E5=88=86?= =?UTF-8?q?=E7=BB=84=E4=B8=8E=E6=B6=A8=E8=B7=8C=E5=88=86=E5=B8=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/handlers/stock.go | 92 +++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 14 deletions(-) diff --git a/backend/internal/handlers/stock.go b/backend/internal/handlers/stock.go index 2e367d8..acd67af 100644 --- a/backend/internal/handlers/stock.go +++ b/backend/internal/handlers/stock.go @@ -155,21 +155,45 @@ func (h *StockHandler) TriggerSync(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": true, "records_count": count}) } +type distributionRow struct { + Label string `json:"label"` + Count int64 `json:"count"` +} + +type distributionScan struct { + SH int64 + SZ int64 + BJ int64 + Up0_3 int64 + Up3_5 int64 + Up5_7 int64 + Up7_10 int64 + Up10 int64 + Down0_3 int64 + Down3_5 int64 + Down5_7 int64 + Down7_10 int64 + Down10 int64 +} + type debugStatsResponse struct { - TradeDate string `json:"trade_date"` - Total int64 `json:"total"` - IndexCount int64 `json:"index_count"` - SuspendedCount int64 `json:"suspended_count"` - UpByPrice int64 `json:"up_by_price"` - DownByPrice int64 `json:"down_by_price"` - FlatByPrice int64 `json:"flat_by_price"` - UpByPct int64 `json:"up_by_pct"` - DownByPct int64 `json:"down_by_pct"` - FlatByPct int64 `json:"flat_by_pct"` - FlatSamples []stockRow `json:"flat_samples"` - BoundarySamples []stockRow `json:"boundary_samples"` - UpBoundarySamples []stockRow `json:"up_boundary_samples"` - DownBoundarySamples []stockRow `json:"down_boundary_samples"` + TradeDate string `json:"trade_date"` + Total int64 `json:"total"` + IndexCount int64 `json:"index_count"` + SuspendedCount int64 `json:"suspended_count"` + UpByPrice int64 `json:"up_by_price"` + DownByPrice int64 `json:"down_by_price"` + FlatByPrice int64 `json:"flat_by_price"` + UpByPct int64 `json:"up_by_pct"` + DownByPct int64 `json:"down_by_pct"` + FlatByPct int64 `json:"flat_by_pct"` + ExchangeCounts map[string]int64 `json:"exchange_counts"` + UpDistribution []distributionRow `json:"up_distribution"` + DownDistribution []distributionRow `json:"down_distribution"` + FlatSamples []stockRow `json:"flat_samples"` + BoundarySamples []stockRow `json:"boundary_samples"` + UpBoundarySamples []stockRow `json:"up_boundary_samples"` + DownBoundarySamples []stockRow `json:"down_boundary_samples"` } // DebugStats 返回最新交易日的详细统计与边界样本,便于对齐第三方口径。 @@ -214,6 +238,46 @@ func (h *StockHandler) DebugStats(c *gin.Context) { stats.TradeDate = latestDate.Format("2006-01-02") + var dist distributionScan + h.DB.WithContext(ctx).Model(&models.StockDailyQuote{}). + Select(` + SUM(CASE WHEN symbol LIKE '%.SH' THEN 1 ELSE 0 END) AS sh, + SUM(CASE WHEN symbol LIKE '%.SZ' THEN 1 ELSE 0 END) AS sz, + SUM(CASE WHEN symbol LIKE '%.BJ' THEN 1 ELSE 0 END) AS bj, + SUM(CASE WHEN change_pct > 0 AND change_pct <= 0.03 THEN 1 ELSE 0 END) AS up_0_3, + SUM(CASE WHEN change_pct > 0.03 AND change_pct <= 0.05 THEN 1 ELSE 0 END) AS up_3_5, + SUM(CASE WHEN change_pct > 0.05 AND change_pct <= 0.07 THEN 1 ELSE 0 END) AS up_5_7, + SUM(CASE WHEN change_pct > 0.07 AND change_pct <= 0.10 THEN 1 ELSE 0 END) AS up_7_10, + SUM(CASE WHEN change_pct > 0.10 THEN 1 ELSE 0 END) AS up_10, + SUM(CASE WHEN change_pct < 0 AND change_pct >= -0.03 THEN 1 ELSE 0 END) AS down_0_3, + SUM(CASE WHEN change_pct < -0.03 AND change_pct >= -0.05 THEN 1 ELSE 0 END) AS down_3_5, + SUM(CASE WHEN change_pct < -0.05 AND change_pct >= -0.07 THEN 1 ELSE 0 END) AS down_5_7, + SUM(CASE WHEN change_pct < -0.07 AND change_pct >= -0.10 THEN 1 ELSE 0 END) AS down_7_10, + SUM(CASE WHEN change_pct < -0.10 THEN 1 ELSE 0 END) AS down_10 + `). + Where(baseWhere, latestDate, idxList). + Scan(&dist) + + stats.ExchangeCounts = map[string]int64{ + "sh": dist.SH, + "sz": dist.SZ, + "bj": dist.BJ, + } + stats.UpDistribution = []distributionRow{ + {Label: "0~3%", Count: dist.Up0_3}, + {Label: "3~5%", Count: dist.Up3_5}, + {Label: "5~7%", Count: dist.Up5_7}, + {Label: "7~10%", Count: dist.Up7_10}, + {Label: ">10%", Count: dist.Up10}, + } + stats.DownDistribution = []distributionRow{ + {Label: "3~0%", Count: dist.Down0_3}, + {Label: "5~3%", Count: dist.Down3_5}, + {Label: "7~5%", Count: dist.Down5_7}, + {Label: "10~7%", Count: dist.Down7_10}, + {Label: ">10%", Count: dist.Down10}, + } + var flatSamples []stockRow h.DB.WithContext(ctx).Model(&models.StockDailyQuote{}). Select("symbol, name, close, prev_close, change_pct").