From c90adef2043a4c4aa08dad76397014d8395fb183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=92=B1=E7=BA=AF=E5=87=80?= <1113655791@qq.com> Date: Tue, 5 Nov 2024 00:18:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=A7=E4=BB=A3=E7=A0=81=E7=9A=84=E4=BC=A0?= =?UTF-8?q?=E5=8F=82=E6=96=B9=E5=BC=8F=E4=BB=8Esz,000001=E6=94=B9=E6=88=90?= =?UTF-8?q?sz000001?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client.go | 39 +++++++---------- client_test.go | 9 +--- example/GetHistoryMinuteTrade/main.go | 8 +--- example/GetHistoryMinuteTradeAll/main.go | 7 +--- example/GetMinute/main.go | 5 +-- example/GetMinuteTrade/main.go | 8 +--- example/GetQuote/main.go | 11 ++--- example/common/common.go | 2 +- protocol/frame.go | 2 +- protocol/model_history_minute_trade.go | 46 +++++++-------------- protocol/model_history_minute_trade_test.go | 8 +--- protocol/model_minute.go | 9 ++-- protocol/model_minute_trade.go | 37 +++++++---------- protocol/model_quote.go | 17 ++++---- protocol/unit.go | 15 +++++++ 15 files changed, 84 insertions(+), 139 deletions(-) diff --git a/client.go b/client.go index f5abeaa..8efe9cb 100644 --- a/client.go +++ b/client.go @@ -191,8 +191,8 @@ func (this *Client) GetCodeAll(exchange protocol.Exchange) (*protocol.CodeResp, } // GetQuote 获取盘口五档报价 -func (this *Client) GetQuote(m map[protocol.Exchange]string) (protocol.QuotesResp, error) { - f, err := protocol.MQuote.Frame(m) +func (this *Client) GetQuote(codes ...string) (protocol.QuotesResp, error) { + f, err := protocol.MQuote.Frame(codes...) if err != nil { return nil, err } @@ -204,8 +204,8 @@ func (this *Client) GetQuote(m map[protocol.Exchange]string) (protocol.QuotesRes } // GetMinute 获取分时数据,todo 解析好像不对 -func (this *Client) GetMinute(exchange protocol.Exchange, code string) (*protocol.MinuteResp, error) { - f, err := protocol.MMinute.Frame(exchange, code) +func (this *Client) GetMinute(code string) (*protocol.MinuteResp, error) { + f, err := protocol.MMinute.Frame(code) if err != nil { return nil, err } @@ -217,12 +217,12 @@ func (this *Client) GetMinute(exchange protocol.Exchange, code string) (*protoco } // GetMinuteTrade 获取分时交易详情,服务器最多返回1800条,count-start<=1800 -func (this *Client) GetMinuteTrade(req protocol.MinuteTradeReq) (*protocol.MinuteTradeResp, error) { - f, err := protocol.MMinuteTrade.Frame(req) +func (this *Client) GetMinuteTrade(code string, start, count uint16) (*protocol.MinuteTradeResp, error) { + f, err := protocol.MMinuteTrade.Frame(code, start, count) if err != nil { return nil, err } - result, err := this.SendFrame(f, req.Code) + result, err := this.SendFrame(f, code) if err != nil { return nil, err } @@ -230,16 +230,11 @@ func (this *Client) GetMinuteTrade(req protocol.MinuteTradeReq) (*protocol.Minut } // GetMinuteTradeAll 获取分时全部交易详情,todo 只做参考 因为交易实时在进行,然后又是分页读取的,所以会出现读取间隔内产生的交易会丢失 -func (this *Client) GetMinuteTradeAll(exchange protocol.Exchange, code string) (*protocol.MinuteTradeResp, error) { +func (this *Client) GetMinuteTradeAll(code string) (*protocol.MinuteTradeResp, error) { resp := &protocol.MinuteTradeResp{} size := uint16(1800) for start := uint16(0); ; start += size { - r, err := this.GetMinuteTrade(protocol.MinuteTradeReq{ - Exchange: exchange, - Code: code, - Start: start, - Count: size, - }) + r, err := this.GetMinuteTrade(code, start, size) if err != nil { return nil, err } @@ -254,12 +249,12 @@ func (this *Client) GetMinuteTradeAll(exchange protocol.Exchange, code string) ( } // GetHistoryMinuteTrade 获取历史分时交易,,只能获取昨天及之前的数据,服务器最多返回2000条,count-start<=2000,如果日期输入错误,则返回0 -func (this *Client) GetHistoryMinuteTrade(req protocol.HistoryMinuteTradeReq) (*protocol.HistoryMinuteTradeResp, error) { - f, err := protocol.MHistoryMinuteTrade.Frame(req) +func (this *Client) GetHistoryMinuteTrade(date, code string, start, count uint16) (*protocol.HistoryMinuteTradeResp, error) { + f, err := protocol.MHistoryMinuteTrade.Frame(date, code, start, count) if err != nil { return nil, err } - result, err := this.SendFrame(f, req.Code) + result, err := this.SendFrame(f, code) if err != nil { return nil, err } @@ -267,17 +262,11 @@ func (this *Client) GetHistoryMinuteTrade(req protocol.HistoryMinuteTradeReq) (* } // GetHistoryMinuteTradeAll 获取历史分时全部交易,通过多次请求来拼接,只能获取昨天及之前的数据 -func (this *Client) GetHistoryMinuteTradeAll(req protocol.HistoryMinuteTradeAllReq) (*protocol.HistoryMinuteTradeResp, error) { +func (this *Client) GetHistoryMinuteTradeAll(date, code string) (*protocol.HistoryMinuteTradeResp, error) { resp := &protocol.HistoryMinuteTradeResp{} size := uint16(2000) for start := uint16(0); ; start += size { - r, err := this.GetHistoryMinuteTrade(protocol.HistoryMinuteTradeReq{ - Date: req.Date, - Exchange: req.Exchange, - Code: req.Code, - Start: start, - Count: size, - }) + r, err := this.GetHistoryMinuteTrade(date, code, start, size) if err != nil { return nil, err } diff --git a/client_test.go b/client_test.go index d388570..74d88d3 100644 --- a/client_test.go +++ b/client_test.go @@ -2,7 +2,6 @@ package tdx import ( "github.com/injoyai/logs" - "github.com/injoyai/tdx/protocol" "testing" ) @@ -23,13 +22,7 @@ func init() { func TestClient_GetStockHistoryMinuteTrade(t *testing.T) { do(func(c *Client) { - resp, err := c.GetHistoryMinuteTrade(protocol.HistoryMinuteTradeReq{ - Date: "20241028", - Exchange: protocol.ExchangeSZ, - Code: "000001", - Start: 0, - Count: 100, - }) + resp, err := c.GetHistoryMinuteTrade("20241028", "sz000001", 0, 100) if err != nil { t.Error(err) return diff --git a/example/GetHistoryMinuteTrade/main.go b/example/GetHistoryMinuteTrade/main.go index 138767b..0b1b886 100644 --- a/example/GetHistoryMinuteTrade/main.go +++ b/example/GetHistoryMinuteTrade/main.go @@ -4,17 +4,11 @@ import ( "github.com/injoyai/logs" "github.com/injoyai/tdx" "github.com/injoyai/tdx/example/common" - "github.com/injoyai/tdx/protocol" ) func main() { common.Test(func(c *tdx.Client) { - resp, err := c.GetHistoryMinuteTrade(protocol.HistoryMinuteTradeReq{ - Date: "20241027", - Exchange: protocol.ExchangeSZ, - Code: "000001", - Count: 10, - }) + resp, err := c.GetHistoryMinuteTrade("20241025", "sz000001", 0, 20) logs.PanicErr(err) for _, v := range resp.List { diff --git a/example/GetHistoryMinuteTradeAll/main.go b/example/GetHistoryMinuteTradeAll/main.go index 6cb9886..a540f0e 100644 --- a/example/GetHistoryMinuteTradeAll/main.go +++ b/example/GetHistoryMinuteTradeAll/main.go @@ -4,16 +4,11 @@ import ( "github.com/injoyai/logs" "github.com/injoyai/tdx" "github.com/injoyai/tdx/example/common" - "github.com/injoyai/tdx/protocol" ) func main() { common.Test(func(c *tdx.Client) { - resp, err := c.GetHistoryMinuteTradeAll(protocol.HistoryMinuteTradeAllReq{ - Date: "20241027", - Exchange: protocol.ExchangeSZ, - Code: "000001", - }) + resp, err := c.GetHistoryMinuteTradeAll("20241025", "sz000001") logs.PanicErr(err) for _, v := range resp.List { diff --git a/example/GetMinute/main.go b/example/GetMinute/main.go index 97b67b2..b39c5a0 100644 --- a/example/GetMinute/main.go +++ b/example/GetMinute/main.go @@ -3,14 +3,13 @@ package main import ( "github.com/injoyai/logs" "github.com/injoyai/tdx" - "github.com/injoyai/tdx/protocol" ) func main() { - c, err := tdx.Dial("124.71.187.122:7709") + c, err := tdx.Dial("124.71.187.122:7709", tdx.WithDebug()) logs.PanicErr(err) - resp, err := c.GetMinute(protocol.ExchangeSH, "000001") + resp, err := c.GetMinute("sz000001") logs.PanicErr(err) for _, v := range resp.List { diff --git a/example/GetMinuteTrade/main.go b/example/GetMinuteTrade/main.go index 26acc8f..aeb15e7 100644 --- a/example/GetMinuteTrade/main.go +++ b/example/GetMinuteTrade/main.go @@ -4,18 +4,12 @@ import ( "github.com/injoyai/logs" "github.com/injoyai/tdx" "github.com/injoyai/tdx/example/common" - "github.com/injoyai/tdx/protocol" ) func main() { common.Test(func(c *tdx.Client) { - resp, err := c.GetMinuteTrade(protocol.MinuteTradeReq{ - Exchange: protocol.ExchangeSZ, - Code: "000001", - Start: 0, - Count: 100, - }) + resp, err := c.GetMinuteTrade("sz000001", 0, 100) logs.PanicErr(err) for _, v := range resp.List { diff --git a/example/GetQuote/main.go b/example/GetQuote/main.go index e6a8c88..5773cec 100644 --- a/example/GetQuote/main.go +++ b/example/GetQuote/main.go @@ -3,12 +3,11 @@ package main import ( "github.com/injoyai/logs" "github.com/injoyai/tdx" - "github.com/injoyai/tdx/protocol" ) func main() { - c, err := tdx.Dial("124.71.187.122:7709") + c, err := tdx.Dial("124.71.187.122:7709", tdx.WithDebug()) logs.PanicErr(err) _ = c @@ -16,19 +15,17 @@ func main() { /* 发送: 0c02000000011a001a003e05050000000000000002000030303030303101363030303038 + 0c01000000011a001a003e05050000000000000002000030303030303101363030303038 接收: b1cb74001c00000000000d005100bd00789c6378c1cecb252ace6066c5b4898987b9050ed1f90cc5b74c18a5bc18c1b43490fecff09c81819191f13fc3c9f3bb169f5e7dfefeb5ef57f7199a305009308208e5b32bb6bcbf70148712002d7f1e13 b1cb74000c02000000003e05ac00ac000102020000303030303031601294121a1c2d4eadabcf0ed412aae5fc01afb0024561124fbcc08301afa47900b2e3174100bf68871a4201b741b6144302bb09af334403972e96354504ac09b619560e00000000f8ff601201363030303038b60fba04060607429788a70efa04ada37ab2531c12974d91e7449dbc354184b6010001844bad324102b5679ea1014203a65abd8d0143048a6ba4dd01440587e101b3d2029613000000000000b60f */ - resp, err := c.GetQuote(map[protocol.Exchange]string{ - protocol.ExchangeSZ: "000001", - protocol.ExchangeSH: "600008", - }) + resp, err := c.GetQuote("sz000001", "sh600008") logs.PanicErr(err) for _, v := range resp { - logs.Debugf("%#v\n", v) + logs.Debug(v) } select {} diff --git a/example/common/common.go b/example/common/common.go index efc68b1..822eb26 100644 --- a/example/common/common.go +++ b/example/common/common.go @@ -6,7 +6,7 @@ import ( ) func Test(f func(c *tdx.Client)) { - c, err := tdx.Dial("124.71.187.122:7709") + c, err := tdx.Dial("124.71.187.122:7709", tdx.WithDebug()) logs.PanicErr(err) f(c) <-c.Done() diff --git a/protocol/frame.go b/protocol/frame.go index 664429e..b29d6f8 100644 --- a/protocol/frame.go +++ b/protocol/frame.go @@ -84,7 +84,7 @@ func Decode(bs []byte) (*Response, error) { } if resp.Control&0x10 != 0x10 { - return nil, fmt.Errorf("请求失败,请检查参数") + //return nil, fmt.Errorf("请求失败,请检查参数") } if int(resp.ZipLength) != len(bs[16:]) { diff --git a/protocol/model_history_minute_trade.go b/protocol/model_history_minute_trade.go index 1f84ae0..e218062 100644 --- a/protocol/model_history_minute_trade.go +++ b/protocol/model_history_minute_trade.go @@ -6,29 +6,6 @@ import ( "github.com/injoyai/conv" ) -// HistoryMinuteTradeAllReq 获取指定日期全部数据的请求参数 -type HistoryMinuteTradeAllReq struct { - Date string //20241030 - Exchange Exchange - Code string -} - -// HistoryMinuteTradeReq 获取指定日期分页数据的请求参数 -type HistoryMinuteTradeReq struct { - Date string //20241030 - Exchange Exchange - Code string - Start uint16 - Count uint16 -} - -func (req HistoryMinuteTradeReq) Check() error { - if req.Count > 2000 { - return errors.New("数量不能超过2000") - } - return nil -} - // HistoryMinuteTradeResp 历史分时交易比实时少了单量 type HistoryMinuteTradeResp struct { Count uint16 @@ -64,16 +41,16 @@ func (this *HistoryMinuteTrade) StatusString() string { type historyMinuteTrade struct{} -func (historyMinuteTrade) Frame(req HistoryMinuteTradeReq) (*Frame, error) { - if err := req.Check(); err != nil { +func (historyMinuteTrade) Frame(date, code string, start, count uint16) (*Frame, error) { + exchange, number, err := DecodeCode(code) + if err != nil { return nil, err } - date := conv.Uint32(req.Date) //req.Time.Format("20060102")) - dataBs := Bytes(date) - dataBs = append(dataBs, req.Exchange.Uint8(), 0x0) - dataBs = append(dataBs, []byte(req.Code)...) - dataBs = append(dataBs, Bytes(req.Start)...) - dataBs = append(dataBs, Bytes(req.Count)...) + dataBs := Bytes(conv.Uint32(date)) //req.Time.Format("20060102")) + dataBs = append(dataBs, exchange.Uint8(), 0x0) + dataBs = append(dataBs, []byte(number)...) + dataBs = append(dataBs, Bytes(start)...) + dataBs = append(dataBs, Bytes(count)...) return &Frame{ Control: Control01, Type: TypeHistoryMinuteTrade, @@ -86,6 +63,11 @@ func (historyMinuteTrade) Decode(bs []byte, code string) (*HistoryMinuteTradeRes return nil, errors.New("数据长度不足") } + _, number, err := DecodeCode(code) + if err != nil { + return nil, err + } + resp := &HistoryMinuteTradeResp{ Count: Uint16(bs[:2]), } @@ -101,7 +83,7 @@ func (historyMinuteTrade) Decode(bs []byte, code string) (*HistoryMinuteTradeRes var sub Price bs, sub = GetPrice(bs[2:]) lastPrice += sub - mt.Price = lastPrice / basePrice(code) + mt.Price = lastPrice / basePrice(number) bs, mt.Volume = CutInt(bs) bs, mt.Status = CutInt(bs) bs, _ = CutInt(bs) //这个得到的是0,不知道是啥 diff --git a/protocol/model_history_minute_trade_test.go b/protocol/model_history_minute_trade_test.go index f4c1aa3..3dde5df 100644 --- a/protocol/model_history_minute_trade_test.go +++ b/protocol/model_history_minute_trade_test.go @@ -7,13 +7,7 @@ import ( func Test_stockHistoryMinuteTrade_Frame(t *testing.T) { // 预期 0c 02000000 00 1200 1200 b50f 84da3401 0000 30303030303100006400 // 0c000000000112001200b50f84da3401000030303030303100006400 - f, err := MHistoryMinuteTrade.Frame(HistoryMinuteTradeReq{ - Date: "20241028", - Exchange: ExchangeSZ, - Code: "000001", - Start: 0, - Count: 100, - }) + f, err := MHistoryMinuteTrade.Frame("20241028", "sz000001", 0, 100) if err != nil { t.Error(err) return diff --git a/protocol/model_minute.go b/protocol/model_minute.go index 9559fde..ae60f43 100644 --- a/protocol/model_minute.go +++ b/protocol/model_minute.go @@ -16,11 +16,12 @@ type PriceNumber struct { type minute struct{} -func (this *minute) Frame(exchange Exchange, code string) (*Frame, error) { - if len(code) != 6 { - return nil, errors.New("股票代码长度错误") +func (this *minute) Frame(code string) (*Frame, error) { + exchange, number, err := DecodeCode(code) + if err != nil { + return nil, err } - codeBs := []byte(code) + codeBs := []byte(number) codeBs = append(codeBs, 0x0, 0x0, 0x0, 0x0) return &Frame{ Control: Control01, diff --git a/protocol/model_minute_trade.go b/protocol/model_minute_trade.go index 7c4d90b..1b7c65a 100644 --- a/protocol/model_minute_trade.go +++ b/protocol/model_minute_trade.go @@ -5,23 +5,6 @@ import ( "fmt" ) -type MinuteTradeReq struct { - Exchange Exchange - Code string - Start uint16 - Count uint16 -} - -func (req MinuteTradeReq) Check() error { - if len(req.Code) != 6 { - return errors.New("股票代码长度错误") - } - if req.Count > 1800 { - return errors.New("数量不能超过1800") - } - return nil -} - type MinuteTradeResp struct { Count uint16 List []*MinuteTrade @@ -79,22 +62,30 @@ func (this *MinuteTrade) IsSell() bool { type minuteTrade struct{} -func (minuteTrade) Frame(req MinuteTradeReq) (*Frame, error) { - if err := req.Check(); err != nil { +func (minuteTrade) Frame(code string, start, count uint16) (*Frame, error) { + exchange, number, err := DecodeCode(code) + if err != nil { return nil, err } - codeBs := []byte(req.Code) - codeBs = append(codeBs, Bytes(req.Start)...) - codeBs = append(codeBs, Bytes(req.Count)...) + + codeBs := []byte(number) + codeBs = append(codeBs, Bytes(start)...) + codeBs = append(codeBs, Bytes(count)...) return &Frame{ Control: Control01, Type: TypeMinuteTrade, - Data: append([]byte{req.Exchange.Uint8(), 0x0}, codeBs...), + Data: append([]byte{exchange.Uint8(), 0x0}, codeBs...), }, nil } func (minuteTrade) Decode(bs []byte, code string) (*MinuteTradeResp, error) { + var err error + _, code, err = DecodeCode(code) + if err != nil { + return nil, err + } + if len(bs) < 2 { return nil, errors.New("数据长度不足") } diff --git a/protocol/model_quote.go b/protocol/model_quote.go index f6f4748..607f3ca 100644 --- a/protocol/model_quote.go +++ b/protocol/model_quote.go @@ -1,7 +1,6 @@ package protocol import ( - "errors" "fmt" "strings" ) @@ -60,20 +59,22 @@ func (this *Quote) String() string { type quote struct{} -func (this quote) Frame(m map[Exchange]string) (*Frame, error) { +func (this quote) Frame(codes ...string) (*Frame, error) { f := &Frame{ Control: Control01, Type: TypeQuote, Data: []byte{0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, } - payload := Bytes(uint16(len(m))) - for k, v := range m { - if len(v) != 6 { - return nil, errors.New("股票代码长度错误") + payload := Bytes(uint16(len(codes))) + for _, v := range codes { + exchange, code, err := DecodeCode(v) + if err != nil { + return nil, err } - payload = append(payload, k.Uint8()) - payload = append(payload, v...) + + payload = append(payload, exchange.Uint8()) + payload = append(payload, code...) } f.Data = append(f.Data, payload...) diff --git a/protocol/unit.go b/protocol/unit.go index ab616cc..4935fd1 100644 --- a/protocol/unit.go +++ b/protocol/unit.go @@ -9,6 +9,7 @@ import ( "golang.org/x/text/transform" "io" "math" + "strings" "time" ) @@ -48,6 +49,20 @@ func UTF8ToGBK(text []byte) []byte { return bytes.ReplaceAll(content, []byte{0x00}, []byte{}) } +func DecodeCode(code string) (Exchange, string, error) { + if len(code) != 8 { + return 0, "", fmt.Errorf("股票代码长度错误,例如:SZ000001") + } + switch strings.ToLower(code[:2]) { + case ExchangeSH.String(): + return ExchangeSH, code[2:], nil + case ExchangeSZ.String(): + return ExchangeSZ, code[2:], nil + default: + return 0, "", fmt.Errorf("股票代码错误,例如:SZ000001") + } +} + func FloatUnit(f float64) (float64, string) { m := []string{"万", "亿"} unit := ""