减少方法名称长度,去掉固定前缀Stock

This commit is contained in:
injoyai
2024-10-31 10:16:49 +08:00
parent fc604d1eff
commit c6e701af1b
27 changed files with 502 additions and 390 deletions

View File

@@ -16,7 +16,8 @@
### 数据校对
* 日K线校对
![](docs/check_kline.png) ![](docs/check_kline_right.png)
![](docs/check_kline.png)
![](docs/check_kline_right.png)
* 校对分时成交
![](docs/check_trade.png)
@@ -40,7 +41,7 @@ func main() {
if err != nil {
panic(err)
}
resp, err := c.GetStockQuotes(map[protocol.Exchange]string{
resp, err := c.GetQuote(map[protocol.Exchange]string{
protocol.ExchangeSH: "000001",
protocol.ExchangeSZ: "600008",
})

266
client.go
View File

@@ -1,7 +1,6 @@
package tdx
import (
"errors"
"fmt"
"github.com/injoyai/base/maps"
"github.com/injoyai/base/maps/wait/v2"
@@ -102,26 +101,26 @@ func (this *Client) handlerDealMessage(c *client.Client, msg ios.Acker) {
case protocol.TypeHeart:
case protocol.TypeStockCount:
resp, err = protocol.MStockCount.Decode(f.Data)
case protocol.TypeCount:
resp, err = protocol.MCount.Decode(f.Data)
case protocol.TypeStockList:
resp, err = protocol.MStockList.Decode(f.Data)
case protocol.TypeCode:
resp, err = protocol.MCode.Decode(f.Data)
case protocol.TypeStockQuote:
resp = protocol.MStockQuote.Decode(f.Data)
case protocol.TypeQuote:
resp = protocol.MQuote.Decode(f.Data)
case protocol.TypeStockMinute:
resp, err = protocol.MStockMinute.Decode(f.Data)
case protocol.TypeMinute:
resp, err = protocol.MMinute.Decode(f.Data)
case protocol.TypeStockMinuteTrade:
resp, err = protocol.MStockMinuteTrade.Decode(f.Data, conv.String(val)) //todo
case protocol.TypeMinuteTrade:
resp, err = protocol.MMinuteTrade.Decode(f.Data, conv.String(val)) //todo
case protocol.TypeStockHistoryMinuteTrade:
resp, err = protocol.MStockHistoryMinuteTrade.Decode(f.Data, conv.String(val))
case protocol.TypeHistoryMinuteTrade:
resp, err = protocol.MHistoryMinuteTrade.Decode(f.Data, conv.String(val))
case protocol.TypeStockKline:
resp, err = protocol.MStockKline.Decode(f.Data, protocol.TypeKline(conv.Uint16(val)))
case protocol.TypeKline:
resp, err = protocol.MKline.Decode(f.Data, conv.Uint8(val))
default:
err = fmt.Errorf("通讯类型未解析:0x%X", f.Type)
@@ -149,36 +148,36 @@ func (this *Client) SendFrame(f *protocol.Frame, cache ...any) (any, error) {
return this.Wait.Wait(conv.String(this.msgID))
}
// GetStockCount 获取市场内的股票数量
func (this *Client) GetStockCount(exchange protocol.Exchange) (*protocol.StockCountResp, error) {
f := protocol.MStockCount.Frame(exchange)
// GetCount 获取市场内的股票数量
func (this *Client) GetCount(exchange protocol.Exchange) (*protocol.CountResp, error) {
f := protocol.MCount.Frame(exchange)
result, err := this.SendFrame(f)
if err != nil {
return nil, err
}
return result.(*protocol.StockCountResp), nil
return result.(*protocol.CountResp), nil
}
// GetStockList 获取市场内指定范围内的所有证券代码,一次固定返回1000只,上证股票有效范围370-1480
// GetCode 获取市场内指定范围内的所有证券代码,一次固定返回1000只,上证股票有效范围370-1480
// 上证前370只是395/399开头的(中证500/总交易等辅助类),在后面的话是一些100开头的国债
// 600开头的股票是上证A股属于大盘股其中6006开头的股票是最早上市的股票 6016开头的股票为大盘蓝筹股900开头的股票是上证B股
// 000开头的股票是深证A股001、002开头的股票也都属于深证A股 其中002开头的股票是深证A股中小企业股票200开头的股票是深证B股
// 300开头的股票是创业板股票400开头的股票是三板市场股票。
func (this *Client) GetStockList(exchange protocol.Exchange, start uint16) (*protocol.StockListResp, error) {
f := protocol.MStockList.Frame(exchange, start)
func (this *Client) GetCode(exchange protocol.Exchange, start uint16) (*protocol.CodeResp, error) {
f := protocol.MCode.Frame(exchange, start)
result, err := this.SendFrame(f)
if err != nil {
return nil, err
}
return result.(*protocol.StockListResp), nil
return result.(*protocol.CodeResp), nil
}
// GetStockAll 通过多次请求的方式获取全部证券代码
func (this *Client) GetStockAll(exchange protocol.Exchange) (*protocol.StockListResp, error) {
resp := &protocol.StockListResp{}
// GetCodeAll 通过多次请求的方式获取全部证券代码
func (this *Client) GetCodeAll(exchange protocol.Exchange) (*protocol.CodeResp, error) {
resp := &protocol.CodeResp{}
size := uint16(1000)
for start := uint16(0); ; start += size {
r, err := this.GetStockList(exchange, start)
r, err := this.GetCode(exchange, start)
if err != nil {
return nil, err
}
@@ -191,9 +190,9 @@ func (this *Client) GetStockAll(exchange protocol.Exchange) (*protocol.StockList
return resp, nil
}
// GetStockQuotes 获取盘口五档报价
func (this *Client) GetStockQuotes(m map[protocol.Exchange]string) (protocol.StockQuotesResp, error) {
f, err := protocol.MStockQuote.Frame(m)
// GetQuote 获取盘口五档报价
func (this *Client) GetQuote(m map[protocol.Exchange]string) (protocol.QuotesResp, error) {
f, err := protocol.MQuote.Frame(m)
if err != nil {
return nil, err
}
@@ -201,12 +200,12 @@ func (this *Client) GetStockQuotes(m map[protocol.Exchange]string) (protocol.Sto
if err != nil {
return nil, err
}
return result.(protocol.StockQuotesResp), nil
return result.(protocol.QuotesResp), nil
}
// GetStockMinute 获取分时数据,todo 解析好像不对
func (this *Client) GetStockMinute(exchange protocol.Exchange, code string) (*protocol.StockMinuteResp, error) {
f, err := protocol.MStockMinute.Frame(exchange, code)
// GetMinute 获取分时数据,todo 解析好像不对
func (this *Client) GetMinute(exchange protocol.Exchange, code string) (*protocol.MinuteResp, error) {
f, err := protocol.MMinute.Frame(exchange, code)
if err != nil {
return nil, err
}
@@ -214,31 +213,33 @@ func (this *Client) GetStockMinute(exchange protocol.Exchange, code string) (*pr
if err != nil {
return nil, err
}
return result.(*protocol.StockMinuteResp), nil
return result.(*protocol.MinuteResp), nil
}
// GetStockMinuteTrade 获取分时交易详情,服务器最多返回1800条,count-start<=1800
func (this *Client) GetStockMinuteTrade(exchange protocol.Exchange, code string, start, count uint16) (*protocol.StockMinuteTradeResp, error) {
if count > 1800 {
return nil, errors.New("数量不能超过1800")
}
f, err := protocol.MStockMinuteTrade.Frame(exchange, code, start, count)
// GetMinuteTrade 获取分时交易详情,服务器最多返回1800条,count-start<=1800
func (this *Client) GetMinuteTrade(req protocol.MinuteTradeReq) (*protocol.MinuteTradeResp, error) {
f, err := protocol.MMinuteTrade.Frame(req)
if err != nil {
return nil, err
}
result, err := this.SendFrame(f, code)
result, err := this.SendFrame(f, req.Code)
if err != nil {
return nil, err
}
return result.(*protocol.StockMinuteTradeResp), nil
return result.(*protocol.MinuteTradeResp), nil
}
// GetStockMinuteTradeAll 获取分时全部交易详情,todo 只做参考 因为交易实时在进行,然后又是分页读取的,所以会出现读取间隔内产生的交易会丢失
func (this *Client) GetStockMinuteTradeAll(exchange protocol.Exchange, code string) (*protocol.StockMinuteTradeResp, error) {
resp := &protocol.StockMinuteTradeResp{}
// GetMinuteTradeAll 获取分时全部交易详情,todo 只做参考 因为交易实时在进行,然后又是分页读取的,所以会出现读取间隔内产生的交易会丢失
func (this *Client) GetMinuteTradeAll(exchange protocol.Exchange, code string) (*protocol.MinuteTradeResp, error) {
resp := &protocol.MinuteTradeResp{}
size := uint16(1800)
for i := uint16(0); ; i += size {
r, err := this.GetStockMinuteTrade(exchange, code, i, size)
for start := uint16(0); ; start += size {
r, err := this.GetMinuteTrade(protocol.MinuteTradeReq{
Exchange: exchange,
Code: code,
Start: start,
Count: size,
})
if err != nil {
return nil, err
}
@@ -252,33 +253,36 @@ func (this *Client) GetStockMinuteTradeAll(exchange protocol.Exchange, code stri
return resp, nil
}
// GetStockHistoryMinuteTrade 获取历史分时交易,,只能获取昨天及之前的数据,服务器最多返回2000条,count-start<=2000
func (this *Client) GetStockHistoryMinuteTrade(t time.Time, exchange protocol.Exchange, code string, start, count uint16) (*protocol.StockHistoryMinuteTradeResp, error) {
if count > 2000 {
return nil, errors.New("数量不能超过2000")
}
f, err := protocol.MStockHistoryMinuteTrade.Frame(t, exchange, code, start, count)
// GetHistoryMinuteTrade 获取历史分时交易,,只能获取昨天及之前的数据,服务器最多返回2000条,count-start<=2000,如果日期输入错误,则返回0
func (this *Client) GetHistoryMinuteTrade(req protocol.HistoryMinuteTradeReq) (*protocol.HistoryMinuteTradeResp, error) {
f, err := protocol.MHistoryMinuteTrade.Frame(req)
if err != nil {
return nil, err
}
result, err := this.SendFrame(f, code)
result, err := this.SendFrame(f, req.Code)
if err != nil {
return nil, err
}
return result.(*protocol.StockHistoryMinuteTradeResp), nil
return result.(*protocol.HistoryMinuteTradeResp), nil
}
// GetStockHistoryMinuteTradeAll 获取历史分时全部交易,通过多次请求来拼接,只能获取昨天及之前的数据
func (this *Client) GetStockHistoryMinuteTradeAll(exchange protocol.Exchange, code string) (*protocol.StockMinuteTradeResp, error) {
resp := &protocol.StockMinuteTradeResp{}
// GetHistoryMinuteTradeAll 获取历史分时全部交易,通过多次请求来拼接,只能获取昨天及之前的数据
func (this *Client) GetHistoryMinuteTradeAll(req protocol.HistoryMinuteTradeAllReq) (*protocol.HistoryMinuteTradeResp, error) {
resp := &protocol.HistoryMinuteTradeResp{}
size := uint16(2000)
for i := uint16(0); ; i += size {
r, err := this.GetStockMinuteTrade(exchange, code, i, size)
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,
})
if err != nil {
return nil, err
}
resp.Count += r.Count
resp.List = append(resp.List, r.List...)
resp.List = append(r.List, resp.List...)
if r.Count < size {
break
}
@@ -286,26 +290,26 @@ func (this *Client) GetStockHistoryMinuteTradeAll(exchange protocol.Exchange, co
return resp, nil
}
// GetStockKline 获取k线数据
func (this *Client) GetStockKline(Type protocol.TypeKline, req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
f, err := protocol.MStockKline.Frame(Type, req)
// GetKline 获取k线数据
func (this *Client) GetKline(Type uint8, req protocol.KlineReq) (*protocol.KlineResp, error) {
f, err := protocol.MKline.Frame(Type, req)
if err != nil {
return nil, err
}
result, err := this.SendFrame(f, Type.Uint16())
result, err := this.SendFrame(f, Type)
if err != nil {
return nil, err
}
return result.(*protocol.StockKlineResp), nil
return result.(*protocol.KlineResp), nil
}
// GetStockKlineAll 获取全部k线数据
func (this *Client) GetStockKlineAll(Type protocol.TypeKline, exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
resp := &protocol.StockKlineResp{}
// GetKlineAll 获取全部k线数据
func (this *Client) GetKlineAll(Type uint8, exchange protocol.Exchange, code string) (*protocol.KlineResp, error) {
resp := &protocol.KlineResp{}
size := uint16(800)
var last *protocol.StockKline
var last *protocol.Kline
for i := uint16(0); ; i += size {
r, err := this.GetStockKline(Type, &protocol.StockKlineReq{
r, err := this.GetKline(Type, protocol.KlineReq{
Exchange: exchange,
Code: code,
Start: i,
@@ -329,102 +333,102 @@ func (this *Client) GetStockKlineAll(Type protocol.TypeKline, exchange protocol.
return resp, nil
}
// GetStockKlineMinute 获取一分钟k线数据
func (this *Client) GetStockKlineMinute(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKlineMinute, req)
// GetKlineMinute 获取一分钟k线数据
func (this *Client) GetKlineMinute(req protocol.KlineReq) (*protocol.KlineResp, error) {
return this.GetKline(protocol.TypeKlineMinute, req)
}
// GetStockKlineMinuteAll 获取一分钟k线全部数据
func (this *Client) GetStockKlineMinuteAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKlineMinute, exchange, code)
// GetKlineMinuteAll 获取一分钟k线全部数据
func (this *Client) GetKlineMinuteAll(exchange protocol.Exchange, code string) (*protocol.KlineResp, error) {
return this.GetKlineAll(protocol.TypeKlineMinute, exchange, code)
}
// GetStockKline5Minute 获取五分钟k线数据
func (this *Client) GetStockKline5Minute(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKline5Minute, req)
// GetKline5Minute 获取五分钟k线数据
func (this *Client) GetKline5Minute(req protocol.KlineReq) (*protocol.KlineResp, error) {
return this.GetKline(protocol.TypeKline5Minute, req)
}
// GetStockKline5MinuteAll 获取5分钟k线全部数据
func (this *Client) GetStockKline5MinuteAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKline5Minute, exchange, code)
// GetKline5MinuteAll 获取5分钟k线全部数据
func (this *Client) GetKline5MinuteAll(exchange protocol.Exchange, code string) (*protocol.KlineResp, error) {
return this.GetKlineAll(protocol.TypeKline5Minute, exchange, code)
}
// GetStockKline15Minute 获取十五分钟k线数据
func (this *Client) GetStockKline15Minute(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKline15Minute, req)
// GetKline15Minute 获取十五分钟k线数据
func (this *Client) GetKline15Minute(req protocol.KlineReq) (*protocol.KlineResp, error) {
return this.GetKline(protocol.TypeKline15Minute, req)
}
// GetStockKline15MinuteAll 获取十五分钟k线全部数据
func (this *Client) GetStockKline15MinuteAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKline15Minute, exchange, code)
// GetKline15MinuteAll 获取十五分钟k线全部数据
func (this *Client) GetKline15MinuteAll(exchange protocol.Exchange, code string) (*protocol.KlineResp, error) {
return this.GetKlineAll(protocol.TypeKline15Minute, exchange, code)
}
// GetStockKline30Minute 获取三十分钟k线数据
func (this *Client) GetStockKline30Minute(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKline30Minute, req)
// GetKline30Minute 获取三十分钟k线数据
func (this *Client) GetKline30Minute(req protocol.KlineReq) (*protocol.KlineResp, error) {
return this.GetKline(protocol.TypeKline30Minute, req)
}
// GetStockKline30MinuteAll 获取三十分钟k线全部数据
func (this *Client) GetStockKline30MinuteAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKline30Minute, exchange, code)
// GetKline30MinuteAll 获取三十分钟k线全部数据
func (this *Client) GetKline30MinuteAll(exchange protocol.Exchange, code string) (*protocol.KlineResp, error) {
return this.GetKlineAll(protocol.TypeKline30Minute, exchange, code)
}
// GetStockKlineHour 获取小时k线数据
func (this *Client) GetStockKlineHour(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKlineHour, req)
// GetKlineHour 获取小时k线数据
func (this *Client) GetKlineHour(req protocol.KlineReq) (*protocol.KlineResp, error) {
return this.GetKline(protocol.TypeKlineHour, req)
}
// GetStockKlineHourAll 获取小时k线全部数据
func (this *Client) GetStockKlineHourAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKlineHour, exchange, code)
// GetKlineHourAll 获取小时k线全部数据
func (this *Client) GetKlineHourAll(exchange protocol.Exchange, code string) (*protocol.KlineResp, error) {
return this.GetKlineAll(protocol.TypeKlineHour, exchange, code)
}
// GetStockKlineDay 获取日k线数据
func (this *Client) GetStockKlineDay(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKlineDay, req)
// GetKlineDay 获取日k线数据
func (this *Client) GetKlineDay(req protocol.KlineReq) (*protocol.KlineResp, error) {
return this.GetKline(protocol.TypeKlineDay, req)
}
// GetStockKlineDayAll 获取日k线全部数据
func (this *Client) GetStockKlineDayAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKlineDay, exchange, code)
// GetKlineDayAll 获取日k线全部数据
func (this *Client) GetKlineDayAll(exchange protocol.Exchange, code string) (*protocol.KlineResp, error) {
return this.GetKlineAll(protocol.TypeKlineDay, exchange, code)
}
// GetStockKlineWeek 获取周k线数据
func (this *Client) GetStockKlineWeek(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKlineWeek, req)
// GetKlineWeek 获取周k线数据
func (this *Client) GetKlineWeek(req protocol.KlineReq) (*protocol.KlineResp, error) {
return this.GetKline(protocol.TypeKlineWeek, req)
}
// GetStockKlineWeekAll 获取周k线全部数据
func (this *Client) GetStockKlineWeekAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKlineWeek, exchange, code)
// GetKlineWeekAll 获取周k线全部数据
func (this *Client) GetKlineWeekAll(exchange protocol.Exchange, code string) (*protocol.KlineResp, error) {
return this.GetKlineAll(protocol.TypeKlineWeek, exchange, code)
}
// GetStockKlineMonth 获取月k线数据
func (this *Client) GetStockKlineMonth(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKlineMonth, req)
func (this *Client) GetStockKlineMonth(req protocol.KlineReq) (*protocol.KlineResp, error) {
return this.GetKline(protocol.TypeKlineMonth, req)
}
// GetStockKlineMonthAll 获取月k线全部数据
func (this *Client) GetStockKlineMonthAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKlineMonth, exchange, code)
// GetKlineMonthAll 获取月k线全部数据
func (this *Client) GetKlineMonthAll(exchange protocol.Exchange, code string) (*protocol.KlineResp, error) {
return this.GetKlineAll(protocol.TypeKlineMonth, exchange, code)
}
// GetStockKlineQuarter 获取季k线数据
func (this *Client) GetStockKlineQuarter(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKlineQuarter, req)
// GetKlineQuarter 获取季k线数据
func (this *Client) GetKlineQuarter(req protocol.KlineReq) (*protocol.KlineResp, error) {
return this.GetKline(protocol.TypeKlineQuarter, req)
}
// GetStockKlineQuarterAll 获取季k线全部数据
func (this *Client) GetStockKlineQuarterAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKlineQuarter, exchange, code)
// GetKlineQuarterAll 获取季k线全部数据
func (this *Client) GetKlineQuarterAll(exchange protocol.Exchange, code string) (*protocol.KlineResp, error) {
return this.GetKlineAll(protocol.TypeKlineQuarter, exchange, code)
}
// GetStockKlineYear 获取年k线数据
func (this *Client) GetStockKlineYear(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
return this.GetStockKline(protocol.TypeKlineYear, req)
// GetKlineYear 获取年k线数据
func (this *Client) GetKlineYear(req protocol.KlineReq) (*protocol.KlineResp, error) {
return this.GetKline(protocol.TypeKlineYear, req)
}
// GetStockKlineYearAll 获取年k线数据
func (this *Client) GetStockKlineYearAll(exchange protocol.Exchange, code string) (*protocol.StockKlineResp, error) {
return this.GetStockKlineAll(protocol.TypeKlineYear, exchange, code)
// GetKlineYearAll 获取年k线数据
func (this *Client) GetKlineYearAll(exchange protocol.Exchange, code string) (*protocol.KlineResp, error) {
return this.GetKlineAll(protocol.TypeKlineYear, exchange, code)
}

View File

@@ -23,9 +23,14 @@ func init() {
}
func TestClient_GetStockHistoryMinuteTrade(t *testing.T) {
ti := time.Date(2024, 10, 28, 0, 0, 0, 0, time.Local)
do(func(c *Client) {
resp, err := c.GetStockHistoryMinuteTrade(ti, protocol.ExchangeSH, "000001", 0, 100)
resp, err := c.GetStockHistoryMinuteTrade(protocol.StockHistoryMinuteTradeReq{
Time: time.Date(2024, 10, 28, 0, 0, 0, 0, time.Local),
Exchange: protocol.ExchangeSZ,
Code: "000001",
Start: 0,
Count: 100,
})
if err != nil {
t.Error(err)
return

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, 369)
resp, err := c.GetCode(protocol.ExchangeSH, 369)
logs.PanicErr(err)
for i, v := range resp.List {

View File

@@ -9,7 +9,7 @@ import (
func main() {
common.Test(func(c *tdx.Client) {
resp, err := c.GetStockAll(protocol.ExchangeSZ)
resp, err := c.GetCodeAll(protocol.ExchangeSZ)
logs.PanicErr(err)
for _, v := range resp.List {

View File

@@ -10,7 +10,7 @@ func main() {
c, err := tdx.Dial("124.71.187.122:7709")
logs.PanicErr(err)
resp, err := c.GetStockCount(protocol.ExchangeSH)
resp, err := c.GetCount(protocol.ExchangeSH)
logs.PanicErr(err)
logs.Debug(resp.Count)

View File

@@ -0,0 +1,26 @@
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.GetHistoryMinuteTrade(protocol.HistoryMinuteTradeReq{
Date: "20241027",
Exchange: protocol.ExchangeSZ,
Code: "000001",
Count: 10,
})
logs.PanicErr(err)
for _, v := range resp.List {
logs.Debug(v)
}
logs.Debug("总数:", resp.Count)
})
}

View File

@@ -5,13 +5,15 @@ import (
"github.com/injoyai/tdx"
"github.com/injoyai/tdx/example/common"
"github.com/injoyai/tdx/protocol"
"time"
)
func main() {
common.Test(func(c *tdx.Client) {
t := time.Date(2024, 10, 28, 0, 0, 0, 0, time.Local)
resp, err := c.GetStockHistoryMinuteTrade(t, protocol.ExchangeSH, "000001", 0, 2000)
resp, err := c.GetHistoryMinuteTradeAll(protocol.HistoryMinuteTradeAllReq{
Date: "20241027",
Exchange: protocol.ExchangeSZ,
Code: "000001",
})
logs.PanicErr(err)
for _, v := range resp.List {

View File

@@ -9,7 +9,7 @@ import (
func main() {
common.Test(func(c *tdx.Client) {
resp, err := c.GetStockKlineDayAll(protocol.ExchangeSH, "000001")
resp, err := c.GetKlineDayAll(protocol.ExchangeSH, "000001")
logs.PanicErr(err)
for _, v := range resp.List {

View File

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

View File

@@ -10,7 +10,12 @@ import (
func main() {
common.Test(func(c *tdx.Client) {
resp, err := c.GetStockMinuteTrade(protocol.ExchangeSH, "000001", 0, 100)
resp, err := c.GetMinuteTrade(protocol.MinuteTradeReq{
Exchange: protocol.ExchangeSZ,
Code: "000001",
Start: 0,
Count: 100,
})
logs.PanicErr(err)
for _, v := range resp.List {

View File

@@ -21,9 +21,9 @@ func main() {
b1cb74001c00000000000d005100bd00789c6378c1cecb252ace6066c5b4898987b9050ed1f90cc5b74c18a5bc18c1b43490fecff09c81819191f13fc3c9f3bb169f5e7dfefeb5ef57f7199a305009308208e5b32bb6bcbf70148712002d7f1e13
b1cb74000c02000000003e05ac00ac000102020000303030303031601294121a1c2d4eadabcf0ed412aae5fc01afb0024561124fbcc08301afa47900b2e3174100bf68871a4201b741b6144302bb09af334403972e96354504ac09b619560e00000000f8ff601201363030303038b60fba04060607429788a70efa04ada37ab2531c12974d91e7449dbc354184b6010001844bad324102b5679ea1014203a65abd8d0143048a6ba4dd01440587e101b3d2029613000000000000b60f
*/
resp, err := c.GetStockQuotes(map[protocol.Exchange]string{
protocol.ExchangeSH: "000001",
protocol.ExchangeSZ: "600008",
resp, err := c.GetQuote(map[protocol.Exchange]string{
protocol.ExchangeSZ: "000001",
protocol.ExchangeSH: "600008",
})
logs.PanicErr(err)

View File

@@ -1,15 +1,15 @@
package protocol
const (
TypeConnect = 0x000D //建立连接
TypeHeart = 0x0004 //心跳
TypeStockCount = 0x044E //获取股票数量
TypeStockList = 0x0450 //获取股票代码
TypeStockQuote = 0x053E //行情信息
TypeStockMinute = 0x051D //分时数据
TypeStockMinuteTrade = 0x0FC5 //分时交易
TypeStockHistoryMinuteTrade = 0x0FB5 //历史分时交易
TypeStockKline = 0x052D //K线图
TypeConnect = 0x000D //建立连接
TypeHeart = 0x0004 //心跳
TypeCount = 0x044E //获取股票数量
TypeCode = 0x0450 //获取股票代码
TypeQuote = 0x053E //行情信息
TypeMinute = 0x051D //分时数据
TypeMinuteTrade = 0x0FC5 //分时交易
TypeHistoryMinuteTrade = 0x0FB5 //历史分时交易
TypeKline = 0x052D //K线图
)
/*

View File

@@ -84,7 +84,7 @@ func Decode(bs []byte) (*Response, error) {
}
if resp.Control&0x10 != 0x10 {
//return nil, fmt.Errorf("控制码不匹配,预期0x1c,得到0x%x", resp.Control)
return nil, fmt.Errorf("请求失败,请检查参数")
}
if int(resp.ZipLength) != len(bs[16:]) {

View File

@@ -5,12 +5,12 @@ import (
"fmt"
)
type StockListResp struct {
type CodeResp struct {
Count uint16
List []*Stock
List []*Code
}
type Stock struct {
type Code struct {
Name string //股票名称
Code string //股票代码
Multiple uint16 //倍数,基本是0x64=100
@@ -18,33 +18,33 @@ type Stock struct {
PreClose float64 //未知
}
func (this *Stock) String() string {
func (this *Code) String() string {
return fmt.Sprintf("%s(%s)", this.Code, this.Name)
}
type stockList struct{}
type code struct{}
func (stockList) Frame(exchange Exchange, start uint16) *Frame {
func (code) Frame(exchange Exchange, start uint16) *Frame {
return &Frame{
Control: Control01,
Type: TypeStockList,
Type: TypeCode,
Data: []byte{exchange.Uint8(), 0x0, uint8(start), uint8(start >> 8)},
}
}
func (stockList) Decode(bs []byte) (*StockListResp, error) {
func (code) Decode(bs []byte) (*CodeResp, error) {
if len(bs) < 2 {
return nil, errors.New("数据长度不足")
}
resp := &StockListResp{
resp := &CodeResp{
Count: Uint16(bs[:2]),
}
bs = bs[2:]
for i := uint16(0); i < resp.Count; i++ {
sec := &Stock{
sec := &Code{
Code: string(bs[:6]),
Multiple: Uint16(bs[6:8]),
Name: string(UTF8ToGBK(bs[8:16])),

View File

@@ -5,15 +5,15 @@ import (
)
var (
MConnect = connect{}
MHeart = heart{}
MStockCount = stockCount{}
MStockQuote = stockQuote{}
MStockList = stockList{}
MStockMinute = stockMinute{}
MStockMinuteTrade = stockMinuteTrade{}
MStockHistoryMinuteTrade = stockHistoryMinuteTrade{}
MStockKline = stockKline{}
MConnect = connect{}
MHeart = heart{}
MCount = count{}
MQuote = quote{}
MCode = code{}
MMinute = minute{}
MMinuteTrade = minuteTrade{}
MHistoryMinuteTrade = historyMinuteTrade{}
MKline = kline{}
)
type ConnectResp struct {

View File

@@ -2,24 +2,24 @@ package protocol
import "errors"
type StockCountResp struct {
type CountResp struct {
Count uint16
}
type stockCount struct{}
type count struct{}
// Frame 0c0200000001080008004e04000075c73301
func (this *stockCount) Frame(exchange Exchange) *Frame {
func (this *count) Frame(exchange Exchange) *Frame {
return &Frame{
Control: Control01,
Type: TypeStockCount,
Type: TypeCount,
Data: []byte{exchange.Uint8(), 0x0, 0x75, 0xc7, 0x33, 0x01}, //后面的4字节不知道啥意思
}
}
func (this *stockCount) Decode(bs []byte) (*StockCountResp, error) {
func (this *count) Decode(bs []byte) (*CountResp, error) {
if len(bs) < 2 {
return nil, errors.New("数据长度不足")
}
return &StockCountResp{Count: Uint16(bs)}, nil
return &CountResp{Count: Uint16(bs)}, nil
}

View File

@@ -0,0 +1,112 @@
package protocol
import (
"errors"
"fmt"
"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
List []*HistoryMinuteTrade
}
type HistoryMinuteTrade struct {
Time string //时间
Price Price //价格
Volume int //成交量
Status int //0是买1是卖2无效汇总出现
}
func (this *HistoryMinuteTrade) String() string {
return fmt.Sprintf("%s \t%s \t%-6s \t%-6d(手) \t%-4s", this.Time, this.Price, this.Amount(), this.Volume, this.StatusString())
}
// Amount 成交额
func (this *HistoryMinuteTrade) Amount() Price {
return this.Price * Price(this.Volume) * 100
}
func (this *HistoryMinuteTrade) StatusString() string {
switch this.Status {
case 0:
return "买入"
case 1:
return "卖出"
default:
return ""
}
}
type historyMinuteTrade struct{}
func (historyMinuteTrade) Frame(req HistoryMinuteTradeReq) (*Frame, error) {
if err := req.Check(); 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)...)
return &Frame{
Control: Control01,
Type: TypeHistoryMinuteTrade,
Data: dataBs,
}, nil
}
func (historyMinuteTrade) Decode(bs []byte, code string) (*HistoryMinuteTradeResp, error) {
if len(bs) < 2 {
return nil, errors.New("数据长度不足")
}
resp := &HistoryMinuteTradeResp{
Count: Uint16(bs[:2]),
}
//第2-6字节不知道是啥
bs = bs[2+4:]
lastPrice := Price(0)
for i := uint16(0); i < resp.Count; i++ {
mt := &HistoryMinuteTrade{
Time: GetHourMinute([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.Status = CutInt(bs)
bs, _ = CutInt(bs) //这个得到的是0不知道是啥
resp.List = append(resp.List, mt)
}
return resp, nil
}

View File

@@ -8,8 +8,13 @@ import (
func Test_stockHistoryMinuteTrade_Frame(t *testing.T) {
// 预期 0c 02000000 00 1200 1200 b50f 84da3401 0000 30303030303100006400
// 0c000000000112001200b50f84da3401000030303030303100006400
ti := time.Date(2024, 10, 28, 0, 0, 0, 0, time.Local)
f, err := MStockHistoryMinuteTrade.Frame(ti, ExchangeSH, "000001", 0, 100)
f, err := MStockHistoryMinuteTrade.Frame(StockHistoryMinuteTradeReq{
Time: time.Date(2024, 10, 28, 0, 0, 0, 0, time.Local),
Exchange: ExchangeSZ,
Code: "000001",
Start: 0,
Count: 100,
})
if err != nil {
t.Error(err)
return

View File

@@ -7,14 +7,14 @@ import (
"time"
)
type StockKlineReq struct {
type KlineReq struct {
Exchange Exchange
Code string
Start uint16
Count uint16
}
func (this *StockKlineReq) Bytes(Type TypeKline) (g.Bytes, error) {
func (this *KlineReq) Bytes(Type uint8) (g.Bytes, error) {
if this.Count > 800 {
return nil, errors.New("单次数量不能超过800")
}
@@ -23,7 +23,7 @@ func (this *StockKlineReq) Bytes(Type TypeKline) (g.Bytes, error) {
}
data := []byte{this.Exchange.Uint8(), 0x0}
data = append(data, []byte(this.Code)...) //这里怎么是正序了?
data = append(data, Bytes(Type.Uint16())...)
data = append(data, Type, 0x0)
data = append(data, 0x01, 0x0)
data = append(data, Bytes(this.Start)...)
data = append(data, Bytes(this.Count)...)
@@ -31,12 +31,12 @@ func (this *StockKlineReq) Bytes(Type TypeKline) (g.Bytes, error) {
return data, nil
}
type StockKlineResp struct {
type KlineResp struct {
Count uint16
List []*StockKline
List []*Kline
}
type StockKline struct {
type Kline struct {
Last Price //昨日收盘价,这个是列表的上一条数据的收盘价如果没有上条数据那么这个值为0
Open Price //开盘价
High Price //最高价
@@ -47,7 +47,7 @@ type StockKline struct {
Time time.Time //时间
}
func (this *StockKline) String() string {
func (this *Kline) String() string {
return fmt.Sprintf("%s 昨收盘:%s 开盘价:%s 最高价:%s 最低价:%s 收盘价:%s 涨跌:%s 涨跌幅:%0.2f 成交量:%s 成交额:%s",
this.Time.Format("2006-01-02 15:04:05"),
this.Last, this.Open, this.High, this.Low, this.Close,
@@ -57,12 +57,12 @@ func (this *StockKline) String() string {
}
// MaxDifference 最大差值,最高-最低
func (this *StockKline) MaxDifference() Price {
func (this *Kline) MaxDifference() Price {
return this.High - this.Low
}
// RisePrice 涨跌金额,第一个数据不准,仅做参考
func (this *StockKline) RisePrice() Price {
func (this *Kline) RisePrice() Price {
if this.Last == 0 {
//稍微数据准确点没减去0这么夸张还是不准的
return this.Close - this.Open
@@ -72,31 +72,31 @@ func (this *StockKline) RisePrice() Price {
}
// RiseRate 涨跌比例/涨跌幅,第一个数据不准,仅做参考
func (this *StockKline) RiseRate() float64 {
func (this *Kline) RiseRate() float64 {
return float64(this.RisePrice()) / float64(this.Open) * 100
}
type stockKline struct{}
type kline struct{}
func (stockKline) Frame(Type TypeKline, req *StockKlineReq) (*Frame, error) {
func (kline) Frame(Type uint8, req KlineReq) (*Frame, error) {
bs, err := req.Bytes(Type)
if err != nil {
return nil, err
}
return &Frame{
Control: Control01,
Type: TypeStockKline,
Type: TypeKline,
Data: bs,
}, nil
}
func (stockKline) Decode(bs []byte, Type TypeKline) (*StockKlineResp, error) {
func (kline) Decode(bs []byte, Type uint8) (*KlineResp, error) {
if len(bs) < 2 {
return nil, errors.New("数据长度不足")
}
resp := &StockKlineResp{
resp := &KlineResp{
Count: Uint16(bs[:2]),
}
@@ -104,7 +104,7 @@ func (stockKline) Decode(bs []byte, Type TypeKline) (*StockKlineResp, error) {
var last Price //上条数据(昨天)的收盘价
for i := uint16(0); i < resp.Count; i++ {
k := &StockKline{
k := &Kline{
Time: GetTime([4]byte(bs[:4]), Type),
}

View File

@@ -4,7 +4,7 @@ import (
"errors"
)
type StockMinuteResp struct {
type MinuteResp struct {
Count uint16
List []PriceNumber
}
@@ -14,9 +14,9 @@ type PriceNumber struct {
Number int
}
type stockMinute struct{}
type minute struct{}
func (this *stockMinute) Frame(exchange Exchange, code string) (*Frame, error) {
func (this *minute) Frame(exchange Exchange, code string) (*Frame, error) {
if len(code) != 6 {
return nil, errors.New("股票代码长度错误")
}
@@ -24,18 +24,18 @@ func (this *stockMinute) Frame(exchange Exchange, code string) (*Frame, error) {
codeBs = append(codeBs, 0x0, 0x0, 0x0, 0x0)
return &Frame{
Control: Control01,
Type: TypeStockMinute,
Type: TypeMinute,
Data: append([]byte{exchange.Uint8(), 0x0}, codeBs...),
}, nil
}
func (this *stockMinute) Decode(bs []byte) (*StockMinuteResp, error) {
func (this *minute) Decode(bs []byte) (*MinuteResp, error) {
if len(bs) < 6 {
return nil, errors.New("数据长度不足")
}
resp := &StockMinuteResp{
resp := &MinuteResp{
Count: Uint16(bs[:2]),
}
//2-6字节是啥?

View File

@@ -0,0 +1,125 @@
package protocol
import (
"errors"
"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
}
// MinuteTrade 分时成交todo 时间没有到秒,客户端上也没有,东方客户端能显示秒
type MinuteTrade struct {
Time string //时间
Price Price //价格
Volume int //成交量
Number int //单数,历史数据改字段无效
Status int //0是买1是卖2无效汇总出现
}
func (this *MinuteTrade) String() string {
return fmt.Sprintf("%s \t%-6s \t%-6s \t%-6d(手) \t%-4d(单) \t%-4s",
this.Time, this.Price, this.Amount(), this.Volume, this.Number, this.StatusString())
}
// Amount 成交额
func (this *MinuteTrade) Amount() Price {
return this.Price * Price(this.Volume) * 100
}
func (this *MinuteTrade) StatusString() string {
switch this.Status {
case 0:
return "买入"
case 1:
return "卖出"
default:
return ""
}
}
// AvgVolume 平均每单成交量
func (this *MinuteTrade) AvgVolume() float64 {
return float64(this.Volume) / float64(this.Number)
}
// AvgPrice 平均每单成交金额
func (this *MinuteTrade) AvgPrice() Price {
return Price(this.AvgVolume() * float64(this.Price) * 100)
}
// IsBuy 是否是买单
func (this *MinuteTrade) IsBuy() bool {
return this.Status == 0
}
// IsSell 是否是卖单
func (this *MinuteTrade) IsSell() bool {
return this.Status == 1
}
type minuteTrade struct{}
func (minuteTrade) Frame(req MinuteTradeReq) (*Frame, error) {
if err := req.Check(); err != nil {
return nil, err
}
codeBs := []byte(req.Code)
codeBs = append(codeBs, Bytes(req.Start)...)
codeBs = append(codeBs, Bytes(req.Count)...)
return &Frame{
Control: Control01,
Type: TypeMinuteTrade,
Data: append([]byte{req.Exchange.Uint8(), 0x0}, codeBs...),
}, nil
}
func (minuteTrade) Decode(bs []byte, code string) (*MinuteTradeResp, error) {
if len(bs) < 2 {
return nil, errors.New("数据长度不足")
}
resp := &MinuteTradeResp{
Count: Uint16(bs[:2]),
}
bs = bs[2:]
lastPrice := Price(0)
for i := uint16(0); i < resp.Count; i++ {
mt := &MinuteTrade{
Time: GetHourMinute([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

@@ -6,9 +6,9 @@ import (
"strings"
)
type StockQuotesResp []*StockQuote
type QuotesResp []*Quote
func (this StockQuotesResp) String() string {
func (this QuotesResp) String() string {
ls := []string(nil)
for _, v := range this {
ls = append(ls, v.String())
@@ -16,7 +16,7 @@ func (this StockQuotesResp) String() string {
return strings.Join(ls, "\n")
}
type StockQuote struct {
type Quote struct {
Exchange Exchange // 市场
Code string // 股票代码 6个ascii字符串
Active1 uint16 // 活跃度
@@ -45,7 +45,7 @@ type StockQuote struct {
Active2 uint16 // 活跃度
}
func (this *StockQuote) String() string {
func (this *Quote) String() string {
return fmt.Sprintf(`%s%s
%s
总量%s, 现量%s, 总金额%s, 内盘%s, 外盘%s
@@ -58,12 +58,12 @@ func (this *StockQuote) String() string {
)
}
type stockQuote struct{}
type quote struct{}
func (this stockQuote) Frame(m map[Exchange]string) (*Frame, error) {
func (this quote) Frame(m map[Exchange]string) (*Frame, error) {
f := &Frame{
Control: Control01,
Type: TypeStockQuote,
Type: TypeQuote,
Data: []byte{0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
}
@@ -105,11 +105,11 @@ b212 昨天收盘价1186
8defd10c 服务时间
c005bed2668e05be15804d8ba12cb3b13a0083c3034100badc029d014201bc990384f70443029da503b7af074403a6e501b9db044504a6e2028dd5048d050000000000005909
*/
func (this stockQuote) Decode(bs []byte) StockQuotesResp {
func (this quote) Decode(bs []byte) QuotesResp {
//logs.Debug(hex.EncodeToString(bs))
resp := StockQuotesResp{}
resp := QuotesResp{}
//前2字节是什么?
bs = bs[2:]
@@ -118,7 +118,7 @@ func (this stockQuote) Decode(bs []byte) StockQuotesResp {
bs = bs[2:]
for i := uint16(0); i < number; i++ {
sec := &StockQuote{
sec := &Quote{
Exchange: Exchange(bs[0]),
Code: string(UTF8ToGBK(bs[1:7])),
Active1: Uint16(bs[7:9]),

View File

@@ -1,66 +0,0 @@
package protocol
import (
"errors"
"github.com/injoyai/conv"
"time"
)
// StockHistoryMinuteTradeResp 历史分时交易比实时少了单量
type StockHistoryMinuteTradeResp struct {
Count uint16
List []*StockMinuteTrade
}
type StockHistoryMinuteTrade struct {
Time string //时间
Price Price //价格
Volume int //成交量
Status int //0是买1是卖2无效汇总出现
}
type stockHistoryMinuteTrade struct{}
func (stockHistoryMinuteTrade) Frame(t time.Time, exchange Exchange, code string, start, count uint16) (*Frame, error) {
date := conv.Uint32(t.Format("20060102"))
dataBs := Bytes(date)
dataBs = append(dataBs, exchange.Uint8(), 0x0)
dataBs = append(dataBs, []byte(code)...)
dataBs = append(dataBs, Bytes(start)...)
dataBs = append(dataBs, Bytes(count)...)
return &Frame{
Control: Control01,
Type: TypeStockHistoryMinuteTrade,
Data: dataBs,
}, nil
}
func (stockHistoryMinuteTrade) Decode(bs []byte, code string) (*StockHistoryMinuteTradeResp, error) {
if len(bs) < 2 {
return nil, errors.New("数据长度不足")
}
resp := &StockHistoryMinuteTradeResp{
Count: Uint16(bs[:2]),
}
//第2-6字节不知道是啥
bs = bs[2+4:]
lastPrice := Price(0)
for i := uint16(0); i < resp.Count; i++ {
mt := &StockMinuteTrade{
Time: GetHourMinute([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.Status = CutInt(bs)
bs, _ = CutInt(bs) //这个得到的是0不知道是啥
resp.List = append(resp.List, mt)
}
return resp, nil
}

View File

@@ -1,107 +0,0 @@
package protocol
import (
"errors"
"fmt"
)
type StockMinuteTradeResp struct {
Count uint16
List []*StockMinuteTrade
}
// StockMinuteTrade 分时成交todo 时间没有到秒,客户端上也没有,东方客户端能显示秒
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%-6s \t%-6d(手) \t%-4d(单) \t%-4s", this.Time, this.Price, this.Amount(), this.Volume, this.Number, this.StatusString())
}
// Amount 成交额
func (this *StockMinuteTrade) Amount() Price {
return this.Price * Price(this.Volume) * 100
}
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: GetHourMinute([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

@@ -81,7 +81,7 @@ func GetHourMinute(bs [2]byte) string {
return fmt.Sprintf("%02d:%02d", h, m)
}
func GetTime(bs [4]byte, Type TypeKline) time.Time {
func GetTime(bs [4]byte, Type uint8) time.Time {
switch Type {
case TypeKlineDay2, TypeKlineMinute, TypeKlineMinute2: