Files
bensema-gotdx/proto/proto.go
2023-09-24 08:50:00 +08:00

285 lines
7.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package proto
import (
"bytes"
"encoding/binary"
"math"
"sync/atomic"
"time"
)
const (
MessageHeaderBytes = 0x10
MessageMaxBytes = 1 << 15
)
const (
KMSG_CMD1 = 0x000d // 建立链接
KMSG_CMD2 = 0x0fdb // 建立链接
KMSG_PING = 0x0015 // 测试连接
KMSG_HEARTBEAT = 0xFFFF // 心跳(自定义)
KMSG_SECURITYCOUNT = 0x044e // 证券数量
KMSG_BLOCKINFOMETA = 0x02c5 // 板块文件信息
KMSG_BLOCKINFO = 0x06b9 // 板块文件
KMSG_COMPANYCATEGORY = 0x02cf // 公司信息文件信息
KMSG_COMPANYCONTENT = 0x02d0 // 公司信息描述
KMSG_FINANCEINFO = 0x0010 // 财务信息
KMSG_HISTORYMINUTETIMEDATE = 0x0fb4 // 历史分时信息
KMSG_HISTORYTRANSACTIONDATA = 0x0fb5 // 历史分笔成交信息
KMSG_INDEXBARS = 0x052d // 指数K线
KMSG_SECURITYBARS = 0x052d // 股票K线
KMSG_MINUTETIMEDATA = 0x0537 // 分时数据
KMSG_SECURITYLIST = 0x0450 // 证券列表
KMSG_SECURITYQUOTES = 0x053e // 行情信息
KMSG_TRANSACTIONDATA = 0x0fc5 // 分笔成交信息
KMSG_XDXRINFO = 0x000f // 除权除息信息
)
const (
KLINE_TYPE_5MIN = 0 // 5 分钟K 线
KLINE_TYPE_15MIN = 1 // 15 分钟K 线
KLINE_TYPE_30MIN = 2 // 30 分钟K 线
KLINE_TYPE_1HOUR = 3 // 1 小时K 线
KLINE_TYPE_DAILY = 4 // 日K 线
KLINE_TYPE_WEEKLY = 5 // 周K 线
KLINE_TYPE_MONTHLY = 6 // 月K 线
KLINE_TYPE_EXHQ_1MIN = 7 // 1 分钟
KLINE_TYPE_1MIN = 8 // 1 分钟K 线
KLINE_TYPE_RI_K = 9 // 日K 线
KLINE_TYPE_3MONTH = 10 // 季K 线
KLINE_TYPE_YEARLY = 11 // 年K 线
)
type Msg interface {
Serialize() ([]byte, error)
UnSerialize(head interface{}, in []byte) error
}
var _seqId uint32
/*
0c 02000000 00 1c00 1c00 2d05 0100363030303030080001000000140000000000000000000000
0c 02189300 01 0300 0300 0d00 01
0c 00000000 00 0200 0200 1500
*/
type ReqHeader struct {
Zip uint8 // ZipFlag
SeqID uint32 // 请求编号
PacketType uint8
PkgLen1 uint16
PkgLen2 uint16
Method uint16 // method 请求方法
}
type RespHeader struct {
I1 uint32
I2 uint8
SeqID uint32 // 请求编号
I3 uint8
Method uint16 // method
ZipSize uint16 // 长度
UnZipSize uint16 // 未压缩长度
}
func seqID() uint32 {
atomic.AddUint32(&_seqId, 1)
return _seqId
}
// pytdx : 类似utf-8的编码方式保存有符号数字
func getprice(b []byte, pos *int) int {
/*
0x7f与常量做与运算实质是保留常量转换为二进制形式的后7位数既取值区间为[0,127]
0x3f与常量做与运算实质是保留常量转换为二进制形式的后6位数既取值区间为[0,63]
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 {
for {
*pos += 1
bData = b[*pos]
data += (int(bData&0x7f) << posByte)
posByte += 7
if (bData & 0x80) <= 0 {
break
}
}
}
*pos++
if bSign {
data = -data
}
return data
}
func gettime(b []byte, pos *int) (h uint16, m uint16) {
var sec uint16
binary.Read(bytes.NewBuffer(b[*pos:*pos+2]), binary.LittleEndian, &sec)
h = sec / 60
m = sec % 60
(*pos) += 2
return
}
func getdatetime(category int, b []byte, pos *int) (year int, month int, day int, hour int, minute int) {
hour = 15
if category < 4 || category == 7 || category == 8 {
var zipday, tminutes uint16
binary.Read(bytes.NewBuffer(b[*pos:*pos+2]), binary.LittleEndian, &zipday)
(*pos) += 2
binary.Read(bytes.NewBuffer(b[*pos:*pos+2]), binary.LittleEndian, &tminutes)
(*pos) += 2
year = int((zipday >> 11) + 2004)
month = int((zipday % 2048) / 100)
day = int((zipday % 2048) % 100)
hour = int(tminutes / 60)
minute = int(tminutes % 60)
} else {
var zipday uint32
binary.Read(bytes.NewBuffer(b[*pos:*pos+4]), binary.LittleEndian, &zipday)
(*pos) += 4
year = int(zipday / 10000)
month = int((zipday % 10000) / 100)
day = int(zipday % 100)
}
return
}
func getdatetimenow(category int, lasttime string) (year int, month int, day int, hour int, minute int) {
utime, _ := time.Parse("2006-01-02 15:04:05", lasttime)
switch category {
case KLINE_TYPE_5MIN:
utime = utime.Add(time.Minute * 5)
case KLINE_TYPE_15MIN:
utime = utime.Add(time.Minute * 15)
case KLINE_TYPE_30MIN:
utime = utime.Add(time.Minute * 30)
case KLINE_TYPE_1HOUR:
utime = utime.Add(time.Hour)
case KLINE_TYPE_DAILY:
utime = utime.AddDate(0, 0, 1)
case KLINE_TYPE_WEEKLY:
utime = utime.Add(time.Hour * 24 * 7)
case KLINE_TYPE_MONTHLY:
utime = utime.AddDate(0, 1, 0)
case KLINE_TYPE_EXHQ_1MIN:
utime = utime.Add(time.Minute)
case KLINE_TYPE_1MIN:
utime = utime.Add(time.Minute)
case KLINE_TYPE_RI_K:
utime = utime.AddDate(0, 0, 1)
case KLINE_TYPE_3MONTH:
utime = utime.AddDate(0, 3, 0)
case KLINE_TYPE_YEARLY:
utime = utime.AddDate(1, 0, 0)
}
if category < 4 || category == 7 || category == 8 {
if (utime.Hour() >= 15 && utime.Minute() > 0) || (utime.Hour() > 15) {
utime = utime.AddDate(0, 0, 1)
utime = utime.Add(time.Minute * 30)
hour = (utime.Hour() + 18) % 24
} else {
hour = utime.Hour()
}
minute = utime.Minute()
} else {
if utime.Unix() > time.Now().Unix() {
utime = time.Now()
}
hour = utime.Hour()
minute = utime.Minute()
if utime.Hour() > 15 {
hour = 15
minute = 0
}
}
year = utime.Year()
month = int(utime.Month())
day = utime.Day()
return
}
func getvolume(ivol int) (volume float64) {
logpoint := ivol >> (8 * 3)
//hheax := ivol >> (8 * 3) // [3]
hleax := (ivol >> (8 * 2)) & 0xff // [2]
lheax := (ivol >> 8) & 0xff //[1]
lleax := ivol & 0xff //[0]
//dbl_1 := 1.0
//dbl_2 := 2.0
//dbl_128 := 128.0
dwEcx := logpoint*2 - 0x7f
dwEdx := logpoint*2 - 0x86
dwEsi := logpoint*2 - 0x8e
dwEax := logpoint*2 - 0x96
tmpEax := dwEcx
if dwEcx < 0 {
tmpEax = -dwEcx
} else {
tmpEax = dwEcx
}
dbl_xmm6 := 0.0
dbl_xmm6 = math.Pow(2.0, float64(tmpEax))
if dwEcx < 0 {
dbl_xmm6 = 1.0 / dbl_xmm6
}
dbl_xmm4 := 0.0
dbl_xmm0 := 0.0
if hleax > 0x80 {
tmpdbl_xmm3 := 0.0
//tmpdbl_xmm1 := 0.0
dwtmpeax := dwEdx + 1
tmpdbl_xmm3 = math.Pow(2.0, float64(dwtmpeax))
dbl_xmm0 = math.Pow(2.0, float64(dwEdx)) * 128.0
dbl_xmm0 += float64(hleax&0x7f) * tmpdbl_xmm3
dbl_xmm4 = dbl_xmm0
} else {
if dwEdx >= 0 {
dbl_xmm0 = math.Pow(2.0, float64(dwEdx)) * float64(hleax)
} else {
dbl_xmm0 = (1 / math.Pow(2.0, float64(dwEdx))) * float64(hleax)
}
dbl_xmm4 = dbl_xmm0
}
dbl_xmm3 := math.Pow(2.0, float64(dwEsi)) * float64(lheax)
dbl_xmm1 := math.Pow(2.0, float64(dwEax)) * float64(lleax)
if (hleax & 0x80) > 0 {
dbl_xmm3 *= 2.0
dbl_xmm1 *= 2.0
}
volume = dbl_xmm6 + dbl_xmm4 + dbl_xmm3 + dbl_xmm1
return
}
func baseUnit(code string) float64 {
switch code[:2] {
case "60", "30", "68", "00":
return 100.0
default:
return 1000.0
}
}