This commit is contained in:
bense
2022-05-12 21:31:08 +08:00
parent 5ff1b4fe05
commit 562d11daaf
9 changed files with 600 additions and 21 deletions

View File

@@ -201,3 +201,73 @@ func (client *Client) GetIndexBars(category uint16, market uint16, code string,
}
return obj.Reply(), err
}
// GetMinuteTimeData 获取分时图数据
func (client *Client) GetMinuteTimeData(market uint16, code string) (*proto.GetMinuteTimeDataReply, error) {
obj := proto.NewGetMinuteTimeData()
_code := [6]byte{}
copy(_code[:], code)
obj.SetParams(&proto.GetMinuteTimeDataRequest{
Market: market,
Code: _code,
})
err := client.do(obj)
if err != nil {
return nil, err
}
return obj.Reply(), err
}
// GetHistoryMinuteTimeData 获取历史分时图数据
func (client *Client) GetHistoryMinuteTimeData(date uint32, market uint16, code string) (*proto.GetHistoryMinuteTimeDataReply, error) {
obj := proto.NewGetHistoryMinuteTimeData()
_code := [6]byte{}
copy(_code[:], code)
obj.SetParams(&proto.GetHistoryMinuteTimeDataRequest{
Date: date,
Market: uint8(market),
Code: _code,
})
err := client.do(obj)
if err != nil {
return nil, err
}
return obj.Reply(), err
}
// GetTransactionData 获取分时成交
func (client *Client) GetTransactionData(market uint16, code string, start uint16, count uint16) (*proto.GetTransactionDataReply, error) {
obj := proto.NewGetTransactionData()
_code := [6]byte{}
copy(_code[:], code)
obj.SetParams(&proto.GetTransactionDataRequest{
Market: market,
Code: _code,
Start: start,
Count: count,
})
err := client.do(obj)
if err != nil {
return nil, err
}
return obj.Reply(), err
}
// GetHistoryTransactionData 获取历史分时成交
func (client *Client) GetHistoryTransactionData(date uint32, market uint16, code string, start uint16, count uint16) (*proto.GetHistoryTransactionDataReply, error) {
obj := proto.NewGetHistoryTransactionData()
_code := [6]byte{}
copy(_code[:], code)
obj.SetParams(&proto.GetHistoryTransactionDataRequest{
Date: date,
Market: market,
Code: _code,
Start: start,
Count: count,
})
err := client.do(obj)
if err != nil {
return nil, err
}
return obj.Reply(), err
}

View File

@@ -110,3 +110,70 @@ func Test_tdx_GetIndexBars(t *testing.T) {
_ = api.Disconnect()
}
func Test_tdx_GetMinuteTimeData(t *testing.T) {
api := prepare()
reply, err := api.GetMinuteTimeData(0, "159607")
if err != nil {
fmt.Println(err)
}
fmt.Println(reply)
for _, bar := range reply.List {
fmt.Println(bar)
}
_ = api.Disconnect()
}
func Test_tdx_GetHistoryMinuteTimeData(t *testing.T) {
api := prepare()
//reply, err := api.GetHistoryMinuteTimeData(20220511, 0, "159607")
reply, err := api.GetHistoryMinuteTimeData(20220511, 0, "159607")
if err != nil {
fmt.Println(err)
}
fmt.Println(reply)
for _, bar := range reply.List {
fmt.Println(bar)
}
_ = api.Disconnect()
}
func Test_tdx_GetTransactionData(t *testing.T) {
api := prepare()
//reply, err := api.GetHistoryMinuteTimeData(20220511, 0, "159607")
reply, err := api.GetTransactionData(0, "159607", 0, 10)
if err != nil {
fmt.Println(err)
}
fmt.Println(reply)
for _, bar := range reply.List {
fmt.Println(bar)
}
_ = api.Disconnect()
}
func Test_tdx_GetHistoryTransactionData(t *testing.T) {
api := prepare()
//reply, err := api.GetHistoryMinuteTimeData(20220511, 0, "159607")
reply, err := api.GetHistoryTransactionData(20220511, 0, "159607", 0, 10)
if err != nil {
fmt.Println(err)
}
fmt.Println(reply)
for _, bar := range reply.List {
fmt.Println(bar)
}
_ = api.Disconnect()
}

