mirror of
https://github.com/injoyai/tdx.git
synced 2025-11-26 21:25:35 +08:00
吧代码的传参方式从sz,000001改成sz000001
This commit is contained in:
39
client.go
39
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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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:]) {
|
||||
|
||||
@@ -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,不知道是啥
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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("数据长度不足")
|
||||
}
|
||||
|
||||
@@ -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...)
|
||||
|
||||
|
||||
@@ -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 := ""
|
||||
|
||||
Reference in New Issue
Block a user