基于Python获取股票分析,数据分析实战
1. Tushare简介
1.1. 开源、免费版Tushare
Tushare是一个免费、开源的python财经数据接口包。主要实现对股票等金融数据从数据采集、清洗加工 到 数据存储的过程,能够为金融分析人员提供快速、整洁、和多样的便于分析的数据,为他们在数据获取方面极大地减轻工作量,使他们更加专注于策略和模型的研究与实现上。考虑到Python pandas包在金融量化分析中体现出的优势,Tushare返回的绝大部分的数据格式都是pandas DataFrame类型,非常便于用pandas/NumPy/Matplotlib进行数据分析和可视化。当然,如果您习惯了用Excel或者关系型数据库做分析,您也可以通过Tushare的数据存储功能,将数据全部保存到本地后进行分析。
私信小编01即可获取大量Python学习资料
地址:http://tushare.org/
1.2. 注册升级版 Tushare pro
Pro版数据更稳定质量更好了,但Pro依然是个开放的,免费的平台,不带任何商业性质和目的。
1.3. 获取Tushare
不管你是量化投资分析师,还是正在学习Python进行数据分析的学习者,这种方法获取的数据都可以适用。
获取前的准备:
pip install tushare
2. 获取数据
我为了更方便的使用Tushare接口API,也为了兼容新、旧版本,设计类整合新版本。
2.1. 获取历史行情数据
#获取历史日线数据 def get_his_dat(self,start_date,end_date): #新pro接口,可以多个股票 if self.pro: self.his_dat = self.stock.daily(ts_code= self.code, start_date=start_date, end_date=end_date) else: #旧接口,不用注册 self.his_dat = ts.get_hist_data(code=self.code,start=start_date, end=end_date) #把索引赋值给trade_date #self.his_dat['trade_date'] = self.his_dat.index self.his_dat = self.his_dat.reset_index() self.setCodebyOld() self.his_dat['ts_code'] = self.code #参照pro接口,修改列名 self.his_dat = self.his_dat.rename(columns={ 'date':'trade_date','volume':'vol','price_change':'change','p_change':'pct_chg'}) #筛选列 self.his_dat = self.his_dat[self.columns] #.reset_index() return self.his_dat
本接口只能获取近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”。
#获取沪深指数 def get_hs_index(self,start_date,end_date): if self.pro: self.hs_index = ts.pro_bar(ts_code= self.code, asset='I', start_date=start_date, end_date=end_date) else: #旧接口,不用注册 index_code={ '000001.SH':'sh','399001.SZ':'399001','000300.SH':'000016.SH','sz50':'sz50','399005.SZ':'zxb','399006.SZ':'cyb'} self.his_dat = ts.get_hist_data(code=index_code[self.code],start=start_date, end=end_date) #把索引赋值给trade_date #self.his_dat['trade_date'] = self.his_dat.index self.his_dat = self.his_dat.reset_index() self.his_dat['ts_code'] = self.code #参照pro接口,修改列名 self.his_dat = self.his_dat.rename(columns={ 'date':'trade_date','volume':'vol','price_change':'change','p_change':'pct_chg'}) #筛选列 self.his_dat = self.his_dat[self.columns] #.reset_index() return self.hs_index
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指数 |
使用方法:
#美股指数 def get_us_index(self,start_date,end_date): if self.pro: self.us_index = self.stock.index_global(ts_code= self.us_code, start_date=start_date, end_date=end_date) self.us_index = self.us_index[self.columns] return self.us_index
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/602.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_dat3. 数据存储在本地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)