diff --git a/cmd/cli/main.go b/cmd/cli/main.go index d1b1e43..d79010b 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -7,7 +7,9 @@ import ( "git.apinb.com/quant/gostock/internal/config" "git.apinb.com/quant/gostock/internal/impl" "git.apinb.com/quant/gostock/internal/logic/strategy" + "git.apinb.com/quant/gostock/internal/logic/strategy/rule" "git.apinb.com/quant/gostock/internal/logic/types" + "git.apinb.com/quant/gostock/internal/models" "github.com/gocarina/gocsv" ) @@ -15,15 +17,26 @@ var ( ServiceKey = "gostock" ) -func main2() { +func main() { log.Println("Hello Cli!") config.New(ServiceKey) impl.NewImpl() - strategy.GenMarkData("601899.SH") + code := "601899.SH" + strategy.InitCacheByCode(code) + model := models.NewStratModel("selector", code) + 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) + + model.Save() } -func main() { +func main2() { log.Println("Hello Cli!") config.New(ServiceKey) impl.NewImpl() diff --git a/internal/logic/strategy/boot.go b/internal/logic/strategy/boot.go index 6d5cddf..c1b7455 100644 --- a/internal/logic/strategy/boot.go +++ b/internal/logic/strategy/boot.go @@ -1,4 +1,5 @@ package strategy func Boot() { + InitCacheByAll() } diff --git a/internal/logic/strategy/data.go b/internal/logic/strategy/data.go index fac25a2..eca093b 100644 --- a/internal/logic/strategy/data.go +++ b/internal/logic/strategy/data.go @@ -8,6 +8,8 @@ import ( "git.apinb.com/quant/gostock/internal/models" ) +var Cache = make(map[string]*StockData) + type StockData struct { Basic models.StockBasic Daily []models.StockDaily @@ -15,6 +17,16 @@ type StockData struct { FinaIndicator []models.StockFinaIndicator } +func InitCacheByAll() { + for _, code := range GetStocks() { + Cache[code] = GetFullData(code) + } +} + +func InitCacheByCode(code string) { + Cache[code] = GetFullData(code) +} + func GetFullData(code string) *StockData { var data StockData impl.DBService.Where("ts_code = ?", code).First(&data.Basic) diff --git a/internal/logic/strategy/filter.go b/internal/logic/strategy/filter.go index d2d5258..f918d3d 100644 --- a/internal/logic/strategy/filter.go +++ b/internal/logic/strategy/filter.go @@ -18,47 +18,6 @@ func MustFilter(basic *models.StockBasic) (bool, *types.ResultData) { Desc: "", Pass: "NOT", } - if re := rule.NewUpDate().Run(basic.ListDate); re.Score <= 0 { - data.Desc = re.Desc - return false, data - } else { - descripts = append(descripts, re.Desc) - } - - if re := rule.NewST().Run(basic.Name); re.Score <= 0 { - data.Desc = re.Desc - return false, data - } else { - descripts = append(descripts, re.Desc) - } - - if re := rule.NewIdustry().Run(basic.Industry); re.Score <= 0 { - data.Desc = re.Desc - return false, data - } else { - descripts = append(descripts, re.Desc) - } - - if re := rule.NewPrice().Run(basic.TsCode); re.Score <= 0 { - data.Desc = re.Desc - return false, data - } else { - descripts = append(descripts, re.Desc) - } - - if re := rule.NewAmount().Run(basic.TsCode); re.Score <= 0 { - data.Desc = re.Desc - return false, data - } else { - descripts = append(descripts, re.Desc) - } - - if re := rule.NewRoe().Run(basic.TsCode); re.Score <= 0 { - data.Desc = re.Desc - return false, data - } else { - descripts = append(descripts, re.Desc) - } // if re := rule.NewRsi(GetArgs(basic.TsCode)).Run(basic.TsCode); re.Score <= 0 { // data.Desc = re.Desc diff --git a/internal/logic/strategy/rule/amount.go b/internal/logic/strategy/rule/amount.go index 9a532bf..87a4325 100644 --- a/internal/logic/strategy/rule/amount.go +++ b/internal/logic/strategy/rule/amount.go @@ -2,9 +2,9 @@ package rule import ( "fmt" + "log" "git.apinb.com/quant/gostock/internal/impl" - "git.apinb.com/quant/gostock/internal/logic/types" "git.apinb.com/quant/gostock/internal/models" ) @@ -13,19 +13,8 @@ var ( MinAmount float64 = 100000 // 万元为单位 ) -type Amount struct { - Key string - Name string -} - -func NewAmount() *Amount { - return &Amount{ - Key: "Amount", - Name: "成交额", - } -} - -func (r *Amount) Run(code string) *types.RuleResult { +func (r *RuleFactory) RunAmount(code string) { + log.Println("RunAmount:", r.Model.Code, "Args:", LastAmountDay, MinAmount) var data []models.StockDaily impl.DBService.Where("ts_code = ?", code).Order("trade_date desc").Limit(LastAmountDay).Find(&data) @@ -39,8 +28,10 @@ func (r *Amount) Run(code string) *types.RuleResult { } if !check { - return &types.RuleResult{Key: r.Key, Name: r.Name, Score: -1, Desc: fmt.Sprintf("最近%d天, 有成交额低于%.2f万元", LastAmountDay, MinAmount)} + r.Model.GtAmount = -1 + r.Model.AddDesc(fmt.Sprintf("最近%d天, 有成交额低于%.2f万元", LastAmountDay, MinAmount)) + return } - return &types.RuleResult{Key: r.Key, Name: r.Name, Score: 1, Desc: fmt.Sprintf("最近%d天, 成交额均高于%.2f万元", LastAmountDay, MinAmount)} + r.Model.GtAmount = 1 } diff --git a/internal/logic/strategy/rule/industry.go b/internal/logic/strategy/rule/industry.go index cb71165..8000426 100644 --- a/internal/logic/strategy/rule/industry.go +++ b/internal/logic/strategy/rule/industry.go @@ -1,9 +1,8 @@ package rule import ( + "log" "strings" - - "git.apinb.com/quant/gostock/internal/logic/types" ) var ( @@ -17,28 +16,19 @@ var ( neutralIndustries = "银行,证券,保险,建筑工程,装修装饰,水泥,其他建材,化工原料,农药化肥,汽车服务,运输设备,旅游服务,酒店餐饮,旅游景点,食品,乳制品,白酒,啤酒,家用电器,家居用品,港口,水运,空运,农业综合,种植业,渔业,多元金融,工程机械,轻工机械,机械基件,机床制造,专用机械,化工机械,电器仪表,塑料,橡胶,化纤,服饰,日用化工,文教休闲,影视音像,广告包装,批发业,商贸代理,其他商业,商品城,电信运营,供气供热,软饮料,红黄酒,公共交通,机场,路桥,水力发电,石油加工,石油开采,石油贸易,园区开发,综合类,林业,特种钢" ) -type Industry struct { - Key string - Name string -} +func (r *RuleFactory) RunIndustry(in string) { + log.Println("RunIndustry:", r.Model.Code, "Args:", in) -func NewIdustry() *Industry { - return &Industry{ - Key: "industry", - Name: "行业", - } -} - -func (r *Industry) Run(in string) *types.RuleResult { - score := 1 - desc := "中性/周期型行业" if strings.Contains(hotIndustries, in) { - score = 2 - desc = "热门行业" + r.Model.IndustryScore = 2 + r.Model.AddDesc("中性/热门行业") + return } else if strings.Contains(sunsetIndustries, in) { - score = -1 - desc = "夕阳行业" + r.Model.IndustryScore = -1 + r.Model.AddDesc("中性/夕阳行业") + return } - return &types.RuleResult{Key: r.Key, Name: r.Name, Score: score, Desc: desc} + r.Model.IndustryScore = 1 + r.Model.AddDesc("中性/周期型行业") } diff --git a/internal/logic/strategy/rule/new.go b/internal/logic/strategy/rule/new.go new file mode 100644 index 0000000..437ab8f --- /dev/null +++ b/internal/logic/strategy/rule/new.go @@ -0,0 +1,13 @@ +package rule + +import "git.apinb.com/quant/gostock/internal/models" + +type RuleFactory struct { + Model *models.StratModel +} + +func NewRule(m *models.StratModel) *RuleFactory { + return &RuleFactory{ + Model: m, + } +} diff --git a/internal/logic/strategy/rule/price.go b/internal/logic/strategy/rule/price.go index 02f3e61..52d3606 100644 --- a/internal/logic/strategy/rule/price.go +++ b/internal/logic/strategy/rule/price.go @@ -2,9 +2,9 @@ package rule import ( "fmt" + "log" "git.apinb.com/quant/gostock/internal/impl" - "git.apinb.com/quant/gostock/internal/logic/types" "git.apinb.com/quant/gostock/internal/models" ) @@ -13,19 +13,8 @@ var ( MinPrice = 5.0 ) -type Price struct { - Key string - Name string -} - -func NewPrice() *Price { - return &Price{ - Key: "Price", - Name: "股价", - } -} - -func (r *Price) Run(code string) *types.RuleResult { +func (r *RuleFactory) RunPrice(code string) { + log.Println("RunPrice:", r.Model.Code, "Args:", LastDay, MinPrice) var data []models.StockDaily impl.DBService.Where("ts_code = ?", code).Order("trade_date desc").Limit(LastDay).Find(&data) @@ -39,8 +28,10 @@ func (r *Price) Run(code string) *types.RuleResult { } if !check { - return &types.RuleResult{Key: r.Key, Name: r.Name, Score: -1, Desc: fmt.Sprintf("最近%d天, 有价格低于%.2f", LastDay, MinPrice)} + r.Model.GtAmount = -1 + r.Model.AddDesc(fmt.Sprintf("最近%d天, 有价格低于%.2f", LastDay, MinPrice)) + return } - return &types.RuleResult{Key: r.Key, Name: r.Name, Score: 1, Desc: fmt.Sprintf("最近%d天, 价格均高于%.2f", LastDay, MinPrice)} + r.Model.GtAmount = 1 } diff --git a/internal/logic/strategy/rule/roe.go b/internal/logic/strategy/rule/roe.go index c7c9cda..68ed557 100644 --- a/internal/logic/strategy/rule/roe.go +++ b/internal/logic/strategy/rule/roe.go @@ -2,10 +2,10 @@ package rule import ( "fmt" + "log" "git.apinb.com/bsm-sdk/core/utils" "git.apinb.com/quant/gostock/internal/impl" - "git.apinb.com/quant/gostock/internal/logic/types" "git.apinb.com/quant/gostock/internal/models" ) @@ -13,31 +13,26 @@ var ( MinRoe float64 = 0 ) -type Roe struct { - Key string - Name string -} - -func NewRoe() *Roe { - return &Roe{ - Key: "Roe", - Name: "年化净资产收益率", - } -} - -func (r *Roe) Run(code string) *types.RuleResult { +func (r *RuleFactory) RunRoe(code string) { + log.Println("RunRoe:", r.Model.Code) var data models.StockFinaIndicator err := impl.DBService.Where("ts_code = ?", code).Order("period desc").Limit(1).First(&data).Error if err != nil { - return &types.RuleResult{Key: r.Key, Name: r.Name, Score: -1, Desc: "最近无财报,无ROE值!"} + r.Model.GtAmount = -1 + r.Model.AddDesc("最近无财报,无ROE值!") + return } data.Roe = utils.FloatRound(data.Roe, 2) if data.Roe < MinRoe { - return &types.RuleResult{Key: r.Key, Name: r.Name, Score: -1, Desc: fmt.Sprintf("ROE=%.2f 低于%.2f", data.Roe, MinRoe)} + r.Model.GtAmount = -1 + r.Model.AddDesc(fmt.Sprintf("ROE=%.2f 低于%.2f", data.Roe, MinRoe)) + return } - return &types.RuleResult{Key: r.Key, Name: r.Name, Score: 1, Desc: fmt.Sprintf("ROE=%.2f 高于%.2f", data.Roe, MinRoe)} + r.Model.GtAmount = 1 + r.Model.AddDesc(fmt.Sprintf("ROE=%.2f 高于%.2f", data.Roe, MinRoe)) + return } diff --git a/internal/logic/strategy/rule/st.go b/internal/logic/strategy/rule/st.go index 034189d..0fa5ec1 100644 --- a/internal/logic/strategy/rule/st.go +++ b/internal/logic/strategy/rule/st.go @@ -1,27 +1,17 @@ package rule import ( + "log" "strings" - - "git.apinb.com/quant/gostock/internal/logic/types" ) -type ST struct { - Key string - Name string -} - -func NewST() *ST { - return &ST{ - Key: "ST", - Name: "ST", - } -} - -func (r *ST) Run(in string) *types.RuleResult { +func (r *RuleFactory) RunST(in string) { + log.Println("RunST:", r.Model.Code, "Args:", in) if strings.Contains(in, "ST") { - return &types.RuleResult{Key: r.Key, Name: r.Name, Score: -1, Desc: "有退市风险"} + r.Model.StScore = -1 + r.Model.AddDesc("有退市风险") + return } - return &types.RuleResult{Key: r.Key, Name: r.Name, Score: 1, Desc: "无退市风险"} + r.Model.StScore = 1 } diff --git a/internal/logic/strategy/rule/up_date.go b/internal/logic/strategy/rule/up_date.go index cb17a36..6090217 100644 --- a/internal/logic/strategy/rule/up_date.go +++ b/internal/logic/strategy/rule/up_date.go @@ -1,35 +1,25 @@ package rule import ( + "log" "time" - - "git.apinb.com/quant/gostock/internal/logic/types" ) -type UpDate struct { - Key string - Name string -} - -func NewUpDate() *UpDate { - return &UpDate{ - Key: "UpDate", - Name: "上市时间", - } -} - -func (r *UpDate) Run(lastdate string) *types.RuleResult { +func (r *RuleFactory) RunUpDate(lastdate string) { + log.Println("RunUpDate:", r.Model.Code, "Args:", lastdate) // 计算上市不足半年的股票 if lastdate == "" { - return &types.RuleResult{Key: r.Key, Name: r.Name, Score: -1, Desc: "无上市时间"} + r.Model.UpDateDay = -1 + r.Model.AddDesc("无上市时间") + return } lastDate, err := time.Parse("20060102", lastdate) if err != nil { - return &types.RuleResult{Key: r.Key, Name: r.Name, Score: -1, Desc: "上市时间格式错误"} + r.Model.UpDateDay = -1 + r.Model.AddDesc("上市时间格式错误") + return } - if time.Now().Sub(lastDate) < time.Hour*24*365/2 { - return &types.RuleResult{Key: r.Key, Name: r.Name, Score: -1, Desc: "上市时间不足6个月"} - } - return &types.RuleResult{Key: r.Key, Name: r.Name, Score: 1, Desc: "上市超过半年"} + daysDiff := int(time.Since(lastDate).Hours() / 24) + r.Model.UpDateDay = daysDiff } diff --git a/internal/models/strat_model.go b/internal/models/strat_model.go index e3accec..e829d2b 100644 --- a/internal/models/strat_model.go +++ b/internal/models/strat_model.go @@ -15,13 +15,13 @@ type StratModel struct { StratKey string Ymd int Code string - UpDateMonth int //上市时间,月数 + UpDateDay int //上市时间,天数 IndustryScore int // 行业分组 - IsSt int + StScore int GtAmount int // 每日交易额大于设定值 GtPrice int // 最近20日交易日价格大于设定值 GtRoe int // ROE 是否大于设定值 - + Desc string } func init() { @@ -42,6 +42,10 @@ func NewStratModel(key, code string) *StratModel { return &obj } +func (s *StratModel) AddDesc(d string) { + s.Desc = s.Desc + "||" + d +} + func (s *StratModel) Save() error { var cnt int64 impl.DBService.Model(&StratModel{}).Where("strat_key=? and ymd=? and code=?", s.StratKey, s.Ymd, s.Code).Count(&cnt)