mirror of
https://github.com/injoyai/tdx.git
synced 2025-11-26 21:25:35 +08:00
日线数据对上了,其它k线待校对
This commit is contained in:
15
README.md
15
README.md
@@ -11,3 +11,18 @@
|
|||||||

|

|
||||||
* K线
|
* K线
|
||||||

|

|
||||||
|
|
||||||
|
### 其它信息
|
||||||
|
|
||||||
|
* 中国的股市开盘时间为:每周一至周五的上午9:30——11:30, 下午13:00——15:00。中国股市收盘时间为:每周一至周五的下午3点。
|
||||||
|
|
||||||
|
* 600开头的股票是上证A股,属于大盘股,其中6006开头的股票是最早上市的股票, 6016开头的股票为大盘蓝筹股;900开头的股票是上证B股; 000开头的股票是深证A股,001、002开头的股票也都属于深证A股, 其中002开头的股票是深证A股中小企业股票;200开头的股票是深证B股; 300开头的股票是创业板股票;400开头的股票是三板市场股票。
|
||||||
|
|
||||||
|
|
||||||
|
### 数据接口
|
||||||
|
|
||||||
|
* 实时行情数据 http://vip.stock.finance.sina.com.cn/mkt/#hs_a
|
||||||
|
描述: A 股数据是从新浪财经获取的数据, 重复运行本函数会被新浪暂时封 IP, 建议增加时间间隔 限量: 单次返回所有 A 股上市公司的实时行情数据
|
||||||
|
|
||||||
|
* 历史行情数据 https://finance.sina.com.cn/realstock/company/sh600006/nc.shtml
|
||||||
|
描述: A 股数据是从新浪财经获取的数据, 历史数据按日频率更新; 注意其中的 sh689009 为 CDR, 请 通过 stock_zh_a_cdr_daily 接口获取 限量: 单次返回指定 A 股上市公司指定日期间的历史行情日频率数据
|
||||||
37
client.go
37
client.go
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/injoyai/ios/client/dial"
|
"github.com/injoyai/ios/client/dial"
|
||||||
"github.com/injoyai/logs"
|
"github.com/injoyai/logs"
|
||||||
"github.com/injoyai/tdx/protocol"
|
"github.com/injoyai/tdx/protocol"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -128,21 +129,15 @@ func (this *Client) handlerDealMessage(c *client.Client, msg ios.Acker) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendFrame 发送数据,并等待响应
|
||||||
func (this *Client) SendFrame(f *protocol.Frame) (any, error) {
|
func (this *Client) SendFrame(f *protocol.Frame) (any, error) {
|
||||||
this.msgID++
|
f.MsgID = atomic.AddUint32(&this.msgID, 1)
|
||||||
f.MsgID = this.msgID
|
|
||||||
if _, err := this.Client.Write(f.Bytes()); err != nil {
|
if _, err := this.Client.Write(f.Bytes()); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return this.Wait.Wait(conv.String(this.msgID))
|
return this.Wait.Wait(conv.String(this.msgID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Client) connect() error {
|
|
||||||
f := protocol.MConnect.Frame()
|
|
||||||
_, err := this.Write(f.Bytes())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStockCount 获取市场内的股票数量
|
// GetStockCount 获取市场内的股票数量
|
||||||
func (this *Client) GetStockCount(exchange protocol.Exchange) (*protocol.StockCountResp, error) {
|
func (this *Client) GetStockCount(exchange protocol.Exchange) (*protocol.StockCountResp, error) {
|
||||||
f := protocol.MStockCount.Frame(exchange)
|
f := protocol.MStockCount.Frame(exchange)
|
||||||
@@ -155,6 +150,9 @@ func (this *Client) GetStockCount(exchange protocol.Exchange) (*protocol.StockCo
|
|||||||
|
|
||||||
// GetStockList 获取市场内指定范围内的所有证券代码,一次固定返回1000只,上证股票有效范围370-1480
|
// GetStockList 获取市场内指定范围内的所有证券代码,一次固定返回1000只,上证股票有效范围370-1480
|
||||||
// 上证前370只是395/399开头的(中证500/总交易等辅助类),在后面的话是一些100开头的国债
|
// 上证前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) {
|
func (this *Client) GetStockList(exchange protocol.Exchange, start uint16) (*protocol.StockListResp, error) {
|
||||||
f := protocol.MStockList.Frame(exchange, start)
|
f := protocol.MStockList.Frame(exchange, start)
|
||||||
result, err := this.SendFrame(f)
|
result, err := this.SendFrame(f)
|
||||||
@@ -164,6 +162,24 @@ func (this *Client) GetStockList(exchange protocol.Exchange, start uint16) (*pro
|
|||||||
return result.(*protocol.StockListResp), nil
|
return result.(*protocol.StockListResp), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetStockAll 通过多次请求的方式获取全部证券代码
|
||||||
|
func (this *Client) GetStockAll(exchange protocol.Exchange) (*protocol.StockListResp, error) {
|
||||||
|
resp := &protocol.StockListResp{}
|
||||||
|
maxSize := uint16(1000)
|
||||||
|
for start := uint16(0); ; start += maxSize {
|
||||||
|
r, err := this.GetStockList(exchange, start)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp.Count += r.Count
|
||||||
|
resp.List = append(resp.List, r.List...)
|
||||||
|
if r.Count < maxSize {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetStockQuotes 获取盘口五档报价
|
// GetStockQuotes 获取盘口五档报价
|
||||||
func (this *Client) GetStockQuotes(m map[protocol.Exchange]string) (protocol.StockQuotesResp, error) {
|
func (this *Client) GetStockQuotes(m map[protocol.Exchange]string) (protocol.StockQuotesResp, error) {
|
||||||
f, err := protocol.MStockQuote.Frame(m)
|
f, err := protocol.MStockQuote.Frame(m)
|
||||||
@@ -286,6 +302,11 @@ func (this *Client) GetStockKline30Minute(req *protocol.StockKlineReq) (*protoco
|
|||||||
return this.GetStockKline(protocol.TypeKline30Minute, req)
|
return this.GetStockKline(protocol.TypeKline30Minute, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetStockKlineHour 获取小时k线数据
|
||||||
|
func (this *Client) GetStockKlineHour(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
|
||||||
|
return this.GetStockKline(protocol.TypeKlineHour, req)
|
||||||
|
}
|
||||||
|
|
||||||
// GetStockKlineDay 获取日k线数据
|
// GetStockKlineDay 获取日k线数据
|
||||||
func (this *Client) GetStockKlineDay(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
|
func (this *Client) GetStockKlineDay(req *protocol.StockKlineReq) (*protocol.StockKlineResp, error) {
|
||||||
return this.GetStockKline(protocol.TypeKlineDay, req)
|
return this.GetStockKline(protocol.TypeKlineDay, req)
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ type StockKline struct {
|
|||||||
Open Price //开盘价
|
Open Price //开盘价
|
||||||
High Price //最高价
|
High Price //最高价
|
||||||
Low Price //最低价
|
Low Price //最低价
|
||||||
Close Price //收盘价
|
Close Price //收盘价,如果是当天,则是最新价/实时价
|
||||||
Volume float64 //成交量
|
Volume float64 //成交量
|
||||||
Amount float64 //成交额
|
Amount float64 //成交额
|
||||||
Time time.Time //时间
|
Time time.Time //时间
|
||||||
@@ -100,9 +100,7 @@ func (stockKline) Decode(bs []byte, Type TypeKline) (*StockKlineResp, error) {
|
|||||||
|
|
||||||
last = last + open + _close
|
last = last + open + _close
|
||||||
|
|
||||||
//logs.Debug(Reverse(bs[:4]), getVolume(Uint32(bs[:4])))
|
k.Volume = getVolume(Uint32(bs[:4]))
|
||||||
//logs.Debug(Reverse(bs[4:8]), getVolume(Uint32(bs[4:8])))
|
|
||||||
k.Volume = getVolume(Uint32(bs[:4])) / 100
|
|
||||||
k.Amount = getVolume(Uint32(bs[4:8]))
|
k.Amount = getVolume(Uint32(bs[4:8]))
|
||||||
|
|
||||||
bs = bs[8:]
|
bs = bs[8:]
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
func Test_stockKline_Frame(t *testing.T) {
|
func Test_stockKline_Frame(t *testing.T) {
|
||||||
//预期0c02000000001c001c002d050000303030303031 0900 0100 0000 0a00 00000000000000000000
|
//预期0c02000000001c001c002d050000303030303031 0900 0100 0000 0a00 00000000000000000000
|
||||||
// 0c00000000011c001c002d050000313030303030 0900 0000 0000 0a00 00000000000000000000
|
// 0c00000000011c001c002d050000313030303030 0900 0000 0000 0a00 00000000000000000000
|
||||||
f, _ := MStockKline.Frame(TypeKlineDay2, &StockKlineReq{
|
f, _ := MStockKline.Frame(TypeKlineDay, &StockKlineReq{
|
||||||
Exchange: ExchangeSH,
|
Exchange: ExchangeSH,
|
||||||
Code: "000001",
|
Code: "000001",
|
||||||
Start: 0,
|
Start: 0,
|
||||||
|
|||||||
@@ -55,12 +55,12 @@ const (
|
|||||||
TypeKline15Minute TypeKline = 1 // 15分钟K 线
|
TypeKline15Minute TypeKline = 1 // 15分钟K 线
|
||||||
TypeKline30Minute TypeKline = 2 // 30分钟K 线
|
TypeKline30Minute TypeKline = 2 // 30分钟K 线
|
||||||
TypeKlineHour TypeKline = 3 // 1小时K 线
|
TypeKlineHour TypeKline = 3 // 1小时K 线
|
||||||
TypeKlineDay TypeKline = 4 // 日K 线
|
TypeKlineDay2 TypeKline = 4 // 日K 线
|
||||||
TypeKlineWeek TypeKline = 5 // 周K 线
|
TypeKlineWeek TypeKline = 5 // 周K 线
|
||||||
TypeKlineMonth TypeKline = 6 // 月K 线
|
TypeKlineMonth TypeKline = 6 // 月K 线
|
||||||
TypeKlineMinute TypeKline = 7 // 1分钟
|
TypeKlineMinute TypeKline = 7 // 1分钟
|
||||||
TypeKlineMinute2 TypeKline = 8 // 1分钟K 线
|
TypeKlineMinute2 TypeKline = 8 // 1分钟K 线
|
||||||
TypeKlineDay2 TypeKline = 9 // 日K 线
|
TypeKlineDay TypeKline = 9 // 日K 线
|
||||||
TypeKlineQuarter TypeKline = 10 // 季K 线
|
TypeKlineQuarter TypeKline = 10 // 季K 线
|
||||||
TypeKlineYear TypeKline = 11 // 年K 线
|
TypeKlineYear TypeKline = 11 // 年K 线
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package protocol
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Price 价格,单位分
|
// Price 价格,单位分
|
||||||
@@ -158,61 +157,3 @@ func getData(bs []byte) (data int) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVolume(ivol uint32) (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
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
package protocol
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_getVolume(t *testing.T) {
|
|
||||||
f := float32(1.03)
|
|
||||||
n := math.Float32bits(f)
|
|
||||||
t.Log(n)
|
|
||||||
|
|
||||||
t.Log(getVolume(n))
|
|
||||||
}
|
|
||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"golang.org/x/text/encoding/simplifiedchinese"
|
"golang.org/x/text/encoding/simplifiedchinese"
|
||||||
"golang.org/x/text/transform"
|
"golang.org/x/text/transform"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -82,7 +83,7 @@ func GetDate(bs [2]byte) string {
|
|||||||
|
|
||||||
func GetTime(bs [4]byte, Type TypeKline) time.Time {
|
func GetTime(bs [4]byte, Type TypeKline) time.Time {
|
||||||
switch Type {
|
switch Type {
|
||||||
case TypeKlineDay, TypeKlineMinute, TypeKlineMinute2:
|
case TypeKlineDay2, TypeKlineMinute, TypeKlineMinute2:
|
||||||
|
|
||||||
yearMonthDay := Uint16(bs[:2])
|
yearMonthDay := Uint16(bs[:2])
|
||||||
hourMinute := Uint16(bs[:2])
|
hourMinute := Uint16(bs[:2])
|
||||||
@@ -115,3 +116,62 @@ func basePrice(code string) Price {
|
|||||||
return 10
|
return 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getVolume(val uint32) (volume float64) {
|
||||||
|
ivol := int32(val)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,3 +17,8 @@ func TestUTF8ToGBK(t *testing.T) {
|
|||||||
bs = UTF8ToGBK(bs)
|
bs = UTF8ToGBK(bs)
|
||||||
t.Log(string(bs))
|
t.Log(string(bs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_getVolume(t *testing.T) {
|
||||||
|
t.Log(getVolume(1237966432))
|
||||||
|
t.Log(getVolume(1237966432))
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user