1. 程式人生 > >使用TuShare下載歷史逐筆成交資料並生成1分鐘線

使用TuShare下載歷史逐筆成交資料並生成1分鐘線

使用如下程式碼從TuShare下載滬深300每隻股票的歷史成交記錄並按股票、日期儲存到本地。主要是為了以後查詢方便快速。

import numpy as np
import pandas as pd
import tushare as ts
import datetime
import time
import tushare as ts
import os

data_dir = 'D:\\python_study\\stock_hist_data\\'  #下載資料的存放路徑

#ts.get_sz50s() #獲取上證50成份股  返回值為DataFrame:code股票程式碼 name股票名稱

cal_dates = ts.trade_cal() #返回交易所日曆,型別為DataFrame, calendarDate  isOpen

#本地實現判斷市場開市函式 
@date: str型別日期 eg.'2017-11-23'
def is_open_day(date):
    if date in cal_dates['calendarDate'].values:
        return cal_dates[cal_dates['calendarDate']==date].iat[0,1]==1
    return False


#從TuShare獲取tick data資料並儲存到本地
#@symbol: str型別股票程式碼 eg.600030
#@date: date型別日期
def get_save_tick_data(symbol, date):
    global sleep_time,data_dir
    res=True
    str_date=str(date)
    dir=data_dir+symbol+'\\'+str(date.year)+'\\'+str(date.month)
    file=dir+'\\'+symbol+'_'+str_date+'_tick_data.h5'
    if is_open_day(str_date):
        if not os.path.exists(dir):
            os.makedirs(dir)
        if not os.path.exists(file):
            try: 
                d=ts.get_tick_data(symbol,str_date,pause=0.1) 
            except IOError, msg:
                print str(msg).decode('UTF-8')
                sleep_time=min(sleep_time*2, 128)#每次下載失敗後sleep_time翻倍,但是最大128s
                print 'Get tick data error: symbol: '+ symbol + ', date: '+str_date+', sleep time is: '+str(sleep_time)
                return res
            else:   
                hdf5_file=pd.HDFStore(file, 'w',complevel=4, complib='blosc')
                hdf5_file['data']=d 
                hdf5_file.close()                
                sleep_time=max(sleep_time/2, 2) #每次成功下載後sleep_time變為一半,但是至少2s
                print "Successfully download and save file: "+file+', sleep time is: '+str(sleep_time)
                return res
        else:
            print "Data already downloaded before, skip " + file
            res=False
            return res

#獲取從起始日期到截止日期中間的的所有日期,前後都是封閉區間        
def get_date_list(begin_date, end_date):        
    date_list = []
    while begin_date <= end_date:
        #date_str = str(begin_date)
        date_list.append(begin_date)
        begin_date += datetime.timedelta(days=1)
    return date_list

#獲取感興趣的所有股票資訊,這裡只獲取滬深300股票
def get_all_stock_id():
    stock_info=ts.get_hs300s()
    return stock_info['code'].values
        
#從TuShare下載感興趣的所有股票的歷史成交資料,並儲存到本地HDF5壓縮檔案
#dates=get_date_list(datetime.date(2017,11,6), datetime.date(2017,11,12))
dates=get_date_list(datetime.date(2017,10,30), datetime.date(2017,11,4))
stocks=get_all_stock_id()
for stock in stocks:
    for date in dates:
       if get_save_tick_data(stock, date): 
           time.sleep(sleep_time)


因為TuShare並沒有提供1分鐘線的資訊,所以需要根據下載到的每日成交資訊生成1分鐘線資訊。

程式碼如下: 其實就是不用for和列,直接 newdf = df.resample ... 儲存列頭一致就好了

#根據分筆成交資料生成1分鐘線
#根據分筆成交資料生成1分鐘線
def gen_min_line(symbol, date):
    global data_dir
    str_date=str(date)
    dir=data_dir+symbol+'\\'+str(date.year)+'\\'+str(date.month)
    tickfile=dir+'\\'+symbol+'_'+str_date+'_tick_data.h5'
    minfile=dir+'\\'+symbol+'_'+str_date+'_1min_data.h5'
    if (os.path.exists(tickfile)) and (not os.path.exists(minfile)):
        hdf5_file=pd.HDFStore(tickfile, 'r')
        df=hdf5_file['data'] 
        hdf5_file.close()
        print "Successfully read tick file: "+tickfile
        if df.shape[0]<10: #TuShare即便在停牌期間也會返回tick data,並且只有三行錯誤的資料,這裡利用行數小於10把那些unexpected tickdata資料排除掉
            print "No tick data read from tick file, skip generating 1min line"
            return 0
        df['time']=str_date+' '+df['time']
        df['time']=pd.to_datetime(df['time'])
        df=df.set_index('time')
        price_df=df['price'].resample('1min').ohlc()
        price_df=price_df.dropna()
        vols=df['volume'].resample('1min').sum()
        vols=vols.dropna()
        vol_df=pd.DataFrame(vols,columns=['volume'])
        amounts=df['amount'].resample('1min').sum()
        amounts=amounts.dropna()
        amount_df=pd.DataFrame(amounts,columns=['amount'])
        newdf=price_df.merge(vol_df, left_index=True, right_index=True).merge(amount_df, left_index=True, right_index=True)
        hdf5_file2=pd.HDFStore(minfile, 'w')
        hdf5_file2['data']=newdf
        hdf5_file2.close()
        print "Successfully write to minute file: "+minfile

dates=get_date_list(datetime.date(2017,8,1), datetime.date(2017,11,12))
stocks=get_all_stock_id()
for stock in stocks:
    for date in dates:
        gen_min_line(stock, date)


Pandas中的resample,重新取樣,是對原樣本重新處理的一個方法,是一個對常規時間序列資料重新取樣和頻率轉換的便捷的方法。