刺猬教你量化投資(二十):常見(jiàn)重要函數(shù)的實(shí)際運(yùn)用

image.png

查看文件路徑

當(dāng)我們需要導(dǎo)入文件時(shí),如果直接輸入當(dāng)前的絕對(duì)路徑,那么在更換運(yùn)行環(huán)境時(shí),就需要手動(dòng)設(shè)置新的路徑。利用os模塊的自帶函數(shù),我們可以輕松解決這一問(wèn)題。

#當(dāng)我們需要獲取文件的當(dāng)前地址,可以用 __file__
current_file = __file__
#輸出結(jié)果為: c:\python\code\program.py

#要獲取根目錄的地址,可以輸入
root_path = os.path.abspath(os.path.join(current_file, os.pardir, os.pardir))
#其中 os.path.abspath(path) 可返回絕對(duì)路徑

os.path.abspath(os.path.join(current_file, os.pardir, os.pardir))  
# current_file是c:\python\code\program.py,那么os.path.abspath(os.path.join(current_file, os.pardir, os.pardir))是c:\
#獲得根目錄的變量
root_path = os.path.abspath(os.path.join(current_file, os.pardir, os.pardir))

#然后可以按需指定目錄的地址,例如
input_data_path = os.path.abspath(os.path.join(root_path, 'data', 'input_data'))
# input_data_path 的路徑是根目錄下的\data\input_data
# 絕對(duì)地址就是c:\python\\data\input_data

調(diào)用簡(jiǎn)單函數(shù)的方法

假設(shè)我們寫了一個(gè)自定義函數(shù):

def addone(x):
      return x+1

要調(diào)用這個(gè)函數(shù)時(shí),可使用apply函數(shù),也可以使用lambda函數(shù)進(jìn)行調(diào)用。

#apply的方式
print df[['漲跌幅']].apply(addone)

#lambda的方式
print df[['漲跌幅']].apply(lambda x: x+1)

補(bǔ)全數(shù)據(jù)

有時(shí)候獲得的股票行情數(shù)據(jù),會(huì)出現(xiàn)非交易日缺失的情況,這時(shí)就需要基于指數(shù)交易日的數(shù)據(jù),用merge函數(shù)對(duì)其進(jìn)行補(bǔ)全。

merge函數(shù)的參數(shù)

還有個(gè)參數(shù)是indecator,等于True時(shí)增加merge列,表明該行數(shù)據(jù)的出處,源自哪一張表,有l(wèi)eft、right、both的區(qū)分。

如果是堆砌,可用concat函數(shù),相關(guān)參數(shù)如下:

image.png
import pandas as pd
s1 = pd.Series([0,1,2],index = ['a','b','c'])
s2 = pd.Series([2,3,4],index = ['c','f','e'])
s3 = pd.Series([4,5,6],index = ['c','f','g'])
series = pd.concat([s1,s2,s3])#默認(rèn)并集、縱向連接
series
image.png
series = pd.concat([s1,s2,s3],ignore_index = True)  # 生成縱軸上的并集,索引會(huì)自動(dòng)生成新的一列
series
image.png
series = pd.concat([s1,s2,s3],axis = 1,join = 'inner')
series
# 縱向取交集,注意該方法對(duì)對(duì)象表中有重復(fù)索引時(shí)失效
image.png
series = pd.concat([s1,s2,s3],axis = 1,join = 'outer')
series
# 橫向索引取并集,縱向索引取交集,注意該方法對(duì)對(duì)象表中有重復(fù)索引時(shí)失效
image.png

resample函數(shù)

通常我們獲得的數(shù)據(jù)是日線數(shù)據(jù),需要轉(zhuǎn)化成周數(shù)據(jù)或月數(shù)據(jù)時(shí),可用resample函數(shù)獲得。

當(dāng)索引為時(shí)間格式時(shí),可用resample函數(shù)將時(shí)間序列數(shù)據(jù)自動(dòng)分割為周、月、季、年等塊,然后再進(jìn)行相應(yīng)的處理。這里需要用到參數(shù)rule,參數(shù)rule='w'代表轉(zhuǎn)化為周,'m'代表月,'q'代表季度,'y'代表年份。'5min'代表5分鐘,'1min'代表1分鐘。

week_df = df.resample(rule='w').last() # 意思是展現(xiàn)每周最后一個(gè)交易日的數(shù)據(jù)
week_df['開(kāi)盤價(jià)'] = df['開(kāi)盤價(jià)'].resample(rule='w').first() # 獲得開(kāi)盤價(jià)數(shù)據(jù)
week_df['成交量'] = df['成交量'].resample(rule='w').sum()   # 獲得成交總量數(shù)據(jù)
week_df['最高價(jià)'] = df['最高價(jià)'].resample(rule='w').max()  # 獲得最高價(jià)數(shù)據(jù)
week_df['最低價(jià)'] = df['最低價(jià)'].resample(rule='w').min()  # 獲得最低價(jià)數(shù)據(jù)

#若要獲得周漲幅,一般可用公式【(最后一天的收盤價(jià) - 第一天的開(kāi)盤價(jià)) / 第一天的開(kāi)盤價(jià) 】進(jìn)行計(jì)算,也可以用lambda函數(shù)直接獲得
week_df['漲跌幅'] = df['漲跌幅'].resample(rule='w').apply(lambda x: (x+1.0).prod() - 1.0 )

