11点涨停逻辑变更为10点

This commit is contained in:
2026-05-12 17:23:53 +08:00
parent faf535d889
commit 81dc55baaf
3 changed files with 33 additions and 72 deletions
@@ -2,6 +2,7 @@ package service
import ( import (
"math" "math"
"strconv"
"strings" "strings"
"level_go/internal/model" "level_go/internal/model"
@@ -193,7 +194,7 @@ func buildLimitBreakNextPerformanceStock(row limitBreakNextPerformanceRow) model
if row.FirstTime != nil { if row.FirstTime != nil {
item.FirstTime = formatLimitTime(*row.FirstTime) item.FirstTime = formatLimitTime(*row.FirstTime)
} }
item.BreakTimeBefore1100 = isLimitBreakTimeBeforeEleven(item.FirstTime) item.BreakTimeBefore1100 = isLimitBreakTimeBeforeTen(item.FirstTime)
if row.TPreClose != nil && *row.TPreClose > 0 { if row.TPreClose != nil && *row.TPreClose > 0 {
// T 日开盘涨幅以 T 日前收为基准,低于 101% 用于筛选低开/小幅高开炸板。 // T 日开盘涨幅以 T 日前收为基准,低于 101% 用于筛选低开/小幅高开炸板。
item.TOpenPctChg = pctChangePtr(row.TOpen, *row.TPreClose) item.TOpenPctChg = pctChangePtr(row.TOpen, *row.TPreClose)
@@ -251,12 +252,38 @@ func formatLimitTime(value string) string {
return timeText[0:2] + ":" + timeText[2:4] + ":" + timeText[4:6] return timeText[0:2] + ":" + timeText[2:4] + ":" + timeText[4:6]
} }
// isLimitBreakTimeBeforeEleven 判断炸板时间是否早于 11:00。 // isLimitBreakTimeBeforeTen 判断炸板时间是否早于 10:00。
// //
// 空时间在当前业务中视为满足条件,保持历史接口行为。 // 空时间在当前业务中视为满足条件,保持历史接口行为。
func isLimitBreakTimeBeforeEleven(limitTime string) bool { func isLimitBreakTimeBeforeTen(limitTime string) bool {
if strings.TrimSpace(limitTime) == "" { if strings.TrimSpace(limitTime) == "" {
return true return true
} }
return isBeforeEleven(&limitTime)
timeText := formatLimitTime(limitTime)
parts := strings.Split(timeText, ":")
if len(parts) < 2 || len(parts) > 3 {
return false
}
hour, err := strconv.Atoi(parts[0])
if err != nil {
return false
}
minute, err := strconv.Atoi(parts[1])
if err != nil {
return false
}
second := 0
if len(parts) == 3 {
second, err = strconv.Atoi(parts[2])
if err != nil {
return false
}
}
if hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59 {
return false
}
return hour < 10
} }
@@ -1,66 +0,0 @@
package service
import "testing"
// TestBuildLimitBreakNextPerformanceStockIntradayProfitableUsesTHigh 验证 T+1 盘中可盈利口径。
//
// 业务要求用 T+1 最高价覆盖 T 日最高价来判断是否可解套,而不是只和 T 日收盘价比较。
func TestBuildLimitBreakNextPerformanceStockIntradayProfitableUsesTHigh(t *testing.T) {
tClose := 9.50
tHigh := 10.00
tests := []struct {
name string
nextHigh *float64
want *bool
}{
{
name: "next high below T high cannot cover T high buy loss",
nextHigh: float64Ptr(9.99),
want: boolPtr(false),
},
{
name: "next high equal T high covers T high buy loss",
nextHigh: float64Ptr(10.00),
want: boolPtr(true),
},
{
name: "missing next high returns nil",
nextHigh: nil,
want: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
item := buildLimitBreakNextPerformanceStock(limitBreakNextPerformanceRow{
TClose: &tClose,
THigh: &tHigh,
NextHigh: tt.nextHigh,
})
if tt.want == nil {
if item.NextIntradayProfitable != nil {
t.Fatalf("NextIntradayProfitable = %v, want nil", *item.NextIntradayProfitable)
}
return
}
if item.NextIntradayProfitable == nil {
t.Fatalf("NextIntradayProfitable = nil, want %v", *tt.want)
}
if *item.NextIntradayProfitable != *tt.want {
t.Fatalf("NextIntradayProfitable = %v, want %v", *item.NextIntradayProfitable, *tt.want)
}
})
}
}
// float64Ptr 是测试用指针辅助函数。
func float64Ptr(value float64) *float64 {
return &value
}
// boolPtr 是测试用指针辅助函数。
func boolPtr(value bool) *bool {
return &value
}
+2 -2
View File
@@ -167,9 +167,9 @@ candidate AS (
LEFT JOIN limit_list_d ppl LEFT JOIN limit_list_d ppl
ON ppl.ts_code = pl.ts_code AND ppl.trade_date = c.previous_two_trade_date AND ppl.` + "`limit`" + ` = 'U' ON ppl.ts_code = pl.ts_code AND ppl.trade_date = c.previous_two_trade_date AND ppl.` + "`limit`" + ` = 'U'
INNER JOIN stock_daily d INNER JOIN stock_daily d
ON d.ts_code = pl.ts_code AND d.trade_date = c.trade_date ON d.ts_code = pl.ts_code COLLATE utf8mb4_0900_ai_ci AND d.trade_date = c.trade_date
LEFT JOIN stock_daily nd LEFT JOIN stock_daily nd
ON nd.ts_code = pl.ts_code AND nd.trade_date = c.next_trade_date ON nd.ts_code = pl.ts_code COLLATE utf8mb4_0900_ai_ci AND nd.trade_date = c.next_trade_date
LEFT JOIN stock_basic sb LEFT JOIN stock_basic sb
ON sb.ts_code = pl.ts_code COLLATE utf8mb4_unicode_ci ON sb.ts_code = pl.ts_code COLLATE utf8mb4_unicode_ci
WHERE c.trade_date BETWEEN ? AND ? WHERE c.trade_date BETWEEN ? AND ?