1. Tushare简介
1.1. 开源、免费版Tushare
Tushare是一个免费、开源的python财经数据接口包。主要实现对股票等金融数据从数据采集、清洗加工 到 数据存储的过程,能够为金融分析人员提供快速、整洁、和多样的便于分析的数据,为他们在数据获取方面极大地减轻工作量,使他们更加专注于策略和模型的研究与实现上。考虑到Python pandas包在金融量化分析中体现出的优势,Tushare返回的绝大部分的数据格式都是pandas DataFrame类型,非常便于用pandas/NumPy/Matplotlib进行数据分析和可视化。当然,如果您习惯了用Excel或者关系型数据库做分析,您也可以通过Tushare的数据存储功能,将数据全部保存到本地后进行分析。
地址:http://tushare.org/
当然在学习Python的道路上肯定会困难,没有好的学习资料,怎么去学习呢?
学习Python中有不明白推荐加入交流Q群号:701698587
群里有志同道合的小伙伴,互帮互助, 群里有不错的视频学习教程和PDF!
1.2. 注册升级版 Tushare pro
Pro版数据更稳定质量更好了,但Pro依然是个开放的,免费的平台,不带任何商业性质和目的。
1.3. 获取Tushare
不管你是量化投资分析师,还是正在学习Python进行数据分析的学习者,这种方法获取的数据都可以适用。
获取前的准备:
2. 获取数据
我为了更方便的使用Tushare接口API,也为了兼容新、旧版本,设计类整合新版本。
2.1. 获取历史行情数据
本接口只能获取近3年的日线数据,适合搭配均线数据进行选股和分析。
输入参数说明:
|股票代码|开始日期|结束日期|数据类型|
| 老版本关键字 |
新版本关键字(pro) |
说明 |
| code |
ts_code |
股票代码 |
| |
trade_date |
交易日期 |
| start |
start_date |
开始日期,格式YYYY-MM-DD/新版本YYYYMMDD |
| end |
end_date |
结束日期,格式YYYY-MM-DD/新版本YYYYMMDD |
| ktype |
|
数据类型 |
| retry_count |
|
当网络异常后重试次数,默认为3 |
| pause |
|
重试时停顿秒数,默认为0 |
老版本中:
1.股票代码,即6位数字代码,或者指数代码(sh=上证指数 sz=深圳成指 hs300=沪深300指数 sz50=上证50 zxb=中小板 cyb=创业板)
2.数据类型,D=日k线 W=周 M=月 5=5分钟 15=15分钟 30=30分钟 60=60分钟,默认为D
返回值说明:
| 老版本关键字 |
新版本关键字(pro) |
说明 |
| |
ts_code |
股票代码 |
| date |
trade_date |
交易日期 |
| open |
open |
开盘价 |
| high |
high |
最高价 |
| close |
close |
收盘价 |
| |
pre_close |
昨收盘价 |
| low |
low |
最低价 |
| volume |
vol |
成交量 |
| price_change |
change |
价格变动、涨跌额 |
| p_change |
pct_chg |
涨跌幅 |
| ma5 |
|
5日均价 |
| ma10 |
|
10日均价 |
| ma20 |
|
20日均价 |
| v_ma5 |
|
5日均量 |
| v_ma10 |
|
10日均量 |
| v_ma20 |
|
20日均量 |
| turnover |
|
换手率[注:指数无此项] |
| |
amount |
成交额 |
老版本中date为index,不是具体column。
2.2. 获取历史行情数据——指数
上证指数、深圳成指、沪深300指数、上证50 、中小板、创业板等。
上证指数代码为“000001.SH”,老版本代码为“sh”;深成指数代码为“399001.SZ”,老版本为“399001”或“sz”。
2.3. 获取历史行情数据——情绪指数
目前pro版本国外已经支持如下指数数据(数据来源:https://tushare.pro/):
| TS指数代码 |
指数名称 |
| XIN9 |
富时中国A50指数 (富时A50) |
| HSI |
恒生指数 |
| DJI |
道琼斯工业指数 |
| SPX |
标普500指数 |
| IXIC |
纳斯达克指数 |
| FTSE |
富时100指数 |
| FCHI |
法国CAC40指数 |
| GDAXI |
德国DAX指数 |
| N225 |
日经225指数 |
| KS11 |
韩国综合指数 |
| AS51 |
澳大利亚标普200指数 |
| SENSEX |
印度孟买SENSEX指数 |
| IBOVESPA |
巴西IBOVESPA指数 |
| RTS |
俄罗斯RTS指数 |
| TWII |
台湾加权指数 |
| CKLSE |
马来西亚指数 |
| SPTSX |
加拿大S&P/TSX指数 |
| CSX5P |
STOXX欧洲50指数 |
使用方法:
2.4. 获取分时数据
升级pro版本,可以获取3年的数据,而老版本 只能获取1个月的分时数据。
#获取分钟级别数据
def get_tickshare_dat(self,freq,start_date, end_date):
if self.pro:
start_date=re.sub(\'\D\',\'\',start_date)
end_date = re.sub(\'\D\',\'\',end_date)
freq = freq + \'min\'
self.tickshare_dat = ts.pro_bar(ts_code=self.code, freq = freq,start_date=start_date, end_date=end_date)
self.tickshare_dat[\'vol\'] = self.tickshare_dat[\'vol\'] /100
else:
# ktype:数据类型,D=日k线 W=周 M=月 5=5分钟 15=15分钟 30=30分钟 60=60分钟,默认为D
self.tickshare_dat = ts.get_hist_data(code=self.code, ktype = freq,start=start_date, end=end_date)
self.tickshare_dat[\'ts_code\'] = self.code
self.tickshare_dat = self.tickshare_dat.reset_index()
self.tickshare_dat = self.tickshare_dat.rename(columns={
\'date\':\'trade_time\',\'volume\':\'vol\'})
self.tickshare_dat[\'trade_date\'] = self.tickshare_dat[\'trade_time\'].apply(lambda x:re.sub(\'\D\',\'\',x[0:10]))
self.setCodebyOld()
self.tickshare_dat[\'ts_code\'] = self.code
self.tickshare_dat = self.tickshare_dat[[\'ts_code\',\'trade_time\',\'open\',\'high\',\'close\',\'low\',\'vol\',\'trade_date\']]
return self.tickshare_dat
注:输入freq为字符型数字,1/5/15/30/60
2.5. 获取股票基本信息
#获取股票基本面信息
def get_ShareInfo(self,trade_date):
if self.pro:
self.shareInfo = self.stock.daily_basic(ts_code=self.code, trade_date=trade_date) #, fields=\'ts_code,trade_date,turnover_rate,volume_ratio,pe,pb\')
else:
self.shareInfo = ts.get_stock_basics()
print(self.shareInfo)
2.6. 获取复权数据
# 获取复权数据
def get_h_dat(self,start_date,end_date,fq=\'hfq\'):
#self.h_dat = ts.get_h_data(code=self.code, autype=\'hfq\',start=start_date, end=end_date)
self.h_dat = ts.pro_bar(ts_code=self.code, adj=fq, start_date=start_date, end_date=end_date)
return self.h_dat
3. 数据存储在本地Mongo数据库中
class Stock_Collection(object):
def __init__(self,db_name):
self.db_name = db_name
client = pymongo.MongoClient(\'mongodb://stock:stock@localhost:27017/stock\')
self.db = client[self.db_name]
def insertdatas(self,name,datas):
collection = self.db[name]
collection.insert(json.loads(datas.T.to_json()).values())
def getDistinctCode(self,name):
collection = self.db[name]
code = collection.distinct(\'ts_code\')
return code
def setIndex_Code(self):
self.sentiment_index = [\'IXIC\',\'DJI\',\'HSI\'] # 情绪指数
self.sentiment_index_column = [\'trade_date\',\'open\',\'high\',\'close\',\'low\',\'change\',\'pct_chg\']
self.index_daily = [\'000001.SH\', \'399001.SZ\']
self.index_daily_column = [\'trade_date\',\'open\',\'high\',\'close\',\'low\',\'vol\',\'change\',\'pct_chg\']
def setCode(self,code):
self.code = code #[\'002230.SZ\'] #, \'000547.SZ\', \'601318.SH\', \'601208.SH\', \'600030.SH\', \'000938.SZ\', \'002108.SZ\', \'600967.SH\']
self.stock_column = [\'trade_date\',\'open\',\'high\',\'close\',\'low\',\'vol\',\'change\',\'pct_chg\']
# 构造LSTM模型训练集
def generate_train_datas(self,db_name,code_name,filename):
collection = self.db[db_name]
self.out_code = code_name
#查询条件“字典”
query_dict = {
\'ts_code\':\'1\',\'trade_date\':{
\'$gt\':\'20171001\'}}
#col_name = {\'_id\':0,\'trade_date\':1,\'ts_code\':1,\'open\':1,\'high\':1,\'close\':1,\'low\':1,\'vol\':1,\'change\':1,\'pct_chg\':1}
col_name = {
\'_id\':0}
for d in self.stock_column:
col_name[d] = 1
query_dict[\'ts_code\'] = self.out_code
#注意时间排序
df = pd.DataFrame(list(collection.find(query_dict,col_name).sort([(\'trade_date\',1)])))
df[\'trade_date\'] = df[\'trade_date\'].apply(lambda x:re.sub(\'\D\',\'\',x)) #去掉日期中的“-”符号
self.code.remove(self.out_code) # 删除输出股票代码
#构造股票数据集
n = 0
k = 0
columns = self.stock_column.copy()
columns.remove(\'trade_date\')
print(\'Start!\')
#self.code长度为1,下面循环不执行
for code in self.code:
query_dict[\'ts_code\'] = code
df1 = pd.DataFrame(list(collection.find(query_dict,col_name).sort([(\'trade_date\',1)])))
df1[\'trade_date\'] = df1[\'trade_date\'].apply(lambda x:re.sub(\'\D\',\'\',x)) #去掉日期中的“-”符号
#按日期合并两个表
#df =pd.merge(left=df,right=df1,how=\'left\',on=[\'trade_date\'])
#以上证为基准
df =pd.merge(left=df,right=df1,how=\'inner\',on=[\'trade_date\'])
# 处理合并表,字段重复的情况,需要把_x,_y新命名字段,下轮继续
cols_dict = {
}
for cols in columns:
cols_dict[cols+\'_x\'] = cols + str(n)
cols_dict[cols+\'_y\'] = cols + str(n+1)
if k==0:
df = df.rename(columns=cols_dict)
n = n + 2
k = 1
else:
k = 0
print(\'code 1\')
print(df)
#构造数据集——上证、深成指数
query_dict = {
\'ts_code\':\'1\'}
columns = self.index_daily_column.copy() #默认list为传址,需要赋值新list
columns.remove(\'trade_date\')
print(self.index_daily_column)
for index_daily in self.index_daily:
query_dict[\'ts_code\'] = index_daily
col_name = {
\'_id\':0}
for d in self.index_daily_column:
col_name[d] = 1
df1 = pd.DataFrame(list(collection.find(query_dict,col_name).sort([(\'trade_date\',1)])))
df1[\'trade_date\'] = df1[\'trade_date\'].apply(lambda x:re.sub(\'\D\',\'\',x)) #去掉日期中的“-”符号
#按日期合并两个表
df =pd.merge(left=df,right=df1,how=\'left\',on=[\'trade_date\'])
cols_dict = {
}
for cols in columns:
cols_dict[cols+\'_x\'] = cols + str(n)
cols_dict[cols+\'_y\'] = cols + str(n+1)
if k==0:
df = df.rename(columns=cols_dict)
n = n + 2
k = 1
else:
k = 0
print(df)
#构造数据集——情绪指数
columns = self.sentiment_index_column.copy()
columns.remove(\'trade_date\')
for sentiment_index in self.sentiment_index:
query_dict[\'ts_code\'] = sentiment_index
col_name = {
\'_id\':0}
for d in self.sentiment_index_column:
col_name[d] = 1
df1 = pd.DataFrame(list(collection.find(query_dict,col_name).sort([(\'trade_date\',1)])))
df1[\'trade_date\'] = df1[\'trade_date\'].apply(lambda x:re.sub(\'\D\',\'\',x)) #去掉日期中的“-”符号
#按日期合并两个表
df =pd.merge(left=df,right=df1,how=\'left\',on=[\'trade_date\'])
cols_dict = {
}
for cols in columns:
cols_dict[cols+\'_x\'] = cols + str(n)
cols_dict[cols+\'_y\'] = cols + str(n+1)
df = df.rename(columns=cols_dict)
if k==0:
df = df.rename(columns=cols_dict)
n = n + 2
k = 1
else:
k = 0
print(df)
df = df.fillna(0) #数据缺失补上为0,相当于停盘!!!
df.to_csv(filename)