用os.walk導(dǎo)入數(shù)據(jù)

當(dāng)輸入os.walk(data_path)時(shí),會(huì)返回root、dirs和files的數(shù)據(jù),root是文件的路徑,dir是路徑下有什么文件夾(返回列表),files是路徑下有什么文件(返回列表)。

然后程序會(huì)到第一個(gè)文件夾里面,繼續(xù)返回相應(yīng)的root、dirs和files……直至全部遍歷。

有了這個(gè)系統(tǒng)自帶函數(shù),后面就好辦了。

首先,我們要獲得想要導(dǎo)入的股票的代碼的列表。

list = []
data_path = config.data_path + '/data'
for root, dirs, files in os.walk(data_path):
       if files:   # 當(dāng)files不為空
           for i in files: #對(duì)files的每一個(gè)文件
                if i.endswith('.csv'):   # 選取以csv為后綴的文件
                      list.append(i[:8])   #將該文件的前8個(gè)字符加入到列表中

print list

第二步,開(kāi)始根據(jù)列表來(lái)導(dǎo)入數(shù)據(jù)

alldata = pd.DataFrame()
for stock in list:
     print stock
     df = importcode.import(stock)
      alldata = alldata.append(df, ignore_index = True)
print alldata

CSV的替代——HDF

一般儲(chǔ)存數(shù)據(jù)是用csv格式,但pandas提供了一種更高效率的方式,那就是hdf格式。

想象一張Excel表,sheetname這里稱作KEY,參數(shù)mode可以是w新建,也可以是a,append。更多參數(shù)如下:

image.png

保存的命令為:

#alldata.to_hdf(path, key='',mode='')
alldata.to_hdf(config.output_data_path + '/alldata.h5', key='all_stock_data',  mode='w'))


# 在前面的例子中,讀取的股票數(shù)據(jù)df,可以這樣保存
# h5[stock] = df
# 或者
# df.to_hdf(path, key = code, mode='a')

#保存完數(shù)據(jù)之后,記得關(guān)閉h5文件,否則容易報(bào)錯(cuò)
h5.close()

要讀取的時(shí)候,可以用 pd.read_hdf(path, key='')

image.png
 #讀取某個(gè)stock的數(shù)據(jù)有兩種方式
print h5.get('sz000006') 
print h5['sz000007']

#查詢有多少?gòu)埍恚梢杂胟eys()
print h5.keys()

分組統(tǒng)計(jì)的groupby函數(shù)

一張超大的數(shù)據(jù)表中,我們想要看某只股票的平均價(jià)格,可用groupby函數(shù)來(lái)實(shí)現(xiàn)。

1、基本的groupby用法

print stock_data.groupby('交易日期')  #按交易日期來(lái)分組
print stock_data.groupby('交易日期') .size() #顯示每天交易股票的數(shù)量
print stock_data.groupby('股票代碼') .size() #顯示每只股票累計(jì)交易的天數(shù)

#分組后想看某只股票的數(shù)據(jù),可用get_group()
print stock_data.groupby('股票代碼').get_group('002466')
#只會(huì)輸出天齊鋰業(yè)的數(shù)據(jù)

除此之外,還可以
print stock_data.groupby('股票代碼').describe()
print stock_data.groupby('股票代碼').first()
print stock_data.groupby('股票代碼').last()
print stock_data.groupby('股票代碼').head()
print stock_data.groupby('股票代碼').tail()
print stock_data.groupby('股票代碼').nth(n) 表示該組的第n行數(shù)據(jù)
輸出的時(shí)候,默認(rèn)group的變量,即股票代碼為index,不想這樣的話,可以用as_index=False, 例如:
print stock_data.groupby('股票代碼',as_index=False)

還可以
print stock_data.groupby('股票代碼')['收盤價(jià)', '漲跌幅'].mean() 取某列數(shù)據(jù)算均值
.max()
.sum()
都是可以的。

還可以輸出排名,用rank()
print stock_data.groupby('股票代碼')['成交量'].rank() 輸出組內(nèi)的算數(shù)排名
print stock_data.groupby('股票代碼')['成交量'].rank(pct=True) 輸出百分比

還可以
print stock_data.groupby(stock_data['交易日期'].dt.year).size() # 計(jì)算該年共有多少個(gè)交易數(shù)據(jù)

還可以先groupby一個(gè),然后再在其中g(shù)roupby另一個(gè)參數(shù),例如:
stock_data.groupby(['股票代碼’, stock_data['交易日期'].dt.year]).size() # 按照股票代碼分組,然后求該證券每年有多少個(gè)交易日

2、進(jìn)階的groupby用法

前面介紹的resample、apply、fillna等函數(shù),都可以嵌入到groupby函數(shù)里面。

當(dāng)然,也可以用笨辦法,用for key, group in df.groupby('列名稱'): 將所需功能遍歷一遍,以達(dá)到相同的效果。key是列名,列的每一個(gè)內(nèi)容,group是該列的內(nèi)容。

遍歷的時(shí)候,對(duì)group進(jìn)行單獨(dú)操作即可,例如group.apply()或group.fillna()

然后只要將每個(gè)group append起來(lái)即可。

結(jié)語(yǔ)

上述回顧的函數(shù)和功能,在量化投資的實(shí)際操作中會(huì)經(jīng)常用到,必須熟練掌握。

刺猬偷腥
2018年10月8日

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容