增加参数的有效性判断

This commit is contained in:
injoyai
2024-10-30 15:29:49 +08:00
parent a8ec5c19a2
commit bd82866f03
3 changed files with 105 additions and 17 deletions

104
client.go
View File

@@ -1,6 +1,7 @@
package tdx package tdx
import ( import (
"errors"
"fmt" "fmt"
"github.com/injoyai/base/maps" "github.com/injoyai/base/maps"
"github.com/injoyai/base/maps/wait/v2" "github.com/injoyai/base/maps/wait/v2"
@@ -10,6 +11,7 @@ import (
"github.com/injoyai/ios/client/dial" "github.com/injoyai/ios/client/dial"
"github.com/injoyai/logs" "github.com/injoyai/logs"
"github.com/injoyai/tdx/protocol" "github.com/injoyai/tdx/protocol"
"runtime/debug"
"sync/atomic" "sync/atomic"
"time" "time"
) )
@@ -76,6 +78,7 @@ func (this *Client) handlerDealMessage(c *client.Client, msg ios.Acker) {
defer func() { defer func() {
if e := recover(); e != nil { if e := recover(); e != nil {
logs.Err(e) logs.Err(e)
debug.PrintStack()
} }
}() }()
@@ -169,15 +172,15 @@ func (this *Client) GetStockList(exchange protocol.Exchange, start uint16) (*pro
// GetStockAll 通过多次请求的方式获取全部证券代码 // GetStockAll 通过多次请求的方式获取全部证券代码
func (this *Client) GetStockAll(exchange protocol.Exchange) (*protocol.StockListResp, error) { func (this *Client) GetStockAll(exchange protocol.Exchange) (*protocol.StockListResp, error) {
resp := &protocol.StockListResp{} resp := &protocol.StockListResp{}
maxSize := uint16(1000) size := uint16(1000)
for start := uint16(0); ; start += maxSize { for start := uint16(0); ; start += size {
r, err := this.GetStockList(exchange, start) r, err := this.GetStockList(exchange, start)
if err != nil { if err != nil {
return nil, err return nil, err
} }
resp.Count += r.Count resp.Count += r.Count
resp.List = append(resp.List, r.List...) resp.List = append(resp.List, r.List...)
if r.Count < maxSize { if r.Count < size {
break break
} }
} }
@@ -212,6 +215,9 @@ func (this *Client) GetStockMinute(exchange protocol.Exchange, code string) (*pr
// GetStockMinuteTrade 获取分时交易详情,服务器最多返回1800条,count-start<=1800 // GetStockMinuteTrade 获取分时交易详情,服务器最多返回1800条,count-start<=1800
func (this *Client) GetStockMinuteTrade(exchange protocol.Exchange, code string, start, count uint16) (*protocol.StockMinuteTradeResp, error) { func (this *Client) GetStockMinuteTrade(exchange protocol.Exchange, code string, start, count uint16) (*protocol.StockMinuteTradeResp, error) {
if count > 1800 {
return nil, errors.New("数量不能超过1800")
}
f, err := protocol.MStockMinuteTrade.Frame(exchange, code, start, count) f, err := protocol.MStockMinuteTrade.Frame(exchange, code, start, count)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -226,16 +232,16 @@ func (this *Client) GetStockMinuteTrade(exchange protocol.Exchange, code string,
// GetStockMinuteTradeAll 获取分时全部交易详情,todo 只做参考 因为交易实时在进行,然后又是分页读取的,所以会出现读取间隔内产生的交易会丢失 // GetStockMinuteTradeAll 获取分时全部交易详情,todo 只做参考 因为交易实时在进行,然后又是分页读取的,所以会出现读取间隔内产生的交易会丢失
func (this *Client) GetStockMinuteTradeAll(exchange protocol.Exchange, code string) (*protocol.StockMinuteTradeResp, error) { func (this *Client) GetStockMinuteTradeAll(exchange protocol.Exchange, code string) (*protocol.StockMinuteTradeResp, error) {
resp := &protocol.StockMinuteTradeResp{} resp := &protocol.StockMinuteTradeResp{}
maxSize := uint16(1800) size := uint16(1800)
for i := uint16(0); ; i += maxSize { for i := uint16(0); ; i += size {
r, err := this.GetStockMinuteTrade(exchange, code, i, i+maxSize) r, err := this.GetStockMinuteTrade(exchange, code, i, i+size)
if err != nil { if err != nil {
return nil, err return nil, err
} }
resp.Count += r.Count resp.Count += r.Count
resp.List = append(resp.List, r.List...) resp.List = append(resp.List, r.List...)
if r.Count < maxSize { if r.Count < size {
break break
} }
} }
@@ -244,6 +250,9 @@ func (this *Client) GetStockMinuteTradeAll(exchange protocol.Exchange, code stri
// GetStockHistoryMinuteTrade 获取历史分时交易,,只能获取昨天及之前的数据,服务器最多返回2000条,count-start<=2000 // GetStockHistoryMinuteTrade 获取历史分时交易,,只能获取昨天及之前的数据,服务器最多返回2000条,count-start<=2000
func (this *Client) GetStockHistoryMinuteTrade(t time.Time, exchange protocol.Exchange, code string, start, count uint16) (*protocol.StockHistoryMinuteTradeResp, error) { func (this *Client) GetStockHistoryMinuteTrade(t time.Time, exchange protocol.Exchange, code string, start, count uint16) (*protocol.StockHistoryMinuteTradeResp, error) {
if count > 2000 {
return nil, errors.New("数量不能超过2000")
}
f, err := protocol.MStockHistoryMinuteTrade.Frame(t, exchange, code, start, count) f, err := protocol.MStockHistoryMinuteTrade.Frame(t, exchange, code, start, count)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -258,15 +267,15 @@ func (this *Client) GetStockHistoryMinuteTrade(t time.Time, exchange protocol.Ex
// GetStockHistoryMinuteTradeAll 获取历史分时全部交易,通过多次请求来拼接,只能获取昨天及之前的数据 // GetStockHistoryMinuteTradeAll 获取历史分时全部交易,通过多次请求来拼接,只能获取昨天及之前的数据
func (this *Client) GetStockHistoryMinuteTradeAll(exchange protocol.Exchange, code string) (*protocol.StockMinuteTradeResp, error) { func (this *Client) GetStockHistoryMinuteTradeAll(exchange protocol.Exchange, code string) (*protocol.StockMinuteTradeResp, error) {
resp := &protocol.StockMinuteTradeResp{} resp := &protocol.StockMinuteTradeResp{}
maxSize := uint16(2000) size := uint16(2000)
for i := uint16(0); ; i += maxSize { for i := uint16(0); ; i += size {
r, err := this.GetStockMinuteTrade(exchange, code, i, i+maxSize) r, err := this.GetStockMinuteTrade(exchange, code, i, i+size)
if err != nil { if err != nil {
return nil, err return nil, err
} }
resp.Count += r.Count resp.Count += r.Count
resp.List = append(resp.List, r.List...) resp.List = append(resp.List, r.List...)
if r.Count < maxSize { if r.Count < size {
break break
} }
} }
@@ -286,52 +295,125 @@ func (this *Client) GetStockKline(Type protocol.TypeKline, req *protocol.StockKl
return result.(*protocol.StockKlineResp), nil return result.(*protocol.StockKlineResp), nil
} }
// GetStockKlineAll 获取全部k线数据
func (this *Client) GetStockKlineAll(Type protocol.TypeKline, exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
resp := &protocol.StockKlineResp{}
size := uint16(800)
for i := uint16(0); ; i += size {
r, err := this.GetStockKline(Type, &protocol.StockKlineReq{
Exchange: exchange,
Code: code,
Start: i,
Count: i + size,
})
if err != nil {
return nil, err
}
resp.Count += r.Count
resp.List = append(resp.List, r.List...)
if r.Count < size {
break
}
}
return resp, nil
}
// GetStockKlineMinute 获取一分钟k线数据 // GetStockKlineMinute 获取一分钟k线数据
func (this *Client) GetStockKlineMinute(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) { func (this *Client) GetStockKlineMinute(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKlineMinute, req) return this.GetStockKline(protocol.TypeKlineMinute, req)
} }
// GetStockKlineMinuteAll 获取一分钟k线全部数据
func (this *Client) GetStockKlineMinuteAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKlineMinute, exchange, code)
}
// GetStockKline5Minute 获取五分钟k线数据 // GetStockKline5Minute 获取五分钟k线数据
func (this *Client) GetStockKline5Minute(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) { func (this *Client) GetStockKline5Minute(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKline5Minute, req) return this.GetStockKline(protocol.TypeKline5Minute, req)
} }
// GetStockKline5MinuteAll 获取5分钟k线全部数据
func (this *Client) GetStockKline5MinuteAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKline5Minute, exchange, code)
}
// GetStockKline15Minute 获取十五分钟k线数据 // GetStockKline15Minute 获取十五分钟k线数据
func (this *Client) GetStockKline15Minute(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) { func (this *Client) GetStockKline15Minute(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKline15Minute, req) return this.GetStockKline(protocol.TypeKline15Minute, req)
} }
// GetStockKline15MinuteAll 获取十五分钟k线全部数据
func (this *Client) GetStockKline15MinuteAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKline15Minute, exchange, code)
}
// GetStockKline30Minute 获取三十分钟k线数据 // GetStockKline30Minute 获取三十分钟k线数据
func (this *Client) GetStockKline30Minute(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) { func (this *Client) GetStockKline30Minute(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKline30Minute, req) return this.GetStockKline(protocol.TypeKline30Minute, req)
} }
// GetStockKline30MinuteAll 获取三十分钟k线全部数据
func (this *Client) GetStockKline30MinuteAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKline30Minute, exchange, code)
}
// GetStockKlineHour 获取小时k线数据 // GetStockKlineHour 获取小时k线数据
func (this *Client) GetStockKlineHour(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) { func (this *Client) GetStockKlineHour(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKlineHour, req) return this.GetStockKline(protocol.TypeKlineHour, req)
} }
// GetStockKlineHourAll 获取小时k线全部数据
func (this *Client) GetStockKlineHourAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKlineHour, exchange, code)
}
// GetStockKlineDay 获取日k线数据 // GetStockKlineDay 获取日k线数据
func (this *Client) GetStockKlineDay(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) { func (this *Client) GetStockKlineDay(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKlineDay, req) return this.GetStockKline(protocol.TypeKlineDay, req)
} }
// GetStockKlineDayAll 获取日k线全部数据
func (this *Client) GetStockKlineDayAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKlineDay, exchange, code)
}
// GetStockKlineWeek 获取周k线数据 // GetStockKlineWeek 获取周k线数据
func (this *Client) GetStockKlineWeek(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) { func (this *Client) GetStockKlineWeek(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKlineWeek, req) return this.GetStockKline(protocol.TypeKlineWeek, req)
} }
// GetStockKlineWeekAll 获取周k线全部数据
func (this *Client) GetStockKlineWeekAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKlineWeek, exchange, code)
}
// GetStockKlineMonth 获取月k线数据 // GetStockKlineMonth 获取月k线数据
func (this *Client) GetStockKlineMonth(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) { func (this *Client) GetStockKlineMonth(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKlineMonth, req) return this.GetStockKline(protocol.TypeKlineMonth, req)
} }
// GetStockKlineMonthAll 获取月k线全部数据
func (this *Client) GetStockKlineMonthAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKlineMonth, exchange, code)
}
// GetStockKlineQuarter 获取季k线数据 // GetStockKlineQuarter 获取季k线数据
func (this *Client) GetStockKlineQuarter(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) { func (this *Client) GetStockKlineQuarter(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKlineQuarter, req) return this.GetStockKline(protocol.TypeKlineQuarter, req)
} }
// GetStockKlineQuarterAll 获取季k线全部数据
func (this *Client) GetStockKlineQuarterAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKlineQuarter, exchange, code)
}
// GetStockKlineYear 获取年k线数据 // GetStockKlineYear 获取年k线数据
func (this *Client) GetStockKlineYear(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) { func (this *Client) GetStockKlineYear(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKlineYear, req) return this.GetStockKline(protocol.TypeKlineYear, req)
} }
// GetStockKlineYearAll 获取年k线数据
func (this *Client) GetStockKlineYearAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKlineYear, exchange, code)
}