View File

@@ -0,0 +1,112 @@
package proto
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
)
type GetHistoryMinuteTimeData struct {
reqHeader *ReqHeader
respHeader *RespHeader
request *GetHistoryMinuteTimeDataRequest
reply *GetHistoryMinuteTimeDataReply
contentHex string
}
type GetHistoryMinuteTimeDataRequest struct {
Date uint32
Market uint8
Code [6]byte
}
type GetHistoryMinuteTimeDataReply struct {
Count uint16
List []HistoryMinuteTimeData
}
type HistoryMinuteTimeData struct {
Price float32
Vol int
}
func NewGetHistoryMinuteTimeData() *GetHistoryMinuteTimeData {
obj := new(GetHistoryMinuteTimeData)
obj.reqHeader = new(ReqHeader)
obj.respHeader = new(RespHeader)
obj.request = new(GetHistoryMinuteTimeDataRequest)
obj.reply = new(GetHistoryMinuteTimeDataReply)
obj.reqHeader.Zip = 0x0c
obj.reqHeader.SeqID = seqID()
obj.reqHeader.PacketType = 0x00
//obj.reqHeader.PkgLen1 =
//obj.reqHeader.PkgLen2 =
obj.reqHeader.Method = KMSG_HISTORYMINUTETIMEDATE
//obj.reqHeader.Method = KMSG_MINUTETIMEDATA
obj.contentHex = ""
return obj
}
func (obj *GetHistoryMinuteTimeData) SetParams(req *GetHistoryMinuteTimeDataRequest) {
obj.request = req
}
func (obj *GetHistoryMinuteTimeData) Serialize() ([]byte, error) {
obj.reqHeader.PkgLen1 = 0x0d
obj.reqHeader.PkgLen2 = 0x0d
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.LittleEndian, obj.reqHeader)
err = binary.Write(buf, binary.LittleEndian, obj.request)
b, err := hex.DecodeString(obj.contentHex)
buf.Write(b)
//b, err := hex.DecodeString(obj.contentHex)
//buf.Write(b)
//err = binary.Write(buf, binary.LittleEndian, uint16(len(obj.stocks)))
return buf.Bytes(), err
}
// 结果数据都是\n,\t分隔的中文字符串比如查询K线数据返回的结果字符串就形如
///“时间\t开盘价\t收盘价\t最高价\t最低价\t成交量\t成交额\n
///20150519\t4.644000\t4.732000\t4.747000\t4.576000\t146667487\t683638848.000000\n
///20150520\t4.756000\t4.850000\t4.960000\t4.756000\t353161092\t1722953216.000000”
func (obj *GetHistoryMinuteTimeData) UnSerialize(header interface{}, data []byte) error {
obj.respHeader = header.(*RespHeader)
fmt.Println(hex.EncodeToString(data))
pos := 0
err := binary.Read(bytes.NewBuffer(data[pos:pos+2]), binary.LittleEndian, &obj.reply.Count)
pos += 2
// 跳过4个字节 功能未解析
_, _, _, bType := data[pos], data[pos+1], data[pos+2], data[pos+3]
pos += 4
lastprice := 0
for index := uint16(0); index < obj.reply.Count; index++ {
priceraw := getprice(data, &pos)
_ = getprice(data, &pos)
vol := getprice(data, &pos)
lastprice += priceraw
var p float32
if bType > 0x40 {
p = float32(lastprice) / 100.0
} else {
p = float32(lastprice) / 1000.0
}
ele := HistoryMinuteTimeData{Price: p,
Vol: vol}
obj.reply.List = append(obj.reply.List, ele)
}
return err
}
func (obj *GetHistoryMinuteTimeData) Reply() *GetHistoryMinuteTimeDataReply {
return obj.reply
}

View File

