增加分时成交函数,数据已经校对,和通达信和东方财富能对应上

This commit is contained in:
钱纯净
2024-10-28 22:52:33 +08:00
parent 791bd4bfac
commit 6ec87de116
12 changed files with 191 additions and 62 deletions

View File

@@ -3,9 +3,9 @@
### 开发进度
* 能通讯,有响应数据,还未解析响应数据
![](docs/plan.png)
* 基本信息(5档报价)
![](docs/plan20241025.png)
* 基本信息(股票列表)
![](docs/plan20241028.png)
* 股票列表
![](docs/plan20241028-1.png)
* 分时成交
![](docs/plan20241028-2.png)

View File

@@ -82,6 +82,9 @@ func (this *Client) handlerDealMessage(c *client.Client, msg ios.Acker) {
case protocol.TypeStockMinute:
resp, err = protocol.MStockMinute.Decode(f.Data)
case protocol.TypeStockMinuteTrade:
resp, err = protocol.MStockMinuteTrade.Decode(f.Data, "") //todo
}
if err != nil {
@@ -162,3 +165,16 @@ func (this *Client) GetStockMinute(exchange protocol.Exchange, code string) (*pr
}
return result.(*protocol.StockMinuteResp), nil
}
// GetStockMinuteTrade 获取分时交易详情
func (this *Client) GetStockMinuteTrade(exchange protocol.Exchange, code string, start, count uint16) (*protocol.StockMinuteTradeResp, error) {
f, err := protocol.MStockMinuteTrade.Frame(exchange, code, start, count)
if err != nil {
return nil, err
}
result, err := this.SendFrame(f)
if err != nil {
return nil, err
}
return result.(*protocol.StockMinuteTradeResp), nil
}

View File

@@ -1,45 +0,0 @@
package tdx
const (
MarketSH = 0 // 上海
MarketSZ = 1 // 深圳
MarketBJ = 2 // 北京
)
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 线
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

View File

Before

Width:  |  Height:  |  Size: 374 KiB

After

Width:  |  Height:  |  Size: 374 KiB

View File

@@ -10,7 +10,7 @@ func main() {
c, err := tdx.Dial("124.71.187.122:7709")
logs.PanicErr(err)
resp, err := c.GetStockList(protocol.ExchangeSH, 200)
resp, err := c.GetStockList(protocol.ExchangeSH, 255)
logs.PanicErr(err)
for _, v := range resp.List {

View File

@@ -0,0 +1,23 @@
package main
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.GetStockMinuteTrade(protocol.ExchangeSH, "000001", 0, 100)
logs.PanicErr(err)
for _, v := range resp.List {
logs.Debug(v)
}
logs.Debug("总数:", resp.Count)
})
}

13
example/common/common.go Normal file
View File

@@ -0,0 +1,13 @@
package common
import (
"github.com/injoyai/logs"
"github.com/injoyai/tdx"
)
func Test(f func(c *tdx.Client)) {
c, err := tdx.Dial("124.71.187.122:7709")
logs.PanicErr(err)
f(c)
<-c.Done()
}

View File

@@ -1,12 +1,13 @@
package protocol
const (
TypeConnect = 0x000D //建立连接
TypeHeart = 0x0004 //心跳
TypeStockCount = 0x044E //获取股票数量
TypeStockList = 0x0450 //获取股票代码
TypeStockQuote = 0x053E //行情信息
TypeStockMinute = 0x051D //分时数据
TypeConnect = 0x000D //建立连接
TypeHeart = 0x0004 //心跳
TypeStockCount = 0x044E //获取股票数量
TypeStockList = 0x0450 //获取股票代码
TypeStockQuote = 0x053E //行情信息
TypeStockMinute = 0x051D //分时数据
TypeStockMinuteTrade = 0x0FC5 //分时交易
)
/*

View File

@@ -9,12 +9,13 @@ import (
)
var (
MConnect = connect{}
MHeart = heart{}
MStockCount = stockCount{}
MStockQuote = stockQuote{}
MStockList = stockList{}
MStockMinute = stockMinute{}
MConnect = connect{}
MHeart = heart{}
MStockCount = stockCount{}
MStockQuote = stockQuote{}
MStockList = stockList{}
MStockMinute = stockMinute{}
MStockMinuteTrade = stockMinuteTrade{}
)
type ConnectResp struct {

View File

@@ -0,0 +1,101 @@
package protocol
import (
"errors"
"fmt"
)
type StockMinuteTradeResp struct {
Count uint16
List []*StockMinuteTrade
}
type StockMinuteTrade struct {
Time string //时间
Price Price //价格
Volume int //成交量
Number int //单数
Status int //0是买1是卖2无效汇总出现
}
func (this *StockMinuteTrade) String() string {
return fmt.Sprintf("%s \t%s \t%-6d(手) \t%-4d(单) \t%-4s", this.Time, this.Price, this.Volume, this.Number, this.StatusString())
}
func (this *StockMinuteTrade) StatusString() string {
switch this.Status {
case 0:
return "买入"
case 1:
return "卖出"
default:
return ""
}
}
// AvgVolume 平均每单成交量
func (this *StockMinuteTrade) AvgVolume() float64 {
return float64(this.Volume) / float64(this.Number)
}
// AvgPrice 平均每单成交金额
func (this *StockMinuteTrade) AvgPrice() Price {
return Price(this.AvgVolume() * float64(this.Price) * 100)
}
// IsBuy 是否是买单
func (this *StockMinuteTrade) IsBuy() bool {
return this.Status == 0
}
// IsSell 是否是卖单
func (this *StockMinuteTrade) IsSell() bool {
return this.Status == 1
}
type stockMinuteTrade struct{}
func (stockMinuteTrade) Frame(exchange Exchange, code string, start, count uint16) (*Frame, error) {
if len(code) != 6 {
return nil, errors.New("股票代码长度错误")
}
codeBs := []byte(code)
codeBs = append(codeBs, Bytes(start)...)
codeBs = append(codeBs, Bytes(count)...)
return &Frame{
Control: Control01,
Type: TypeStockMinuteTrade,
Data: append([]byte{exchange.Uint8(), 0x0}, codeBs...),
}, nil
}
func (stockMinuteTrade) Decode(bs []byte, code string) (*StockMinuteTradeResp, error) {
if len(bs) < 2 {
return nil, errors.New("数据长度不足")
}
resp := &StockMinuteTradeResp{
Count: Uint16(bs[:2]),
}
bs = bs[2:]
lastPrice := Price(0)
for i := uint16(0); i < resp.Count; i++ {
mt := &StockMinuteTrade{
Time: GetTime([2]byte(bs[:2])),
}
var sub Price
bs, sub = GetPrice(bs[2:])
lastPrice += sub
mt.Price = lastPrice / basePrice(code)
bs, mt.Volume = CutInt(bs)
bs, mt.Number = CutInt(bs)
bs, mt.Status = CutInt(bs)
bs, _ = CutInt(bs) //这个得到的是0不知道是啥
resp.List = append(resp.List, mt)
}
return resp, nil
}

View File

@@ -61,3 +61,22 @@ func FloatUnitString(f float64) string {
func IntUnitString(n int) string {
return FloatUnitString(float64(n))
}
func GetTime(bs [2]byte) string {
n := Uint16(bs[:])
h := n / 60
m := n % 60
return fmt.Sprintf("%02d:%02d", h, m)
}
func basePrice(code string) Price {
if len(code) == 0 {
return 1
}
switch code[:2] {
case "60", "30", "68", "00":
return 1
default:
return 10
}
}