1. 程式人生 > 其它 >go語言http呼叫Tushare財經資料包

go語言http呼叫Tushare財經資料包

技術標籤:gotusharego資料分析

go語言http呼叫Tushare財經資料包

Tushare平臺介紹

  1. Tushare平臺網址 https://tushare.pro/document/1,網址上就有下載安裝以及資料獲取的方式。Tushare Pro提供了包括股票、指數、基金、期貨、數字貨幣在內的各類資產交易行情的分鐘資料。
  2. 免費獲取,資料準確,適合量化投資分析師(Quant),對金融市場進行大資料分析的企業和個人,開發以證券為基礎的金融類產品和解決方案的公司,正在學習利用python進行資料分析的人使用。
  3. 有以下幾種獲取方式,今天介紹的是通過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_holder200
Kline500
dividends200
suspensions200

具體限制次數請參照官網(可能會變化)。

切勿攻擊,濫用tushare資料包。資料只供策略研究和學習使用,不允許作為商業目的。日漸增多的資料採集和處理需求、持續上升的使用者請求,給伺服器和頻寬的擴容造成了很大壓力。做遵紀守法的好公民,每個人心中都應該有一條線。