init
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"level_go/internal/model"
|
||||
"math"
|
||||
"sort"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type StockService struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func roundTo4(val float64) float64 {
|
||||
return math.Round(val*10000) / 10000
|
||||
}
|
||||
|
||||
func (s *StockService) AnalyzePerformance(startDate, endDate string) ([]model.AnalysisResponse, error) {
|
||||
var results []model.AnalysisResponse
|
||||
|
||||
var limits []struct {
|
||||
TsCode string
|
||||
Name string
|
||||
Open float64
|
||||
High float64
|
||||
}
|
||||
|
||||
// 1. 查找涨停股票
|
||||
query := `
|
||||
SELECT l.ts_code, l.name, d.open, d.high
|
||||
FROM stock_limit_data l
|
||||
LEFT JOIN stock_daily d ON l.ts_code = d.ts_code AND l.trade_date = d.trade_date
|
||||
WHERE l.trade_date = ? AND l.status = 1`
|
||||
|
||||
if err := s.DB.Raw(query, startDate).Scan(&limits).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 2. 分析区间数据
|
||||
for _, stock := range limits {
|
||||
var dailies []model.StockDaily
|
||||
s.DB.Where("ts_code = ? AND trade_date BETWEEN ? AND ?", stock.TsCode, startDate, endDate).
|
||||
Order("trade_date ASC").Find(&dailies)
|
||||
|
||||
if len(dailies) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// A. 找最高点
|
||||
maxPrice := -1.0
|
||||
maxIdx := 0
|
||||
for i, d := range dailies {
|
||||
if d.High >= maxPrice {
|
||||
maxPrice = d.High
|
||||
maxIdx = i
|
||||
}
|
||||
}
|
||||
|
||||
// B. 找最高点后的最低点
|
||||
postData := dailies[maxIdx+1:]
|
||||
var minLow, dropPct, reboundPct float64
|
||||
|
||||
if len(postData) > 0 {
|
||||
minLow = postData[0].Low
|
||||
for _, p := range postData {
|
||||
if p.Low < minLow {
|
||||
minLow = p.Low
|
||||
}
|
||||
}
|
||||
lastClose := postData[len(postData)-1].Close
|
||||
dropPct = roundTo4(((maxPrice - minLow) / maxPrice) * 100)
|
||||
if minLow > 0 {
|
||||
reboundPct = roundTo4(((lastClose - minLow) / minLow) * 100)
|
||||
}
|
||||
}
|
||||
|
||||
results = append(results, model.AnalysisResponse{
|
||||
Code: stock.TsCode,
|
||||
Name: stock.Name,
|
||||
DayOpen: stock.Open,
|
||||
DayHigh: stock.High,
|
||||
MaxHigh: maxPrice,
|
||||
MaxDate: dailies[maxIdx].TradeDate.Format("2006-01-02"),
|
||||
PostMinLow: minLow,
|
||||
DropPct: dropPct,
|
||||
ReboundPct: reboundPct,
|
||||
})
|
||||
}
|
||||
|
||||
// 3. 按降幅排序
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].DropPct > results[j].DropPct
|
||||
})
|
||||
|
||||
return results, nil
|
||||
}
|
||||
Reference in New Issue
Block a user