@@ -0,0 +1,106 @@
package proto
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
)
type GetHistoryTransactionData struct {
reqHeader *ReqHeader
respHeader *RespHeader
request *GetHistoryTransactionDataRequest
reply *GetHistoryTransactionDataReply
contentHex string
}
type GetHistoryTransactionDataRequest struct {
Date uint32
Market uint16
Code [6]byte
Start uint16
Count uint16
}
type GetHistoryTransactionDataReply struct {
Count uint16
List []HistoryTransactionData
}
type HistoryTransactionData struct {
Time string
Price float64
Vol int
Num int
BuyOrSell int
}
func NewGetHistoryTransactionData() *GetHistoryTransactionData {
obj := new(GetHistoryTransactionData)
obj.reqHeader = new(ReqHeader)
obj.respHeader = new(RespHeader)
obj.request = new(GetHistoryTransactionDataRequest)
obj.reply = new(GetHistoryTransactionDataReply)
obj.reqHeader.Zip = 0x0c
obj.reqHeader.SeqID = seqID()
obj.reqHeader.PacketType = 0x00
//obj.reqHeader.PkgLen1 =
//obj.reqHeader.PkgLen2 =
obj.reqHeader.Method = KMSG_HISTORYTRANSACTIONDATA
//obj.reqHeader.Method = KMSG_MINUTETIMEDATA
obj.contentHex = ""
return obj
}
func (obj *GetHistoryTransactionData) SetParams(req *GetHistoryTransactionDataRequest) {
obj.request = req
}
func (obj *GetHistoryTransactionData) Serialize() ([]byte, error) {
obj.reqHeader.PkgLen1 = 0x12
obj.reqHeader.PkgLen2 = 0x12
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.LittleEndian, obj.reqHeader)
err = binary.Write(buf, binary.LittleEndian, obj.request)
b, err := hex.DecodeString(obj.contentHex)
buf.Write(b)
//b, err := hex.DecodeString(obj.contentHex)
//buf.Write(b)
//err = binary.Write(buf, binary.LittleEndian, uint16(len(obj.stocks)))
return buf.Bytes(), err
}
func (obj *GetHistoryTransactionData) UnSerialize(header interface{}, data []byte) error {
obj.respHeader = header.(*RespHeader)
pos := 0
err := binary.Read(bytes.NewBuffer(data[pos:pos+2]), binary.LittleEndian, &obj.reply.Count)
// 跳过4个字节
pos += 6
lastprice := 0
for index := uint16(0); index < obj.reply.Count; index++ {
ele := HistoryTransactionData{}
h, m := gettime(data, &pos)
ele.Time = fmt.Sprintf("%02d:%02d", h, m)
priceraw := getprice(data, &pos)
ele.Vol = getprice(data, &pos)
ele.BuyOrSell = getprice(data, &pos)
getprice(data, &pos)
lastprice = lastprice + priceraw
ele.Price = float64(lastprice) / baseUnit(string(obj.request.Code[:]))
obj.reply.List = append(obj.reply.List, ele)
}
return err
}
func (obj *GetHistoryTransactionData) Reply() *GetHistoryTransactionDataReply {
return obj.reply
}

View File

