diff --git a/internal/cron/boot.go b/internal/cron/boot.go index 0a5d8a6..1aa9993 100644 --- a/internal/cron/boot.go +++ b/internal/cron/boot.go @@ -4,7 +4,7 @@ import "git.apinb.com/dataset/stock/internal/logic/a" func Boot() { a.NewApiClient() - a.GetStockBasic() - a.GetLastDaily() - a.GetLastIndicator() + //a.GetStockBasic() + a.GetStockDaily() + //a.GetStockIndicator() } diff --git a/internal/logic/a/basic.go b/internal/logic/a/basic.go new file mode 100644 index 0000000..0ebe851 --- /dev/null +++ b/internal/logic/a/basic.go @@ -0,0 +1,103 @@ +package a + +import ( + "errors" + "log" + "strings" + + "git.apinb.com/dataset/stock/internal/impl" + "git.apinb.com/dataset/stock/internal/models" + "gorm.io/gorm" +) + +func GetStockBasic() { + // 参数 + params := map[string]string{ + "list_status": "L", // 上市状态 L上市 D退市 P暂停上市,默认是L + } + + // 字段 + fields := strings.Split("ts_code,symbol,name,area,industry,fullname,enname,cnspell,market,exchange,list_date,is_hs,act_name,act_ent_type", ",") + + // 根据api 请求对应的接口 + reply, _ := TushareClient.StockBasic(params, fields) + if reply.Code != 0 { + log.Println("ERROR", "GetStockBasic", reply.Code, reply.Msg) + return + } + + for _, item := range reply.Data.Items { + var record models.StockBasic + data := Anys2Strings(item) + + err := impl.DBService.Where("ts_code=?", data[0]).First(&record).Error + if errors.Is(err, gorm.ErrRecordNotFound) { + // create + record = models.StockBasic{ + TsCode: data[0], + Symbol: data[1], + Name: data[2], + Area: data[3], + Industry: data[4], + FullName: data[5], + EnName: data[6], + CnSpell: data[7], + Market: data[8], + Exchange: data[9], + ListDate: data[10], + IsHS: data[11], + ActName: data[12], + ActEntType: data[13], + } + impl.DBService.Create(&record) + } else if err == nil { + // check updated. + upd := make(map[string]any) + if record.Name != data[2] { + upd["name"] = data[2] + } + if record.Area != data[3] { + upd["area"] = data[3] + } + if record.Industry != data[4] { + upd["industry"] = data[4] + } + if record.FullName != data[5] { + upd["full_name"] = data[5] + } + if record.EnName != data[6] { + upd["en_name"] = data[6] + } + if record.CnSpell != data[7] { + upd["cn_spell"] = data[7] + } + if record.Market != data[8] { + upd["market"] = data[8] + } + if record.Exchange != data[9] { + upd["exchange"] = data[9] + } + if record.ListDate != data[10] { + upd["list_date"] = data[10] + } + if record.IsHS != data[11] { + upd["is_hs"] = data[11] + } + if record.ActName != data[12] { + upd["act_name"] = data[12] + } + if record.ActEntType != data[13] { + upd["act_ent_type"] = data[13] + } + if len(upd) > 0 { + impl.DBService.Model(record).Updates(upd) + } + } + } +} + +func GetStockCodes() []string { + var col []string + impl.DBService.Model(&models.StockBasic{}).Pluck("ts_code", &col) + return col +} diff --git a/internal/logic/a/daily.go b/internal/logic/a/daily.go new file mode 100644 index 0000000..31e7b86 --- /dev/null +++ b/internal/logic/a/daily.go @@ -0,0 +1,58 @@ +package a + +import ( + "log" + "time" + + "git.apinb.com/dataset/stock/internal/impl" + "git.apinb.com/dataset/stock/internal/models" +) + +func GetStockDaily() { + s, e := ReturnLastDay() + for _, code := range GetStockCodes() { + params := map[string]string{ + "ts_code": code, + "start_date": s, + "end_date": e, + } + + var cnt int64 + impl.DBService.Model(&models.StockDaily{}).Where("ts_code=? and trade_date in (?,?)", code, s, e).Count(&cnt) + if cnt == 2 { + continue + } + + fields := []string{} + reply, err := TushareClient.Daily(params, fields) + if err != nil { + log.Println("ERROR", "GetStockDaily", err) + return + } + + for _, item := range reply.Data.Items { + var cnt int64 + impl.DBService.Model(&models.StockDaily{}).Where("ts_code=? and trade_date=?", item[0].(string), item[1].(string)).Count(&cnt) + log.Println("++ items") + if cnt == 0 { + impl.DBService.Create(&models.StockDaily{ + TsCode: item[0].(string), + TradeDate: item[1].(string), + Open: item[2].(float64), + High: item[3].(float64), + Low: item[4].(float64), + Close: item[5].(float64), + PreClose: item[6].(float64), + Change: item[7].(float64), + PctChg: item[8].(float64), + Vol: item[9].(float64), + Amount: item[10].(float64), + }) + } + } + + time.Sleep(200 * time.Microsecond) + + } + +} diff --git a/internal/logic/a/indicator.go b/internal/logic/a/indicator.go new file mode 100644 index 0000000..2267713 --- /dev/null +++ b/internal/logic/a/indicator.go @@ -0,0 +1,59 @@ +package a + +import ( + "log" + + "git.apinb.com/dataset/stock/internal/impl" + "git.apinb.com/dataset/stock/internal/models" +) + +func GetStockIndicator() { + s, e := ReturnLastDay() + for _, code := range GetStockCodes() { + params := map[string]string{ + "ts_code": code, + "start_date": s, + "end_date": e, + } + + var cnt int64 + impl.DBService.Model(&models.StockDaily{}).Where("ts_code=? and trade_date in (?,?)", code, s, e).Count(&cnt) + if cnt == 2 { + continue + } + + reply, err := TushareClient.Daily(params, []string{}) + if err != nil { + log.Println("ERROR", "GetStockIndicator", err) + return + } + + for _, item := range reply.Data.Items { + var cnt int64 + impl.DBService.Model(&models.StockIndicator{}).Where("ts_code=? and trade_date=?", item[0].(string), item[1].(string)).Count(&cnt) + if cnt == 0 { + impl.DBService.Create(&models.StockIndicator{ + TsCode: item[0].(string), + TradeDate: item[1].(string), + Close: item[2].(float64), + TurnoverRate: item[3].(float64), + TurnoverRateF: item[4].(float64), + VolumeRatio: item[5].(float64), + Pe: item[6].(float64), + PeTtm: item[7].(float64), + Pb: item[8].(float64), + Ps: item[9].(float64), + PsTtm: item[10].(float64), + DvRatio: item[11].(float64), + DvTtm: item[12].(float64), + TotalShare: item[13].(float64), + FloatShare: item[14].(float64), + FreeShare: item[15].(float64), + TotalMv: item[16].(float64), + CircMv: item[17].(float64), + }) + } + } + } + +} diff --git a/internal/logic/a/new.go b/internal/logic/a/new.go index 5059764..44f6212 100644 --- a/internal/logic/a/new.go +++ b/internal/logic/a/new.go @@ -1,16 +1,10 @@ package a import ( - "errors" - "log" - "strings" "time" "git.apinb.com/bsm-sdk/core/utils" - "git.apinb.com/dataset/stock/internal/impl" - "git.apinb.com/dataset/stock/internal/models" tushare "github.com/ShawnRong/tushare-go" - "gorm.io/gorm" ) var ( @@ -22,178 +16,10 @@ func NewApiClient() { TushareClient = tushare.New(TushareToken) } -func GetStockBasic() { - // 参数 - params := map[string]string{ - "list_status": "L", // 上市状态 L上市 D退市 P暂停上市,默认是L - } - - // 字段 - fields := strings.Split("ts_code,symbol,name,area,industry,fullname,enname,cnspell,market,exchange,list_date,is_hs,act_name,act_ent_type", ",") - - // 根据api 请求对应的接口 - reply, _ := TushareClient.StockBasic(params, fields) - if reply.Code != 0 { - log.Println("ERROR", "GetStockBasic", reply.Code, reply.Msg) - return - } - - for _, item := range reply.Data.Items { - var record models.StockBasic - data := Anys2Strings(item) - - err := impl.DBService.Where("ts_code=?", data[0]).First(&record).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - // create - record = models.StockBasic{ - TsCode: data[0], - Symbol: data[1], - Name: data[2], - Area: data[3], - Industry: data[4], - FullName: data[5], - EnName: data[6], - CnSpell: data[7], - Market: data[8], - Exchange: data[9], - ListDate: data[10], - IsHS: data[11], - ActName: data[12], - ActEntType: data[13], - } - impl.DBService.Create(&record) - } else if err == nil { - // check updated. - upd := make(map[string]any) - if record.Name != data[2] { - upd["name"] = data[2] - } - if record.Area != data[3] { - upd["area"] = data[3] - } - if record.Industry != data[4] { - upd["industry"] = data[4] - } - if record.FullName != data[5] { - upd["full_name"] = data[5] - } - if record.EnName != data[6] { - upd["en_name"] = data[6] - } - if record.CnSpell != data[7] { - upd["cn_spell"] = data[7] - } - if record.Market != data[8] { - upd["market"] = data[8] - } - if record.Exchange != data[9] { - upd["exchange"] = data[9] - } - if record.ListDate != data[10] { - upd["list_date"] = data[10] - } - if record.IsHS != data[11] { - upd["is_hs"] = data[11] - } - if record.ActName != data[12] { - upd["act_name"] = data[12] - } - if record.ActEntType != data[13] { - upd["act_ent_type"] = data[13] - } - if len(upd) > 0 { - impl.DBService.Model(record).Updates(upd) - } - } - } -} - -func GetLastDaily() { - s, e := ReturnLastDay() - params := map[string]string{ - "start_date": s, - "end_date": e, - } - - reply, _ := TushareClient.Daily(params, []string{}) - if reply.Code != 0 { - log.Println("ERROR", "GetLastDaily", reply.Code, reply.Msg) - return - } - - for _, item := range reply.Data.Items { - var cnt int64 - impl.DBService.Model(&models.LastDaily{}).Where("ts_code=? and trade_date=?", item[0].(string), item[1].(string)).Count(&cnt) - if cnt == 0 { - impl.DBService.Create(&models.LastDaily{ - TsCode: item[0].(string), - TradeDate: item[1].(string), - Open: item[2].(float64), - High: item[3].(float64), - Low: item[4].(float64), - Close: item[5].(float64), - PreClose: item[6].(float64), - Change: item[7].(float64), - PctChg: item[8].(float64), - Vol: item[9].(float64), - Amount: item[10].(float64), - }) - } - } -} - -func GetLastIndicator() { - var stocks []models.StockBasic - impl.DBService.Find(&stocks) - - s, e := ReturnLastDay() - for _, row := range stocks { - params := map[string]string{ - "ts_code": row.TsCode, - "start_date": s, - "end_date": e, - } - - reply, _ := TushareClient.Daily(params, []string{}) - if reply.Code != 0 { - log.Println("ERROR", "GetLastIndicator", reply.Code, reply.Msg) - return - } - - for _, item := range reply.Data.Items { - var cnt int64 - impl.DBService.Model(&models.LastIndicator{}).Where("ts_code=? and trade_date=?", item[0].(string), item[1].(string)).Count(&cnt) - if cnt == 0 { - impl.DBService.Create(&models.LastIndicator{ - TsCode: item[0].(string), - TradeDate: item[1].(string), - Close: item[2].(float64), - TurnoverRate: item[3].(float64), - TurnoverRateF: item[4].(float64), - VolumeRatio: item[5].(float64), - Pe: item[6].(float64), - PeTtm: item[7].(float64), - Pb: item[8].(float64), - Ps: item[9].(float64), - PsTtm: item[10].(float64), - DvRatio: item[11].(float64), - DvTtm: item[12].(float64), - TotalShare: item[13].(float64), - FloatShare: item[14].(float64), - FreeShare: item[15].(float64), - TotalMv: item[16].(float64), - CircMv: item[17].(float64), - }) - } - } - } - -} - func ReturnLastDay() (string, string) { now := time.Now() - start := now.Format("20060102") - end := now.AddDate(0, -1, 0).Format("20060102") + end := now.Format("20060102") + start := now.AddDate(0, 0, -1).Format("20060102") return start, end } diff --git a/internal/models/last_daily.go b/internal/models/stock_daily.go similarity index 90% rename from internal/models/last_daily.go rename to internal/models/stock_daily.go index 2159b97..64f5da2 100644 --- a/internal/models/last_daily.go +++ b/internal/models/stock_daily.go @@ -5,7 +5,7 @@ import ( ) // LastDaily 股票日线数据 -type LastDaily struct { +type StockDaily struct { ID uint `gorm:"primarykey;autoIncrement" json:"id"` TsCode string `gorm:"type:varchar(20);not null;index:idx_ts_code;comment:股票代码" json:"ts_code"` TradeDate string `gorm:"type:date;not null;index:idx_trade_date;comment:交易日期" json:"trade_date"` @@ -21,10 +21,10 @@ type LastDaily struct { } func init() { - database.AppendMigrate(&LastDaily{}) + database.AppendMigrate(&StockDaily{}) } // TableName 指定表名 -func (LastDaily) TableName() string { - return "last_daily" +func (StockDaily) TableName() string { + return "stock_daily" } diff --git a/internal/models/last_indicator.go b/internal/models/stock_indicator.go similarity index 89% rename from internal/models/last_indicator.go rename to internal/models/stock_indicator.go index eeb8800..609b2a0 100644 --- a/internal/models/last_indicator.go +++ b/internal/models/stock_indicator.go @@ -4,8 +4,8 @@ import ( "git.apinb.com/bsm-sdk/core/database" ) -// LastIndicator 股票日线数据模型 -type LastIndicator struct { +// StockIndicator 股票日线数据模型 +type StockIndicator struct { ID uint `gorm:"primarykey;autoIncrement"` TsCode string `gorm:"type:varchar(20);not null;comment:TS股票代码;index:idx_ts_code"` TradeDate string `gorm:"type:date;not null;comment:交易日期;index:idx_trade_date;index:idx_ts_trade,priority:2"` @@ -28,10 +28,10 @@ type LastIndicator struct { } func init() { - database.AppendMigrate(&LastIndicator{}) + database.AppendMigrate(&StockIndicator{}) } // TableName 设置表名 -func (LastIndicator) TableName() string { - return "last_indicator" +func (StockIndicator) TableName() string { + return "stock_indicator" }