mirror of
https://github.com/injoyai/tdx.git
synced 2025-11-26 21:25:35 +08:00
增加同花顺的复权日线数据接口,拉取测试通过(无成交金额数据),后续应该会转移位置
This commit is contained in:
156
extend/spider_ths.go
Normal file
156
extend/spider_ths.go
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
package extend
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"github.com/injoyai/conv"
|
||||||
|
"github.com/injoyai/tdx"
|
||||||
|
"github.com/injoyai/tdx/protocol"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
UrlTHSDayKline = "http://d.10jqka.com.cn/v6/line/hs_%s/0%d/all.js"
|
||||||
|
THS_QFQ uint8 = 1 //前复权
|
||||||
|
THS_HFQ uint8 = 2 //后复权
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewTHSDayKline() *THSDayKline {
|
||||||
|
return &THSDayKline{
|
||||||
|
Client: http.DefaultClient,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
THSDayKline
|
||||||
|
前复权,和通达信对的上,和东方财富对不上
|
||||||
|
后复权,和通达信,东方财富都对不上
|
||||||
|
*/
|
||||||
|
type THSDayKline struct {
|
||||||
|
Codes []string
|
||||||
|
Client *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *THSDayKline) GetName() string {
|
||||||
|
return "同花顺日线"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *THSDayKline) Run(ctx context.Context, m *tdx.Manage) error {
|
||||||
|
codes := this.Codes
|
||||||
|
if len(codes) == 0 {
|
||||||
|
codes = m.Codes.GetStocks()
|
||||||
|
}
|
||||||
|
for _, _type := range []uint8{THS_QFQ, THS_HFQ} {
|
||||||
|
for _, code := range codes {
|
||||||
|
ls, err := this.Pull(ctx, code, _type)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = ls
|
||||||
|
//加入数据库
|
||||||
|
|
||||||
|
<-time.After(time.Millisecond * 300)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *THSDayKline) Pull(ctx context.Context, code string, _type uint8) ([]*Kline, error) {
|
||||||
|
if _type != THS_QFQ && _type != THS_HFQ {
|
||||||
|
return nil, fmt.Errorf("数据类型错误,例如:前复权1或后复权2")
|
||||||
|
}
|
||||||
|
|
||||||
|
code = protocol.AddPrefix(code)
|
||||||
|
if len(code) != 8 {
|
||||||
|
return nil, fmt.Errorf("股票代码错误,例如:SZ000001或000001")
|
||||||
|
}
|
||||||
|
|
||||||
|
u := fmt.Sprintf(UrlTHSDayKline, code[2:], _type)
|
||||||
|
req, err := http.NewRequest(http.MethodGet, u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
|
||||||
|
'Chrome/90.0.4430.212 Safari/537.36',
|
||||||
|
'Referer': 'http://stockpage.10jqka.com.cn/',
|
||||||
|
'DNT': '1',
|
||||||
|
*/
|
||||||
|
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 Edg/89.0.774.54")
|
||||||
|
req.Header.Set("Referer", "http://stockpage.10jqka.com.cn/")
|
||||||
|
req.Header.Set("DNT", "1")
|
||||||
|
resp, err := this.Client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
bs, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
n := bytes.IndexByte(bs, '(')
|
||||||
|
bs = bs[n+1 : len(bs)-1]
|
||||||
|
|
||||||
|
m := map[string]any{}
|
||||||
|
err = json.Unmarshal(bs, &m)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
total := conv.Int(m["total"])
|
||||||
|
priceFactor := conv.Float64(m["priceFactor"])
|
||||||
|
prices := strings.Split(conv.String(m["price"]), ",")
|
||||||
|
dates := strings.Split(conv.String(m["dates"]), ",")
|
||||||
|
volumes := strings.Split(conv.String(m["volumn"]), ",")
|
||||||
|
start := conv.String(m["start"])
|
||||||
|
t, err := time.Parse("20060102", start)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//好像到了22点,总数量会比实际多1
|
||||||
|
if total == len(dates)+1 && total == len(volumes)+1 {
|
||||||
|
total -= 1
|
||||||
|
}
|
||||||
|
//判断数量是否对应
|
||||||
|
if total*4 != len(prices) || total != len(dates) || total != len(volumes) {
|
||||||
|
return nil, fmt.Errorf("total=%d prices=%d dates=%d volumns=%d", total, len(prices), len(dates), len(volumes))
|
||||||
|
}
|
||||||
|
|
||||||
|
ls := []*Kline(nil)
|
||||||
|
|
||||||
|
year := t.Year()
|
||||||
|
lastDate := ""
|
||||||
|
for i := 0; i < total; i++ {
|
||||||
|
//当日前变小时(12xx变01xx),说明过了1年,除非该股票停牌了1年多则数据错误
|
||||||
|
if dates[i] < lastDate {
|
||||||
|
year++
|
||||||
|
}
|
||||||
|
lastDate = dates[i]
|
||||||
|
x, err := time.Parse("0102", dates[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
x = time.Date(year, x.Month(), x.Day(), 15, 0, 0, 0, time.Local)
|
||||||
|
low := protocol.Price(conv.Float64(prices[i*4+0]) * 1000 / priceFactor)
|
||||||
|
ls = append(ls, &Kline{
|
||||||
|
Code: protocol.AddPrefix(code),
|
||||||
|
Date: x.Unix(),
|
||||||
|
Open: protocol.Price(conv.Float64(prices[i*4+1])*1000/priceFactor) + low,
|
||||||
|
High: protocol.Price(conv.Float64(prices[i*4+2])*1000/priceFactor) + low,
|
||||||
|
Low: low,
|
||||||
|
Close: protocol.Price(conv.Float64(prices[i*4+3])*1000/priceFactor) + low,
|
||||||
|
Volume: (conv.Int64(volumes[i]) + 50) / 100,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return ls, nil
|
||||||
|
}
|
||||||
18
extend/spider_ths_test.go
Normal file
18
extend/spider_ths_test.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package extend
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewSpiderTHS(t *testing.T) {
|
||||||
|
x := NewTHSDayKline()
|
||||||
|
ls, err := x.Pull(context.Background(), "sz000001", THS_HFQ)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, v := range ls {
|
||||||
|
t.Log(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user