This commit is contained in:
2026-01-17 01:14:19 +08:00
parent 2249667d8b
commit 2fc2c89f25
7 changed files with 234 additions and 188 deletions

View File

@@ -4,7 +4,7 @@ import "git.apinb.com/dataset/stock/internal/logic/a"
func Boot() { func Boot() {
a.NewApiClient() a.NewApiClient()
a.GetStockBasic() //a.GetStockBasic()
a.GetLastDaily() a.GetStockDaily()
a.GetLastIndicator() //a.GetStockIndicator()
} }

103
internal/logic/a/basic.go Normal file
View File

@@ -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
}

58
internal/logic/a/daily.go Normal file
View File

@@ -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)
}
}

View File

@@ -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),
})
}
}
}
}

View File

@@ -1,16 +1,10 @@
package a package a
import ( import (
"errors"
"log"
"strings"
"time" "time"
"git.apinb.com/bsm-sdk/core/utils" "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" tushare "github.com/ShawnRong/tushare-go"
"gorm.io/gorm"
) )
var ( var (
@@ -22,178 +16,10 @@ func NewApiClient() {
TushareClient = tushare.New(TushareToken) 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) { func ReturnLastDay() (string, string) {
now := time.Now() now := time.Now()
start := now.Format("20060102") end := now.Format("20060102")
end := now.AddDate(0, -1, 0).Format("20060102") start := now.AddDate(0, 0, -1).Format("20060102")
return start, end return start, end
} }

View File

@@ -5,7 +5,7 @@ import (
) )
// LastDaily 股票日线数据 // LastDaily 股票日线数据
type LastDaily struct { type StockDaily struct {
ID uint `gorm:"primarykey;autoIncrement" json:"id"` ID uint `gorm:"primarykey;autoIncrement" json:"id"`
TsCode string `gorm:"type:varchar(20);not null;index:idx_ts_code;comment:股票代码" json:"ts_code"` 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"` TradeDate string `gorm:"type:date;not null;index:idx_trade_date;comment:交易日期" json:"trade_date"`
@@ -21,10 +21,10 @@ type LastDaily struct {
} }
func init() { func init() {
database.AppendMigrate(&LastDaily{}) database.AppendMigrate(&StockDaily{})
} }
// TableName 指定表名 // TableName 指定表名
func (LastDaily) TableName() string { func (StockDaily) TableName() string {
return "last_daily" return "stock_daily"
} }

View File

@@ -4,8 +4,8 @@ import (
"git.apinb.com/bsm-sdk/core/database" "git.apinb.com/bsm-sdk/core/database"
) )
// LastIndicator 股票日线数据模型 // StockIndicator 股票日线数据模型
type LastIndicator struct { type StockIndicator struct {
ID uint `gorm:"primarykey;autoIncrement"` ID uint `gorm:"primarykey;autoIncrement"`
TsCode string `gorm:"type:varchar(20);not null;comment:TS股票代码;index:idx_ts_code"` 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"` 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() { func init() {
database.AppendMigrate(&LastIndicator{}) database.AppendMigrate(&StockIndicator{})
} }
// TableName 设置表名 // TableName 设置表名
func (LastIndicator) TableName() string { func (StockIndicator) TableName() string {
return "last_indicator" return "stock_indicator"
} }