From b9f522b10143ef1908ff0958d8d4e3865b943176 Mon Sep 17 00:00:00 2001 From: yanweidong Date: Mon, 9 Feb 2026 18:28:00 +0800 Subject: [PATCH] add mock order. --- cmd/main/main.go | 1 + cmd/{cli => selector}/main.go | 3 +- etc/gostock_dev.yaml | 2 +- etc/gostock_prod.yaml | 2 +- etc/gostock_test.yaml | 2 +- internal/logic/mock/order.go | 81 +++++++++++++++++++++++++++++++ internal/logic/restful/starter.go | 43 ++++++++++++++++ internal/models/mock_position.go | 14 +++--- internal/models/strat_model.go | 4 +- scripts/build.sh | 2 +- 10 files changed, 141 insertions(+), 13 deletions(-) rename cmd/{cli => selector}/main.go (96%) create mode 100644 internal/logic/mock/order.go create mode 100644 internal/logic/restful/starter.go diff --git a/cmd/main/main.go b/cmd/main/main.go index 9f75d9d..224e7be 100644 --- a/cmd/main/main.go +++ b/cmd/main/main.go @@ -30,6 +30,7 @@ func main() { app.Use(middleware.Cors()) app.Use(gin.Recovery()) app.GET("/", restful.Ping) + app.GET("/start/strategy", restful.Starter) // 启动HTTP服务器 err := app.Run(fmt.Sprintf(":%s", config.Spec.Port)) diff --git a/cmd/cli/main.go b/cmd/selector/main.go similarity index 96% rename from cmd/cli/main.go rename to cmd/selector/main.go index 2700962..bd63206 100644 --- a/cmd/cli/main.go +++ b/cmd/selector/main.go @@ -22,9 +22,10 @@ func main() { config.New(ServiceKey) impl.NewImpl() + ymd := models.GetYmd() for _, code := range strategy.GetStocks() { strategy.InitCacheByCode(code) - model := models.NewStratModel("selector", code) + model := models.NewStratModel("selector", code, ymd) stratRule := rule.NewRule(model) { stratRule.RunUpDate(strategy.Cache[code].Basic.ListDate) diff --git a/etc/gostock_dev.yaml b/etc/gostock_dev.yaml index d22b043..75eff70 100644 --- a/etc/gostock_dev.yaml +++ b/etc/gostock_dev.yaml @@ -1,5 +1,5 @@ Service: gostock -Port: 14299 +Port: 13499 Databases: Driver: postgres diff --git a/etc/gostock_prod.yaml b/etc/gostock_prod.yaml index dea0cff..81464d7 100644 --- a/etc/gostock_prod.yaml +++ b/etc/gostock_prod.yaml @@ -1,5 +1,5 @@ Service: gostock -Port: 14299 +Port: 13499 Databases: Driver: postgres diff --git a/etc/gostock_test.yaml b/etc/gostock_test.yaml index dea0cff..81464d7 100644 --- a/etc/gostock_test.yaml +++ b/etc/gostock_test.yaml @@ -1,5 +1,5 @@ Service: gostock -Port: 14299 +Port: 13499 Databases: Driver: postgres diff --git a/internal/logic/mock/order.go b/internal/logic/mock/order.go new file mode 100644 index 0000000..d24c285 --- /dev/null +++ b/internal/logic/mock/order.go @@ -0,0 +1,81 @@ +package mock + +import ( + "log" + + "git.apinb.com/bsm-sdk/core/utils" + "git.apinb.com/quant/gostock/internal/impl" + "git.apinb.com/quant/gostock/internal/models" +) + +func Run(key string, ymd int) { + log.Println("Run Mock Order.") + var stocks []*models.StratModel + impl.DBService.Where("strat_key=? and ymd=? and ai_score>=?", key, ymd, 5).Find(&stocks) + if len(stocks) == 0 { + log.Println("No data to process.") + return + } + for _, s := range stocks { + log.Printf("Processing %s %s", s.Code, s.StratKey) + + // 1.判断是否有持仓 + var cnt int64 + impl.DBService.Model(&models.MockPosition{}).Where("code=? and status=0", s.Code).Count(&cnt) + if cnt > 0 { + log.Printf("Position exists for %s, skip.", s.Code) + continue + } + // 2.获取当日收盘最新价 + var latestPrice float64 + impl.DBService.Model(&models.StockDaily{}).Where("ts_code=? and trade_date=?", s.Code, ymd).Select("close").Scan(&latestPrice) + if latestPrice == 0 { + log.Printf("No data for %s, skip.", s.Code) + continue + } + + // 3.开仓 + newOpenPrice := utils.FloatRound(latestPrice*1.005, 2) // 默认开仓价为收盘价+0.5%的滑点 + log.Printf("Latest price for %s is %f,open %f", s.Code, latestPrice, newOpenPrice) + impl.DBService.Model(&models.MockPosition{}).Create(&models.MockPosition{ + Code: s.Code, + OpenPrice: newOpenPrice, + Pnl: 0, + PnlRate: 0, + Status: 0, + }) + } +} + +func CheckClose() { + log.Println("Check Close Mock Order.") + var positions []*models.MockPosition + impl.DBService.Where("status=0").Find(&positions) + for _, p := range positions { + var item models.StockDaily + err := impl.DBService.Model(&models.StockDaily{}).Where("ts_code=?", p.Code).Order("id desc").Limit(1).First(&item).Error + if err != nil { + log.Printf("No data for %s, skip.", p.Code) + continue + } + + // 1.通过最高价计算平仓价格 + newClosePrice := utils.FloatRound(item.High*0.99, 2) + log.Printf("Latest price for %s is %f,close %f", p.Code, item.High, newClosePrice) + + // 2.计算盈亏 + pnl := utils.FloatRound(newClosePrice-p.OpenPrice, 2) + pnlRate := utils.FloatRound(p.Pnl/p.OpenPrice*100, 2) + log.Printf("Pnl for %s is %f,rate %f", p.Code, pnl, pnlRate) + // 3.判断盈亏超过20%,才确定平仓 + if pnlRate >= 20 { + impl.DBService.Model(&models.MockPosition{}).Where("id=?", p.ID).Updates(map[string]any{ + "close_price": newClosePrice, + "pnl": pnl, + "pnl_rate": pnlRate, + "status": 1, + }) + + } + } +} diff --git a/internal/logic/restful/starter.go b/internal/logic/restful/starter.go new file mode 100644 index 0000000..52222e1 --- /dev/null +++ b/internal/logic/restful/starter.go @@ -0,0 +1,43 @@ +package restful + +import ( + "log" + + "git.apinb.com/quant/gostock/internal/logic/mock" + "git.apinb.com/quant/gostock/internal/logic/strategy" + "git.apinb.com/quant/gostock/internal/logic/strategy/rule" + "git.apinb.com/quant/gostock/internal/models" + "github.com/gin-gonic/gin" +) + +func Starter(ctx *gin.Context) { + log.Println("Strategy START.") + ymd := models.GetYmd() + for _, code := range strategy.GetStocks() { + strategy.InitCacheByCode(code) + model := models.NewStratModel("selector", code, ymd) + stratRule := rule.NewRule(model) + { + stratRule.RunUpDate(strategy.Cache[code].Basic.ListDate) + stratRule.RunST(strategy.Cache[code].Basic.Name) + stratRule.RunIndustry(strategy.Cache[code].Basic.Industry) + stratRule.RunPrice(code) + stratRule.RunAmount(code) + stratRule.RunRoe(code) + stratRule.RunRsi(code) + + // 过滤无需AI分析 + if model.StScore > 0 && model.IndustryScore > 0 && model.GtPrice > 0 && model.GtAmount > 0 && model.GtRoe > 0 && model.ScoreRsi > 0 { + model.AiScore = 0 // 待分析 + } else { + model.AiScore = -2 + model.AddDesc("无需AI分析") + } + } + model.Save() + } + + strategy.BootAiStart("selector", ymd) + log.Println("Strategy END.") + mock.Run("selector", ymd) +} diff --git a/internal/models/mock_position.go b/internal/models/mock_position.go index 9cea2c1..5a22e30 100644 --- a/internal/models/mock_position.go +++ b/internal/models/mock_position.go @@ -1,11 +1,13 @@ package models +import "gorm.io/gorm" + type MockPosition struct { gorm.Model - Code string - OpenPrice float64 + Code string + OpenPrice float64 ClosePrice float64 - Pnl float64 - PnlRate float64 - Status int -} \ No newline at end of file + Pnl float64 + PnlRate float64 + Status int `default:"0"` +} diff --git a/internal/models/strat_model.go b/internal/models/strat_model.go index 6fab146..2d85734 100644 --- a/internal/models/strat_model.go +++ b/internal/models/strat_model.go @@ -52,10 +52,10 @@ func (StratModel) TableName() string { return "strat_model" } -func NewStratModel(key, code string) *StratModel { +func NewStratModel(key, code string, ymd int) *StratModel { obj := StratModel{ StratKey: key, - Ymd: GetYmd(), + Ymd: ymd, Code: code, } return &obj diff --git a/scripts/build.sh b/scripts/build.sh index 49660e6..4534df3 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,5 +1,5 @@ #!/bin/bash -GOARCH=amd64 GOOS=linux go build -o ../builds/gostock ./cmd/cli/main.go +GOARCH=amd64 GOOS=linux go build -o ../builds/gostock ./cmd/main/main.go nohup ./gostock > /data/app/logs/gostock.log 2>&1 & \ No newline at end of file