【手把手教你如何从Tushare库下载股票数据,并保存在硬盘当中】

手把手教你如何从Tushare库下载股票数据,并保存在硬盘当中。


前言

我之前发过一片关于通过爬虫技术从网易金融上获取股票数据的文章,大家反响还是挺强烈的。但是吧,那个作品只能说是我早期学习爬虫和量化的一个缩影。我现在要和大家分享的是非常Dry的干货。基本上可以说是我个人的最终版的股票数据下载文本,甚至可以说是Tushare下载数据的一个基石。


一、Tushare是什么?

在国内做量化基本上都或多或少知道Tushare这个库的,大佬们基本上都是用Tushare来分享自己的作品。作为一个相对价格友好的金融数据库是非常良心的,价格相比于Wind,力度还是非常大的。

我们来看看Tushare在pypi上给自己的功能介绍是什么:

  • easy to use as most of the data returned are pandas DataFrame objects
  • can be easily saved as csv, excel or json files
  • can be inserted into MySQL or Mongodb

Tushare的目标人群:

  • financial market analyst of China
  • learners of financial data analysis with pandas/NumPy
  • people who are interested in China financial data

行了咱们也扯得差不多了,开始整正事儿吧。

二、代码

首先我的声明一下:

  1. 我今天分享的代码不能用Jupyter来运行,但是可以用Jupyter来调试Debug,希望大家理解。
  2. 用了代码记得帮兄弟我宣传推广一下哈,嘿嘿。
  3. Tushare是需要花钱的,我用的是500元年费的,据说200元年费就可以有很丰富的功能了。说句实话如果你真的很想往量化方面发展研究的话,我觉得入手200元的还是个挺不错的选择。具体200元能干什么请自己去浏览哈。200元档位是2000积分,我大致观察了一下,基本上覆盖所有功能了。

1.引入库

代码如下(示例):

import os
import time
from datetime import datetime as dt
from datetime import timedelta
import threading
import pandas as pd
import numpy as np
import requests
import tushare as ts
token = '这个地方放你的Tushare秘钥'
ts.set_token(token)
pro = ts.pro_api(token)

2.交易日的逻辑

as_of_today = str(dt.now().strftime('%Y%m%d'))
def last_trading_day():
    data = pro.query('trade_cal',
                     start_date='20200101',
                     end_date=as_of_today,
                     is_open='1')
    trading_dates = data['cal_date']
    d0 = dt.now()
    trading_dates_list = trading_dates.tolist()

    if as_of_today in trading_dates.values:
        if d0.hour >= 16:
            today_index = trading_dates_list.index(as_of_today)
            latest_trading_date = trading_dates_list[int(today_index)]
            return latest_trading_date
        else:
            previous_trading_date = trading_dates.values[-2]
            return previous_trading_date
    else:
        previous_trading_date = trading_dates.values[-1]
        return previous_trading_date

这段代码最早的出处是在这里看到的。后来我自己又加工了一下。具体的意思就是:“如果今天在交易日历列表中,且现在时间是16点后,那就给我今天的日期;如果没到16点,给我昨天的日期;如果今天不在交易日历列表中,返回列表里最后一个日期”。为什么是16点?一般来讲收盘后一个小时会更新当日的数据库,你才能拿到当天的数据。

3.先把每天个股的基础数据调出来

data = pro.daily_basic(trade_date=last_trading_day())

返回的数据如下:

名称				类型		描述
ts_code			str		TS股票代码
trade_date		str		交易日期
close			float	当日收盘价
turnover_rate	float	换手率(%)
turnover_rate_f	float	换手率(*流通股)
volume_ratio	float	量比
pe				float	市盈率(总市值/净利润, 亏损的PE为空)
pe_ttm			float	市盈率(TTM,亏损的PE为空)
pb				float	市净率(总市值/净资产)
ps				float	市销率
ps_ttm			float	市销率(TTM)
dv_ratio		float	股息率 (%)
dv_ttm			float	股息率(TTM)(%)
total_share		float	总股本 (万股)
float_share		float	流通股本 (万股)
free_share		float	*流通股本 (万)
total_mv		float	总市值 (万元)
circ_mv			float	流通市值(万元)

我相信大家也不太可能想每天都去下载更新4000多支股票的所有的数据是吧?我们有了这些相对基础的基本面的信息后,就可以稍微加工筛选一下我们更理想的候选股票。

x1 = data.close < 200  # 收盘价小于200元
x2 = data.pe < 100  # 市盈率低于100倍
x3 = data.pb < 10  # 市净率低于10倍
x4 = data.turnover_rate > 1  # 换手率大于1
x = x1 & x2 & x3 & x4
stock_list_1 = data[x].ts_code.values.tolist()

通过这样的手法来过滤我们的候选股票,首先就可以缩小我们的工作量,缩小范围。

3.接下来我们来组织一下第二组股票池:

data2 = pro.query('stock_basic')

返回的数据如下:

名称			类型		默认显示	描述
ts_code		str		Y		TS代码
symbol		str		Y		股票代码
name		str		Y		股票名称
area		str		Y		地域
industry	str		Y		所属行业
fullname	str		N		股票全称
enname		str		N		英文全称
cnspell		str		N		拼音缩写
market		str		Y		市场类型(主板/创业板/科创板/CDR)
exchange	str		N		交易所代码
curr_type	str		N		交易货币
list_status	str		N		上市状态 L上市 D退市 P暂停上市
list_date	str		Y		上市日期
delist_date	str		N		退市日期
is_hs		str		N		是否沪深港通标的,N否 H沪股通 S深股通

我一般喜欢看上市至少一年的股票,我对次新股没有把握,所以不会去碰。那我如何筛选呢?

AS_of_Today = int(dt.now().strftime('%Y%m%d'))
data2 = data2[data2['list_date'].apply(int).values < (AS_of_Today-360)]

我对*ST也不是很来电,别特么哪天直接被退市了就BBQ了。

data2 = data2[-data2.name.str.startswith('*')]

我对某些行业也不是很了解或者不是我的菜:

data2 = data2[-data2.industry.isin(['银行','保险','房地产','区域地产',])

然后我们再打包一个list出来:

stock_list_2 = data2.ts_code.values.tolist()

如果你有自己的list也想加进来的话请自行加载。

4.合并List

我上面举例有两个Lists是吧?假设我们还有俩自己的私货Lists。那我们就把这4个Lists给合并成一个List,并去除同类项,防止反复下载,浪费资源。

stock_list = [value for value in stock_list_1 if value in stock_list_2] + stock_list_3 + stock_list_4
stock_list = list(dict.fromkeys(stock_list))

总结

综上所述,我们目前就有了一个我们初选的股票代码池了。
下一篇我来讲讲如何封装构建下载的部分内容。
请大家帮我点个赞收藏吧!
有问题的朋友可以留言或者私信加魏鑫都行。

上一篇:如何使用TOP Server for Wonderware通过OPC UA集成S7-1500


下一篇:js代码解析原则