View File

@@ -54,9 +54,9 @@ func (this *Frame) Bytes() g.Bytes {
type Response struct { type Response struct {
Prefix uint32 //未知,猜测是帧头 Prefix uint32 //未知,猜测是帧头
I2 uint8 //未知,猜测是响应的控制码 Control uint8 //响应的控制码,目前发现0c是错误,1c是成功,猜测左数右第4位代表是否成功
MsgID uint32 //消息ID MsgID uint32 //消息ID
Control uint8 //未知,猜测是响应的控制码 Unknown uint8 //未知,猜测是响应的控制码
Type uint16 //响应类型,对应请求类型,如建立连接,请求分时数据等 Type uint16 //响应类型,对应请求类型,如建立连接,请求分时数据等
ZipLength uint16 //数据长度 ZipLength uint16 //数据长度
Length uint16 //未压缩长度 Length uint16 //未压缩长度
@@ -65,7 +65,7 @@ type Response struct {
/* /*
Decode Decode
帧头 |未知 |消息ID |控制码 |数据类型 |未解压长度 |解压长度 |数据域 帧头 |控制码 |消息ID |控制码 |数据类型 |未解压长度 |解压长度 |数据域
b1cb7400 |1c |00000000 |00 |0d00 |5100 |bd00 |789c6378c1cecb252ace6066c5b4898987b9050ed1f90cc5b74c18a5bc18c1b43490fecff09c81819191f13fc3c9f3bb169f5e7dfefeb5ef57f7199a305009308208e5b32bb6bcbf70148712002d7f1e13 b1cb7400 |1c |00000000 |00 |0d00 |5100 |bd00 |789c6378c1cecb252ace6066c5b4898987b9050ed1f90cc5b74c18a5bc18c1b43490fecff09c81819191f13fc3c9f3bb169f5e7dfefeb5ef57f7199a305009308208e5b32bb6bcbf70148712002d7f1e13
*/ */
func Decode(bs []byte) (*Response, error) { func Decode(bs []byte) (*Response, error) {
@@ -74,15 +74,19 @@ func Decode(bs []byte) (*Response, error) {
} }
resp := &Response{ resp := &Response{
Prefix: Uint32(bs[:4]), Prefix: Uint32(bs[:4]),
I2: bs[4], Control: bs[4],
MsgID: Uint32(bs[5:9]), MsgID: Uint32(bs[5:9]),
Control: bs[9], Unknown: bs[9],
Type: Uint16(bs[10:12]), Type: Uint16(bs[10:12]),
ZipLength: Uint16(bs[12:14]), ZipLength: Uint16(bs[12:14]),
Length: Uint16(bs[14:16]), Length: Uint16(bs[14:16]),
Data: bs[16:], Data: bs[16:],
} }
if resp.Control&0x10 != 0x10 {
//return nil, fmt.Errorf("控制码不匹配,预期0x1c,得到0x%x", resp.Control)
}
if int(resp.ZipLength) != len(bs[16:]) { if int(resp.ZipLength) != len(bs[16:]) {
return nil, fmt.Errorf("压缩数据长度不匹配,预期%d,得到%d", resp.ZipLength+16, len(bs)) return nil, fmt.Errorf("压缩数据长度不匹配,预期%d,得到%d", resp.ZipLength+16, len(bs))
} }

View File

@@ -15,6 +15,9 @@ type StockKlineReq struct {
} }
func (this *StockKlineReq) Bytes(Type TypeKline) (g.Bytes, error) { func (this *StockKlineReq) Bytes(Type TypeKline) (g.Bytes, error) {
if this.Count > 800 {
return nil, errors.New("单次数量不能超过800")
}
if len(this.Code) != 6 { if len(this.Code) != 6 {
return nil, errors.New("股票代码长度错误") return nil, errors.New("股票代码长度错误")
} }
@@ -78,7 +81,6 @@ func (stockKline) Decode(bs []byte, Type TypeKline) (*StockKlineResp, error) {
bs = bs[2:] bs = bs[2:]
var last Price var last Price
for i := uint16(0); i < resp.Count; i++ { for i := uint16(0); i < resp.Count; i++ {
k := &StockKline{ k := &StockKline{
Time: GetTime([4]byte(bs[:4]), Type), Time: GetTime([4]byte(bs[:4]), Type),