Tushare是一個免費(fèi)、開源的python財經(jīng)數(shù)據(jù)接口包。主要實現(xiàn)對股票等金融數(shù)據(jù)從數(shù)據(jù)采集、清洗加工 到 數(shù)據(jù)存儲的過程,能夠為金融分析人員提供快速、整潔、和多樣的便于分析的數(shù)據(jù),為他們在數(shù)據(jù)獲取方面極大地減輕工作量,使他們更加專注于策略和模型的研究與實現(xiàn)上??紤]到Python pandas包在金融量化分析中體現(xiàn)出的優(yōu)勢,Tushare返回的絕大部分的數(shù)據(jù)格式都是pandas DataFrame類型,非常便于用pandas/NumPy/Matplotlib進(jìn)行數(shù)據(jù)分析和可視化。當(dāng)然,如果您習(xí)慣了用Excel或者關(guān)系型數(shù)據(jù)庫做分析,您也可以通過Tushare的數(shù)據(jù)存儲功能,將數(shù)據(jù)全部保存到本地后進(jìn)行分析。
私信小編01即可獲取大量Python學(xué)習(xí)資料
地址:http://tushare.org/
Pro版數(shù)據(jù)更穩(wěn)定質(zhì)量更好了,但Pro依然是個開放的,免費(fèi)的平臺,不帶任何商業(yè)性質(zhì)和目的。
不管你是量化投資分析師,還是正在學(xué)習(xí)Python進(jìn)行數(shù)據(jù)分析的學(xué)習(xí)者,這種方法獲取的數(shù)據(jù)都可以適用。
獲取前的準(zhǔn)備:
pip install tushare
我為了更方便的使用Tushare接口API,也為了兼容新、舊版本,設(shè)計類整合新版本。
#獲取歷史日線數(shù)據(jù) 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年的日線數(shù)據(jù),適合搭配均線數(shù)據(jù)進(jìn)行選股和分析。
輸入?yún)?shù)說明:
|股票代碼|開始日期|結(jié)束日期|數(shù)據(jù)類型|
老版本關(guān)鍵字 | 新版本關(guān)鍵字(pro) | 說明 |
code | ts_code | 股票代碼 |
trade_date | 交易日期 | |
start | start_date | 開始日期,格式Y(jié)YYY-MM-DD/新版本YYYYMMDD |
end | end_date | 結(jié)束日期,格式Y(jié)YYY-MM-DD/新版本YYYYMMDD |
ktype | 數(shù)據(jù)類型 | |
retry_count | 當(dāng)網(wǎng)絡(luò)異常后重試次數(shù),默認(rèn)為3 | |
pause | 重試時停頓秒數(shù),默認(rèn)為0 |
老版本中:
1.股票代碼,即6位數(shù)字代碼,或者指數(shù)代碼(sh=上證指數(shù) sz=深圳成指 hs300=滬深300指數(shù) sz50=上證50 zxb=中小板 cyb=創(chuàng)業(yè)板)
2.數(shù)據(jù)類型,D=日k線 W=周 M=月 5=5分鐘 15=15分鐘 30=30分鐘 60=60分鐘,默認(rèn)為D
返回值說明:
老版本關(guān)鍵字 | 新版本關(guān)鍵字(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 | 換手率[注:指數(shù)無此項] | |
amount | 成交額 |
老版本中date為index,不是具體column。
上證指數(shù)、深圳成指、滬深300指數(shù)、上證50 、中小板、創(chuàng)業(yè)板等。
上證指數(shù)代碼為“000001.SH”,老版本代碼為“sh”;深成指數(shù)代碼為“399001.SZ”,老版本為“399001”或“sz”。
#獲取滬深指數(shù) 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
目前pro版本國外已經(jīng)支持如下指數(shù)數(shù)據(jù)(數(shù)據(jù)來源:https://tushare.pro/):
TS指數(shù)代碼 | 指數(shù)名稱 |
XIN9 | 富時中國A50指數(shù) (富時A50) |
HSI | 恒生指數(shù) |
DJI | 道瓊斯工業(yè)指數(shù) |
SPX | 標(biāo)普500指數(shù) |
IXIC | 納斯達(dá)克指數(shù) |
FTSE | 富時100指數(shù) |
FCHI | 法國CAC40指數(shù) |
GDAXI | 德國DAX指數(shù) |
N225 | 日經(jīng)225指數(shù) |
KS11 | 韓國綜合指數(shù) |
AS51 | 澳大利亞標(biāo)普200指數(shù) |
SENSEX | 印度孟買SENSEX指數(shù) |
IBOVESPA | 巴西IBOVESPA指數(shù) |
RTS | 俄羅斯RTS指數(shù) |
TWII | 臺灣加權(quán)指數(shù) |
CKLSE | 馬來西亞指數(shù) |
SPTSX | 加拿大S&P/TSX指數(shù) |
CSX5P | STOXX歐洲50指數(shù) |
使用方法:
#美股指數(shù) 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
升級pro版本,可以獲取3年的數(shù)據(jù),而老版本 只能獲取1個月的分時數(shù)據(jù)。
#獲取分鐘級別數(shù)據(jù) 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:數(shù)據(jù)類型,D=日k線 W=周 M=月 5=5分鐘 15=15分鐘 30=30分鐘 60=60分鐘,默認(rèn)為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為字符型數(shù)字,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. 獲取復(fù)權(quán)數(shù)據(jù)# 獲取復(fù)權(quán)數(shù)據(jù) 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. 數(shù)據(jù)存儲在本地Mongo數(shù)據(jù)庫中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'] # 情緒指數(shù) 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'] # 構(gòu)造LSTM模型訓(xùn)練集 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) # 刪除輸出股票代碼 #構(gòu)造股票數(shù)據(jù)集 n = 0 k = 0 columns = self.stock_column.copy() columns.remove('trade_date') print('Start!') #self.code長度為1,下面循環(huán)不執(zhí)行 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']) #以上證為基準(zhǔn) df =pd.merge(left=df,right=df1,how='inner',on=['trade_date']) # 處理合并表,字段重復(fù)的情況,需要把_x,_y新命名字段,下輪繼續(xù) 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) #構(gòu)造數(shù)據(jù)集——上證、深成指數(shù) query_dict = { 'ts_code':'1'} columns = self.index_daily_column.copy() #默認(rèn)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) #構(gòu)造數(shù)據(jù)集——情緒指數(shù) 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) #數(shù)據(jù)缺失補(bǔ)上為0,相當(dāng)于停盤?。?! df.to_csv(filename)