@@ -27,10 +27,10 @@ type GetIndexBarsRequest struct {
type GetIndexBarsReply struct {
Count uint16
List []GetIndexBar
List []IndexBar
}
type GetIndexBar struct {
type IndexBar struct {
Open float64
Close float64
High float64
@@ -98,7 +98,7 @@ func (obj *GetIndexBars) UnSerialize(header interface{}, data []byte) error {
pre_diff_base := 0
//lasttime := ""
for index := uint16(0); index < obj.reply.Count; index++ {
ele := GetIndexBar{}
ele := IndexBar{}
ele.Year, ele.Month, ele.Day, ele.Hour, ele.Minute = getdatetime(int(obj.request.Category), data, &pos)

View File

@@ -0,0 +1,102 @@
package proto
// todo API未有效解析
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
)
type GetMinuteTimeData struct {
reqHeader *ReqHeader
respHeader *RespHeader
request *GetMinuteTimeDataRequest
reply *GetMinuteTimeDataReply
contentHex string
}
type GetMinuteTimeDataRequest struct {
Market uint16
Code [6]byte
Date uint32
}
type GetMinuteTimeDataReply struct {
Count uint16
List []MinuteTimeData
}
type MinuteTimeData struct {
Price float32
Vol int
}
func NewGetMinuteTimeData() *GetMinuteTimeData {
obj := new(GetMinuteTimeData)
obj.reqHeader = new(ReqHeader)
obj.respHeader = new(RespHeader)
obj.request = new(GetMinuteTimeDataRequest)
obj.reply = new(GetMinuteTimeDataReply)
obj.reqHeader.Zip = 0x0c
obj.reqHeader.SeqID = seqID()
obj.reqHeader.PacketType = 0x00
//obj.reqHeader.PkgLen1 =
//obj.reqHeader.PkgLen2 =
obj.reqHeader.Method = 0x051d
//obj.reqHeader.Method = KMSG_MINUTETIMEDATA
obj.contentHex = ""
return obj
}
func (obj *GetMinuteTimeData) SetParams(req *GetMinuteTimeDataRequest) {
obj.request = req
}
func (obj *GetMinuteTimeData) Serialize() ([]byte, error) {
obj.reqHeader.PkgLen1 = 0x0e
obj.reqHeader.PkgLen2 = 0x0e
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.LittleEndian, obj.reqHeader)
err = binary.Write(buf, binary.LittleEndian, obj.request)
b, err := hex.DecodeString(obj.contentHex)
buf.Write(b)
//b, err := hex.DecodeString(obj.contentHex)
//buf.Write(b)
//err = binary.Write(buf, binary.LittleEndian, uint16(len(obj.stocks)))
return buf.Bytes(), err
}
// 结果数据都是\n,\t分隔的中文字符串比如查询K线数据返回的结果字符串就形如
///“时间\t开盘价\t收盘价\t最高价\t最低价\t成交量\t成交额\n
///20150519\t4.644000\t4.732000\t4.747000\t4.576000\t146667487\t683638848.000000\n
///20150520\t4.756000\t4.850000\t4.960000\t4.756000\t353161092\t1722953216.000000”
func (obj *GetMinuteTimeData) UnSerialize(header interface{}, data []byte) error {
obj.respHeader = header.(*RespHeader)
fmt.Println(hex.EncodeToString(data))
pos := 0
err := binary.Read(bytes.NewBuffer(data[pos:pos+2]), binary.LittleEndian, &obj.reply.Count)
// 跳过4个字节
pos += 6
lastprice := 0
for index := uint16(0); index < obj.reply.Count; index++ {
priceraw := getprice(data, &pos)
getprice(data, &pos)
vol := getprice(data, &pos)
lastprice = lastprice + priceraw
ele := MinuteTimeData{float32(lastprice) / 100.0, vol}
obj.reply.List = append(obj.reply.List, ele)
}
return err
}
func (obj *GetMinuteTimeData) Reply() *GetMinuteTimeDataReply {
return obj.reply
}

View File

@@ -27,10 +27,10 @@ type GetSecurityBarsRequest struct {
type GetSecurityBarsReply struct {
Count uint16
List []GetSecurityBar
List []SecurityBar
}
type GetSecurityBar struct {
type SecurityBar struct {
Open float64
Close float64
High float64
@@ -100,7 +100,7 @@ func (obj *GetSecurityBars) UnSerialize(header interface{}, data []byte) error {
pre_diff_base := 0
for index := uint16(0); index < obj.reply.Count; index++ {
ele := GetSecurityBar{}
ele := SecurityBar{}
ele.Year, ele.Month, ele.Day, ele.Hour, ele.Minute = getdatetime(int(obj.request.Category), data, &pos)
ele.DateTime = fmt.Sprintf("%d-%02d-%02d %02d:%02d:00", ele.Year, ele.Month, ele.Day, ele.Hour, ele.Minute)

View File

@@ -0,0 +1,104 @@
package proto
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
)
type GetTransactionData struct {
reqHeader *ReqHeader
respHeader *RespHeader
request *GetTransactionDataRequest
reply *GetTransactionDataReply
contentHex string
}
type GetTransactionDataRequest struct {
Market uint16
Code [6]byte
Start uint16
Count uint16
}
type GetTransactionDataReply struct {
Count uint16
List []TransactionData
}
type TransactionData struct {
Time string
Price float64
Vol int
Num int
BuyOrSell int
}
func NewGetTransactionData() *GetTransactionData {
obj := new(GetTransactionData)
obj.reqHeader = new(ReqHeader)
obj.respHeader = new(RespHeader)
obj.request = new(GetTransactionDataRequest)
obj.reply = new(GetTransactionDataReply)
obj.reqHeader.Zip = 0x0c
obj.reqHeader.SeqID = seqID()
obj.reqHeader.PacketType = 0x00
//obj.reqHeader.PkgLen1 =
//obj.reqHeader.PkgLen2 =
obj.reqHeader.Method = KMSG_TRANSACTIONDATA
//obj.reqHeader.Method = KMSG_MINUTETIMEDATA
obj.contentHex = ""
return obj
}
func (obj *GetTransactionData) SetParams(req *GetTransactionDataRequest) {
obj.request = req
}
func (obj *GetTransactionData) Serialize() ([]byte, error) {
obj.reqHeader.PkgLen1 = 0x0e
obj.reqHeader.PkgLen2 = 0x0e
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.LittleEndian, obj.reqHeader)
err = binary.Write(buf, binary.LittleEndian, obj.request)
b, err := hex.DecodeString(obj.contentHex)
buf.Write(b)
//b, err := hex.DecodeString(obj.contentHex)
//buf.Write(b)
//err = binary.Write(buf, binary.LittleEndian, uint16(len(obj.stocks)))
return buf.Bytes(), err
}
func (obj *GetTransactionData) UnSerialize(header interface{}, data []byte) error {
obj.respHeader = header.(*RespHeader)
pos := 0
err := binary.Read(bytes.NewBuffer(data[pos:pos+2]), binary.LittleEndian, &obj.reply.Count)
pos += 2
lastprice := 0
for index := uint16(0); index < obj.reply.Count; index++ {
ele := TransactionData{}
hour, minute := gettime(data, &pos)
ele.Time = fmt.Sprintf("%02d:%02d", hour, minute)
priceraw := getprice(data, &pos)
ele.Vol = getprice(data, &pos)
ele.Num = getprice(data, &pos)
ele.BuyOrSell = getprice(data, &pos)
lastprice += priceraw
ele.Price = float64(lastprice) / baseUnit(string(obj.request.Code[:]))
_ = getprice(data, &pos)
obj.reply.List = append(obj.reply.List, ele)
}
return err
}
func (obj *GetTransactionData) Reply() *GetTransactionDataReply {
return obj.reply
}

View File

@@ -102,34 +102,42 @@ func seqID() uint32 {
// pytdx : 类似utf-8的编码方式保存有符号数字
func getprice(b []byte, pos *int) int {
posbype := 6
bdata := b[*pos]
intdata := int(bdata & 0x3f)
/*
0x7f与常量做与运算实质是保留常量转换为二进制形式的后7位数既取值区间为[0,127]
0x3f与常量做与运算实质是保留常量转换为二进制形式的后6位数既取值区间为[0,63]
sign := false
if (bdata & 0x40) > 0 {
sign = true
0x80 1000 0000
0x7f 0111 1111
0x40 100 0000
0x3f 011 1111
*/
posByte := 6
bData := b[*pos]
data := int(bData & 0x3f)
bSign := false
if (bData & 0x40) > 0 {
bSign = true
}
if (bdata & 0x80) > 0 {
if (bData & 0x80) > 0 {
for {
*pos += 1
bdata = b[*pos]
intdata += (int(bdata&0x7f) << posbype)
bData = b[*pos]
data += (int(bData&0x7f) << posByte)
posbype += 7
posByte += 7
if (bdata & 0x80) <= 0 {
if (bData & 0x80) <= 0 {
break
}
}
}
*pos += 1
*pos++
if sign {
intdata = -intdata
if bSign {
data = -data
}
return intdata
return data
}
func gettime(b []byte, pos *int) (h uint16, m uint16) {
@@ -278,3 +286,13 @@ func getvolume(ivol int) (volume float64) {
volume = dbl_xmm6 + dbl_xmm4 + dbl_xmm3 + dbl_xmm1
return
}
func baseUnit(code string) float64 {
c := code[:2]
switch c {
case "60", "30", "68", "00":
return 100.0
}
return 1000.0
}