Merge remote-tracking branch 'origin/master'

This commit is contained in:
钱纯净
2025-04-17 23:17:28 +08:00
6 changed files with 189 additions and 28 deletions

View File

@@ -235,12 +235,18 @@ func (this *Client) GetCodeAll(exchange protocol.Exchange) (*protocol.CodeResp,
// GetQuote 获取盘口五档报价
func (this *Client) GetQuote(codes ...string) (protocol.QuotesResp, error) {
if DefaultCodes == nil {
return nil, errors.New("DefaultCodes未初始化")
}
for i := range codes {
codes[i] = DefaultCodes.AddExchange(codes[i])
//如果是股票代码,则加上前缀
codes[i] = protocol.AddPrefix(codes[i])
if !protocol.IsStock(codes[i]) {
if DefaultCodes == nil {
return nil, errors.New("DefaultCodes未初始化")
}
//不是股票代码的话根据codes的信息加上前缀
codes[i] = DefaultCodes.AddExchange(codes[i])
}
}
f, err := protocol.MQuote.Frame(codes...)
if err != nil {
return nil, err
@@ -256,26 +262,25 @@ func (this *Client) GetQuote(codes ...string) (protocol.QuotesResp, error) {
if len(quotes) != len(codes) {
return nil, fmt.Errorf("预期%d个实际%d个", len(codes), len(quotes))
}
if DefaultCodes == nil {
return nil, errors.New("DefaultCodes未初始化")
}
for i, code := range codes {
m := DefaultCodes.Get(code)
if m == nil {
return nil, fmt.Errorf("未查询到代码[%s]相关信息", code)
}
for ii, v := range quotes[i].SellLevel {
quotes[i].SellLevel[ii].Price = m.Price(v.Price)
}
for ii, v := range quotes[i].BuyLevel {
quotes[i].BuyLevel[ii].Price = m.Price(v.Price)
}
quotes[i].K = protocol.K{
Last: m.Price(quotes[i].K.Last),
Open: m.Price(quotes[i].K.Open),
High: m.Price(quotes[i].K.High),
Low: m.Price(quotes[i].K.Low),
Close: m.Price(quotes[i].K.Close),
if !protocol.IsStock(code) {
m := DefaultCodes.Get(code)
if m == nil {
return nil, fmt.Errorf("未查询到代码[%s]相关信息", code)
}
for ii, v := range quotes[i].SellLevel {
quotes[i].SellLevel[ii].Price = m.Price(v.Price)
}
for ii, v := range quotes[i].BuyLevel {
quotes[i].BuyLevel[ii].Price = m.Price(v.Price)
}
quotes[i].K = protocol.K{
Last: m.Price(quotes[i].K.Last),
Open: m.Price(quotes[i].K.Open),
High: m.Price(quotes[i].K.High),
Low: m.Price(quotes[i].K.Low),
Close: m.Price(quotes[i].K.Close),
}
}
}
}

View File

@@ -314,7 +314,8 @@ func (this *CodeModel) FullCode() string {
}
func (this *CodeModel) Price(p protocol.Price) protocol.Price {
return p * protocol.Price(math.Pow10(int(3-this.Decimal)))
return protocol.Price(float64(p) * math.Pow10(int(2-this.Decimal)))
return p * protocol.Price(math.Pow10(int(2-this.Decimal)))
}
func NewSessionFunc(db *xorm.Engine, fn func(session *xorm.Session) error) error {

148
extend/pull-kline-mysql.go Normal file
View File

@@ -0,0 +1,148 @@
package extend
import (
"context"
_ "github.com/go-sql-driver/mysql"
"github.com/injoyai/base/chans"
"github.com/injoyai/logs"
"github.com/injoyai/tdx"
"github.com/injoyai/tdx/protocol"
"xorm.io/core"
"xorm.io/xorm"
)
func NewPullKlineMysql(cfg PullKlineConfig) (*PullKlineMysql, error) {
db, err := xorm.NewEngine("mysql", cfg.Dir)
if err != nil {
return nil, err
}
db.SetMapper(core.SameMapper{})
_tables := []*KlineTable(nil)
for _, v := range cfg.Tables {
table := KlineTableMap[v]
if err = db.Sync2(table); err != nil {
return nil, err
}
_tables = append(_tables, table)
}
return &PullKlineMysql{
tables: _tables,
Config: cfg,
DB: db,
}, nil
}
type PullKlineMysql struct {
tables []*KlineTable
Config PullKlineConfig
DB *xorm.Engine
}
func (this *PullKlineMysql) Name() string {
return "拉取k线数据"
}
func (this *PullKlineMysql) Run(ctx context.Context, m *tdx.Manage) error {
limit := chans.NewWaitLimit(uint(this.Config.Limit))
//1. 获取所有股票代码
codes := this.Config.Codes
if len(codes) == 0 {
codes = m.Codes.GetStocks()
}
for _, v := range codes {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
limit.Add()
go func(code string) {
defer limit.Done()
for _, table := range this.tables {
if table == nil {
continue
}
select {
case <-ctx.Done():
return
default:
}
var err error
//2. 获取最后一条数据
last := new(Kline)
if _, err = this.DB.Table(table).Where("Code=?", code).Desc("Date").Get(last); err != nil {
logs.Err(err)
return
}
//3. 从服务器获取数据
insert := Klines{}
err = m.Do(func(c *tdx.Client) error {
insert, err = this.pull(code, last.Date, table.Handler(c))
return err
})
if err != nil {
logs.Err(err)
return
}
//4. 插入数据库
err = tdx.NewSessionFunc(this.DB, func(session *xorm.Session) error {
for i, v := range insert {
if i == 0 {
if _, err := session.Table(table).Where("Code=? and Date >= ?", code, v.Date).Delete(); err != nil {
return err
}
}
if _, err := session.Table(table).Insert(v); err != nil {
return err
}
}
return nil
})
logs.PrintErr(err)
}
}(v)
}
limit.Wait()
return nil
}
func (this *PullKlineMysql) pull(code string, lastDate int64, f func(code string, f func(k *protocol.Kline) bool) (*protocol.KlineResp, error)) (Klines, error) {
if lastDate == 0 {
lastDate = protocol.ExchangeEstablish.Unix()
}
resp, err := f(code, func(k *protocol.Kline) bool {
return k.Time.Unix() <= lastDate || k.Time.Unix() <= this.Config.StartAt.Unix()
})
if err != nil {
return nil, err
}
ks := Klines{}
for _, v := range resp.List {
ks = append(ks, &Kline{
Code: code,
Date: v.Time.Unix(),
Open: v.Open,
High: v.High,
Low: v.Low,
Close: v.Close,
Volume: v.Volume,
Amount: v.Amount,
})
}
return ks, nil
}

View File

@@ -186,7 +186,7 @@ func (this *PullKline) pull(code string, lastDate int64, f func(code string, f f
}
type Kline struct {
Code string `json:"code" xorm:"-"` //代码
Code string `json:"code"` //代码
Date int64 `json:"date"` //时间节点 2006-01-02 15:00
Open protocol.Price `json:"open"` //开盘价
High protocol.Price `json:"high"` //最高价

View File

@@ -47,7 +47,7 @@ type Quote struct {
func (this *Quote) String() string {
return fmt.Sprintf(`%s%s
%s
%s, 现量:%s, 总金额:%s, 内盘:%s, 外盘:%s
%s, 现量:%s, 总金额:%s, 内盘:%s, 外盘:%s
%s%s
`,
this.Exchange.String(), this.Code, this.K,
@@ -142,9 +142,9 @@ func (this quote) Decode(bs []byte) QuotesResp {
sellLevel := PriceLevel{}
bs, p = GetPrice(bs)
buyLevel.Price = p + sec.K.Close
buyLevel.Price = p*10 + sec.K.Close
bs, p = GetPrice(bs)
sellLevel.Price = p + sec.K.Close
sellLevel.Price = p*10 + sec.K.Close
bs, buyLevel.Number = CutInt(bs)
bs, sellLevel.Number = CutInt(bs)

View File

@@ -78,6 +78,13 @@ func DecodeK(bs []byte) ([]byte, K) {
bs, k.Low = GetPrice(bs)
k.Low += k.Close
//默认按股票展示
k.Last *= 10
k.Open *= 10
k.Close *= 10
k.High *= 10
k.Low *= 10
return bs, k
}