go语言http调用Tushare财经数据包
Tushare平台介绍
- Tushare平台网址 https://tushare.pro/document/1,网址上就有下载安装以及数据获取的方式。Tushare Pro提供了包括股票、指数、基金、期货、数字货币在内的各类资产交易行情的分钟数据。
- 免费获取,数据准确,适合量化投资分析师(Quant),对金融市场进行大数据分析的企业和个人,开发以证券为基础的金融类产品和解决方案的公司,正在学习利用python进行数据分析的人使用。
- 有以下几种获取方式,今天介绍的是通过http来获取数据。
4. 为了避免部分用户低门槛无限制的恶意调取数据,更好地保证大多数用户调取数据的稳定性,同时也为了Tushare社区的可持续发展,Pro接口开始引入积分制度。只有具备一定积分级别的用户才能调取相应的API,目前只是一个分级门槛,并不消耗积分。以下只是基础积分权限,积分越多频次越高,除分钟数据外5000以上正常调取数据无频次限制。https://waditu.com/document/1?doc_id=108
使用go + http方式调用Tushare数据
// 具体http网站查看https://tushare.pro/document/1?doc_id=130
const endpoint string = "http://api.waditu.com"
const timeLayout string = "20060102"
type KLine struct {
TsCode string `json:"ts_code" structs:"1"`
TradeDate int64 `json:"trade_date" structs:"2"`
Close float64 `json:"close" structs:"3"`
Open float64 `json:"open" structs:"4"`
High float64 `json:"high" structs:"5"`
Low float64 `json:"low" structs:"6"`
PreClose float64 `json:"pre_close" structs:"7"`
LowLimit float64 `json:"low_limit" structs:"8"`
HighLimit float64 `json:"high_limit" structs:"9"`
Volume float64 `json:"volume" structs:"10"`
Amount float64 `json:"amount" structs:"11"`
Factor float64 `json:"factor" structs:"12"`
}
type Response struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data ResponseData `json:"data"`
}
// ResponseData stands for the field "data" in the body.
type ResponseData struct {
Fields []string `json:"fields"`
Items [][]interface{} `json:"items"`
}
type Client struct {
// token is the token given by tushare
token string
}
// NewClient creates a new instance of Client
func NewClient(token string) *Client {
return &Client{token: token}
}
// makeBody makes a request body to tushare by apiName, fields and params.
func (c *Client) makeBody(apiName, fields string,
params map[string]interface{}) (io.Reader, error) {
m := map[string]interface{}{
"api_name": apiName,
"token": c.token,
"fields": fields,
}
if params == nil {
m["params"] = ""
} else {
m["params"] = params
}
b, err := json.Marshal(m)
if err != nil {
return nil, err
}
return bytes.NewBuffer(b), nil
}
// request makes a http request to tushare
func (c *Client) request(body io.Reader) (*Response, error) {
// do the request
resp, err := http.Post(endpoint, "application/json", body)
for err != nil {
resp, err = http.Post(endpoint, "application/json", body)
}
// read the data from the body
// if the data is abnormal, error will be returned
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var res Response
err = json.Unmarshal(b, &res)
if err != nil {
return nil, err
}
if res.Code != 0 {
return nil, errors.New(res.Msg)
}
return &res, nil
}
func parseUnix(tsDate string) int64 {
date, _ := time.Parse(timeLayout, tsDate)
return date.Unix() - 28800
}
// parseRecord parse a list of a record in tushare's response body to our
// entity
func (c *Client) parseRecord(schema []string, record []interface{},
e interface{}) {
switch v := e.(type) {
case *Top10Holder:
// ts_code,ann_date,end_date,holder_name,hold_amount,hold_ratio
for i := range record {
if record[i] == nil {
continue
}
switch schema[i] {
case "ts_code":
v.TsCode = record[i].(string)
case "ann_date":
v.AnnDate = parseUnix(record[i].(string))
case "end_date":
v.Year, _ = strconv.Atoi(record[i].(string)[0:4])
case "holder_name":
v.HolderName = record[i].(string)
case "hold_amount":
v.HoldAmount = record[i].(float64)
case "hold_ratio":
v.HoldRatio = record[i].(float64) / 100.0
}
}
case *KLine:
// ts_code,trade_date,open,high,low,close,pre_close,change,
// pct_chg,vol,amount
for i := range record {
if record[i] == nil {
continue
}
switch schema[i] {
case "ts_code":
v.TsCode = record[i].(string)
case "trade_date":
v.TradeDate = parseUnix(record[i].(string))
case "open":
v.Open = record[i].(float64)
case "high":
v.High = record[i].(float64)
case "low":
v.Low = record[i].(float64)
case "close":
v.Close = record[i].(float64)
case "pre_close":
v.PreClose = record[i].(float64)
v.LowLimit = v.PreClose * 0.9
v.HighLimit = v.PreClose * 1.1
case "vol":
v.Volume = record[i].(float64)
case "amount":
v.Amount = record[i].(float64) * 1000
}
v.Factor = 1.0
}
}
}
// FetchKLineByTsCode fetches kline data of a single asset
func (c *Client) FetchKLineByTsCode(tsCode string, tradeDate,
startDate, endDate *time.Time, index bool) ([]KLine, error) {
fields := "ts_code,trade_date,open,high,low,close,pre_close,change," +
"pct_chg,vol,amount"
lines := make([]KLine, 0)
table := ""
if !index {
table = "daily"
} else {
table = "index_daily"
}
params := map[string]interface{}{
"ts_code": tsCode,
}
if tradeDate != nil {
params["trade_date"] = tradeDate.Format(timeLayout)
}
if startDate != nil {
params["start_date"] = startDate.Format(timeLayout)
}
if endDate != nil {
params["end_date"] = endDate.Format(timeLayout)
}
reqBody, err := c.makeBody(table, fields, params)
if err != nil {
return nil, err
}
resp, err := c.request(reqBody)
if err != nil {
return nil, err
}
for _, record := range resp.Data.Items {
line := KLine{}
c.parseRecord(resp.Data.Fields, record, &line)
lines = append(lines, line)
}
return lines, nil
}
上述代码即为构造一个结构体Kline,然后使用http post方式获取tushare数据,将数据转化为结构体形式。涉及到json数据格式转化,reqBody的构造。
重点在于获取tushare的token,token获取方式可参照https://waditu.com/document/1?doc_id=130。
以上就是go通过http方式来获取tushare数据的过程。
注意事项
http方式调用tushare是有次数限制的,免费数据源不可随意调取,按照平台给出的每分钟调用次数限制来使用。
不同数据类型的限制次数不同,下面给出一个大概的参考次数,
获取数据项 | 次数限制 |
---|---|
top10_holder | 200 |
Kline | 500 |
dividends | 200 |
suspensions | 200 |
具体限制次数请参照官网(可能会变化)。
切勿攻击,滥用tushare数据包。数据只供策略研究和学习使用,不允许作为商业目的。日渐增多的数据采集和处理需求、持续上升的用户请求,给服务器和带宽的扩容造成了很大压力。做遵纪守法的好公民,每个人心中都应该有一条线。