1. Tushare簡介
1.1. 開源、免費版Tushare
Tushare是一個免費、開源的Python/ target=_blank class=infotextkey>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/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)