我之前发过一片关于通过爬虫技术从网易金融上获取股票数据的文章,大家反响还是挺强烈的。但是吧,那个作品只能说是我早期学习爬虫和量化的一个缩影。我现在要和大家分享的是非常Dry的干货。基本上可以说是我个人的最终版的股票数据下载文本,甚至可以说是Tushare下载数据的一个基石。
在国内做量化基本上都或多或少知道Tushare这个库的,大佬们基本上都是用Tushare来分享自己的作品。作为一个相对价格友好的金融数据库是非常良心的,价格相比于Wind,力度还是非常大的。
我们来看看Tushare在pypi上给自己的功能介绍是什么:
Tushare的目标人群:
行了咱们也扯得差不多了,开始整正事儿吧。
首先我的声明一下:
代码如下(示例):
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)
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点?一般来讲收盘后一个小时会更新当日的数据库,你才能拿到当天的数据。
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()
通过这样的手法来过滤我们的候选股票,首先就可以缩小我们的工作量,缩小范围。
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也想加进来的话请自行加载。
我上面举例有两个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))
综上所述,我们目前就有了一个我们初选的股票代码池了。
下一篇我来讲讲如何封装构建下载的部分内容。
请大家帮我点个赞收藏吧!
有问题的朋友可以留言或者私信加魏鑫都行。