在量化投资分析中,数据源始终是最基础部分。有一些研究者往往是从网络爬虫开始的。通过scrapy等python爬虫框架或者MATLAB进行数据爬取,这是非常不可取的,我们既然研究量化投资分析,应该首采用尽可能简单的方式获取到足够的历史数据。最好能够在几分钟内,上手所有自己需要的数据。Tushare实现的就是这样的任务,在没有网络爬虫基础和实战经验下,研究者能够通过它提供的API轻松获取到大量历史数据。
TuShare是一个免费、开源的python财经数据接口包。主要实现对股票等金融数据从数据采集、清洗加工 到 数据存储的过程,能够为金融分析人员提供快速、整洁、和多样的便于分析的数据,为他们在数据来源方面极大地减轻了工作 量,使他们更加专注于策略和模型的研究与实现上。tushare pro,数据更稳定质量更高,可获取沪深股票行情、财务、市场参考等数据,以及指数(含国外股指)、基金、期货、期权、宏观经济、行业经济等财经数据,为我们节省了大量宝贵时间。此外,近期还增加了新闻联播的文本数据,为文本分析和数据挖掘提供了很好的素材。新版本需要注册获取token才能免费使用。官方获取网址. 。
考虑到Python pandas包在金融量化分析中体现出的优势,TuShare返回的绝大部分的数据格式都是pandas DataFrame类型,非常便于用pandas/NumPy/Matplotlib进行数据分析和可视化。当然,如果您习惯了用Excel或者关系型数 据库做分析,您也可以通过TuShare的数据存储功能,将数据全部保存到本地后进行分析。应一些用户的请求,从0.2.5版本开始,TuShare同时 兼容Python 2.x和Python 3.x,对部分代码进行了重构,并优化了一些算法,确保数据获取的高效和稳定。
tushare包的安装方式,有很多种,都很简单。
方式1:pypi中直接获取
pip install tushare
若在国内下载tushare超时,可以通过临时修改为清华pip源的方式安装
pip install tushare -i https://pypi.tuna.tsinghua.edu.cn/simple
方式2 :源码安装
首先访问 https://pypi.python.org/pypi/tushare/ 下载源码 ,进入到项目的目录下执行
python setup.py install
方式3:GitHub 获取源码
访问https://github.com/waditu/tushare,将项目下载或者clone到本地,进入到项目的目录下,
执行python setup.py install
tushare版本升级方式:
pip install tushare --upgrade
查看tushare当前版本:import tushare print(tushare.__version__)
下面以股票行情数据为例,展示下tushare如何获取数据。股票行情数据以股票行情数据为例,简要介绍如何获取数据。
pro = ts.pro_api()
#查询当前所有正常上市交易的股票列表
data = pro.stock_basic(exchange='', list_status='L', fields='ts_code,symbol,name,area,industry,list_date')
tushare返回的data数据为pandas.DataFrame格式
ts_code symbol name area industry list_date
0 000001.SZ 000001 平安银行 深圳 银行 19910403
1 000002.SZ 000002 万科A 深圳 全国地产 19910129
2 000004.SZ 000004 国农科技 深圳 生物制药 19910114
3 000005.SZ 000005 世纪星源 深圳 房产服务 19901210
4 000006.SZ 000006 深振业A 深圳 区域地产 19920427
5 000007.SZ 000007 全新好 深圳 酒店餐饮 19920413
6 000008.SZ 000008 神州高铁 北京 运输设备 19920507
7 000009.SZ 000009 中国宝安 深圳 综合类 19910625
8 000010.SZ 000010 美丽生态 深圳 建筑施工 19951027
9 000011.SZ 000011 深物业A 深圳 区域地产 19920330
10 000012.SZ 000012 南玻A 深圳 玻璃 19920228
11 000014.SZ 000014 沙河股份 深圳 全国地产 19920602
12 000016.SZ 000016 深康佳A 深圳 家用电器 19920327
13 000017.SZ 000017 深中华A 深圳 文教休闲 19920331
14 000018.SZ 000018 神州长城 深圳 装修装饰 19920616
15 000019.SZ 000019 深深宝A 深圳 软饮料 19921012
16 000020.SZ 000020 深华发A 深圳 元器件 19920428
17 000021.SZ 000021 深科技 深圳 电脑设备 19940202
18 000022.SZ 000022 深赤湾A 深圳 港口 19930505
19 000023.SZ 000023 深天地A 深圳 其他建材 19930429
20 000025.SZ 000025 特力A 深圳 汽车服务 19930621
pro = ts.pro_api()
df = pro.trade_cal(exchange='', start_date='20180101', end_date='20181231')
返回的数据
exchange cal_date is_open
0 SSE 20180101 0
1 SSE 20180102 1
2 SSE 20180103 1
3 SSE 20180104 1
4 SSE 20180105 1
5 SSE 20180106 0
6 SSE 20180107 0
7 SSE 20180108 1
8 SSE 20180109 1
9 SSE 20180110 1
10 SSE 20180111 1
11 SSE 20180112 1
12 SSE 20180113 0
13 SSE 20180114 0
14 SSE 20180115 1
15 SSE 20180116 1
16 SSE 20180117 1
17 SSE 20180118 1
18 SSE 20180119 1
19 SSE 20180120 0
20 SSE 20180121 0
pro = ts.pro_api()
df = pro.query('daily', ts_code='000001.SZ', start_date='20180701', end_date='20180718')
打印获取的数据:
ts_code trade_date open high low close pre_close change pct_chg vol amount
0 000001.SZ 20180718 8.75 8.85 8.69 8.70 8.72 -0.02 -0.23 525152.77 460697.377
1 000001.SZ 20180717 8.74 8.75 8.66 8.72 8.73 -0.01 -0.11 375356.33 326396.994
2 000001.SZ 20180716 8.85 8.90 8.69 8.73 8.88 -0.15 -1.69 689845.58 603427.713
3 000001.SZ 20180713 8.92 8.94 8.82 8.88 8.88 0.00 0.00 603378.21 535401.175
4 000001.SZ 20180712 8.60 8.97 8.58 8.88 8.64 0.24 2.78 1140492.31 1008658.828
5 000001.SZ 20180711 8.76 8.83 8.68 8.78 8.98 -0.20 -2.23 851296.70 744765.824
6 000001.SZ 20180710 9.02 9.02 8.89 8.98 9.03 -0.05 -0.55 896862.02 803038.965
7 000001.SZ 20180709 8.69 9.03 8.68 9.03 8.66 0.37 4.27 1409954.60 1255007.609
8 000001.SZ 20180706 8.61 8.78 8.45 8.66 8.60 0.06 0.70 988282.69 852071.526
9 000001.SZ 20180705 8.62 8.73 8.55 8.60 8.61 -0.01 -0.12 835768.77 722169.579
这里只是简单地列举了一些常用的数据获取API,更多API可以参考官方网址获取
再封装的目的是通过封装,循环获取所有股票的所有历史数据,这里演示的Demo可以直接拷贝使用
import tushare as ts
import scipy.io as sio
import datetime
import numpy as np
import pandas as pd
import time
from tqdm import tqdm
import os
# print(ts.__version__)
"""注意:
1.函数在获取文件的时候会出现网络等错误,导致鲁棒性不好。需要修改,如果获取不成功就多读几次
2.每次更新数据都要把旧的数据读进内存,然后append到新数据中,再写入文件.这样会消耗更长时间来操作文件
ts_code str 股票代码
trade_date str 交易日期
open float 开盘价
high float 最高价
low float 最低价
close float 收盘价
pre_close float 昨收价
change float 涨跌额
pct_chg float 涨跌幅 (未复权,如果是复权请用 通用行情接口 )
vol float 成交量 (手)
amount float 成交额 (千元)
"""
def updateAllStockHistoryData(pro):
stock_list = pd.read_excel("./data/stock_list_from_tushare.xlsx")
pbar = tqdm(total=stock_list.shape[0])
i = 0
for index, sl in stock_list.iterrows():
# 如果这个文件不存在,就直接从网上获取所有数据,然后写入
if not os.path.exists("./data/stock_data_"+str(sl.ts_code)+".xlsx"):
stock_daily_data = pro.daily(ts_code = sl.ts_code, start_date = sl.list_date,
end_date = datetime.datetime.now().strftime('%Y%m%d'))
stock_weekly_data = pro.weekly(ts_code=sl.ts_code, start_date=sl.list_date,
end_date=datetime.datetime.now().strftime('%Y%m%d'),
fields='ts_code,trade_date,close,open,high,low,pre_close,change,pct_chg,vol,amount')
stock_monthly_data = pro.monthly(ts_code=sl.ts_code, start_date=sl.list_date,
end_date=datetime.datetime.now().strftime('%Y%m%d'),
fields='ts_code,trade_date,close,open,high,low,pre_close,change,pct_chg,vol,amount')
with pd.ExcelWriter("./data/stock_data_"+str(sl.ts_code)+".xlsx",engine="openpyxl") as writer:
stock_daily_data.to_excel(writer, sheet_name = 'daily')
stock_weekly_data.to_excel(writer, sheet_name = 'weekly')
stock_monthly_data.to_excel(writer, sheet_name = 'monthly')
print("stock: " + str(sl.ts_code) +" file is downloaded from tushare")
else:
# 如果存在这个文件就读取出来看首行日期,然后根据首行日期-当前日期进行获取数据,append进去
try:
stock_daily_data_old = pd.read_excel("./data/stock_data_"+str(sl.ts_code)+".xlsx", sheet_name='daily')
stock_weekly_data_old = pd.read_excel("./data/stock_data_"+str(sl.ts_code)+".xlsx", sheet_name='weekly')
stock_monthly_data_old = pd.read_excel("./data/stock_data_"+str(sl.ts_code)+".xlsx", sheet_name='monthly')
last_date = str(stock_daily_data_old.trade_date[0])
delta_one_day = datetime.timedelta(days=1)
last_date = datetime.datetime.strptime(last_date,"%Y%m%d")+delta_one_day
last_date = last_date.strftime('%Y%m%d')
stock_daily_data = pro.daily(ts_code = sl.ts_code, start_date = last_date,
end_date = datetime.datetime.now().strftime('%Y%m%d'))
stock_daily_data = stock_daily_data.append(stock_daily_data_old)
stock_weekly_data = pro.weekly(ts_code=sl.ts_code, start_date=last_date,
end_date=datetime.datetime.now().strftime('%Y%m%d'),
fields='ts_code,trade_date,close,open,high,low,pre_close,change,pct_chg,vol,amount')
stock_weekly_data = stock_weekly_data.append(stock_weekly_data_old)
stock_monthly_data = pro.monthly(ts_code=sl.ts_code, start_date=last_date,
end_date=datetime.datetime.now().strftime('%Y%m%d'),
fields='ts_code,trade_date,close,open,high,low,pre_close,change,pct_chg,vol,amount')
stock_monthly_data = stock_monthly_data.append(stock_monthly_data_old)
# stock_monthly_data = pro.
# stock_year_data =
with pd.ExcelWriter("./data/stock_data_"+str(sl.ts_code)+".xlsx", engine="openpyxl") as writer:
stock_daily_data.to_excel(writer, sheet_name = 'daily')
stock_weekly_data.to_excel(writer, sheet_name = 'weekly')
stock_monthly_data.to_excel(writer, sheet_name = 'monthly')
time.sleep(0.02)
print("stock: " + str(sl.ts_code) +" file is updated from tushare")
finally:
pass
pbar.update(i)
i = i + 1
pbar.close
return 0
# 更新大盘指数日指标
'''
ts_code str Y TS代码
trade_date str Y 交易日期
total_mv float Y 当日总市值(元)
float_mv float Y 当日流通市值(元)
total_share float Y 当日总股本(股)
float_share float Y 当日流通股本(股)
free_share float Y 当日自由流通股本(股)
turnover_rate float Y 换手率
turnover_rate_f float Y 换手率(基于自由流通股本)
pe float Y 市盈率
pe_ttm float Y 市盈率TTM
pb float Y 市净率
'''
def updateMarketIndexHistoryDataFromTushare(pro):
writer = pd.ExcelWriter("./data/market_index_history_data" + ".xlsx", engine="openpyxl")
ts_codes = ['000001.SH', '000300.SH', '000905.SH', '399001.SZ', '399005.SZ', '399006.SZ', '399016.SZ', '399300.SZ']
fields = 'ts_code, trade_date, total_mv, float_mv, total_share, float_share, free_share, turnover_rate, turnover_rate_f, pe, pe_ttm, pb'
if not os.path.exists("./data/market_index_history_data" + ".xlsx"):
for ts_code in ts_codes:
Market_Index = pro.index_dailybasic(ts_code = ts_code, start_date='20040101', end_date = datetime.datetime.now().strftime('%Y%m%d'), fields=fields)
Market_Index.to_excel(writer, sheet_name=ts_code)
writer.save()
print("File: market_index_history_data is downloaded.")
else:
for ts_code in ts_codes:
Market_Index_old = pd.read_excel("./data/market_index_history_data" + ".xlsx", sheet_name=ts_code)
last_date = str(Market_Index_old.trade_date[0])
delta_one_day = datetime.timedelta(days=1)
last_date = datetime.datetime.strptime(last_date, "%Y%m%d") + delta_one_day
last_date = last_date.strftime('%Y%m%d')
Market_Index_new = pro.index_dailybasic(ts_code = ts_code, start_date=last_date, end_date = datetime.datetime.now().strftime('%Y%m%d'), fields=fields)
Market_Index_new = Market_Index_new.append(Market_Index_old)
Market_Index_new.to_excel(writer, sheet_name=ts_code)
writer.save()
print("File: market_index_history_data is updated.")
return 0
# 获取上市公司列表
def updateStockList(pro):
# Query the stock list(正常上市公司列表)
stock_list = pro.stock_basic(exchange='', list_status='L', fields='ts_code,symbol,name,area,industry,fullname,enname,market, exchange,curr_type,list_status,list_date,list_date')
stock_list.to_excel("./data/stock_list_from_tushare.xlsx")
return 0
# 获取历史交易日历
def updateTradeCalenda(pro):
#
# Query the trade calendar(获取历史交易日历)
trade_calendar = pro.trade_cal(exchange='', start_date='20180101', end_date=datetime.datetime.now().strftime('%Y%m%d'))
trade_calendar.to_excel("./data/trade_calendar_from_tushare.xlsx")
return 0
if __name__ == '__main__':
# Initialize the pro interface
pro = ts.pro_api('your_token')
print("Trying to download data form tushare...")
# 获取当前上市公司列表
updateStockList(pro)
# 获取历史交易日历
updateTradeCalenda(pro)
# 更新所有股票日,周,月K历史数据
# updateAllStockHistoryData(pro)
# 更新大盘指数历史数据
updateMarketIndexHistoryDataFromTushare(pro)
简单介绍一下文件中的子函数:
- 通过调用
updateAllStockHistoryData()
更新所有上市公司从上市以来,到最近一天期间所有日K,周K和月K历史数据,保存到文件同级目录data/
文件夹下- 通过调用
updateMarketIndexHistoryDataFromTushare()
函数,获取大盘指数数据,包括['000001.SH', '000300.SH', '000905.SH', '399001.SZ', '399005.SZ', '399006.SZ', '399016.SZ', '399300.SZ']
全部运行结束后,我们就可以得到所有股票的全部历史数据,一共825M左右
通过已有的数据源,我们可以简单的获取到大量数据(825M),而不需要从头学习网络爬虫。节省了大量时间。为了让大家更好的利用tushare工具,获取更多关于tushare数据获取的内容,我会在这片博客中不断填充。大家如果有好的封装,可以在底下评论。我会测试,整理并及时发布到该博客中。