Python量化交易05——基于多因子选择和选股策略(随机森林,LGBM)
??參考書目:深入淺出Python量化交易實(shí)戰(zhàn)
在機(jī)器學(xué)習(xí)里面的X叫做特征變量,在統(tǒng)計(jì)學(xué)里面叫做協(xié)變量也叫自變量,在量化投資里面則叫做因子,所謂多因子就是有很多的特征變量。
本次帶來(lái)的就是多因子模型,并且使用的是機(jī)器學(xué)習(xí)的強(qiáng)大的非線性模型,集成學(xué)習(xí)里面的隨機(jī)森林和LGBM模型,帶來(lái)因子的選擇策略和股票的選擇策略。
由于股票數(shù)據(jù)的獲取都需要第三方庫(kù)或者是專業(yè)的量化投資框架,很多第三方庫(kù)某些功能需要收費(fèi)(Tushare),而免費(fèi)的一些庫(kù)(證券寶)獲取的數(shù)據(jù)特征變量又沒(méi)那么多。所以這里是用聚寬量化投資框架,是可以免費(fèi)使用一些功能的(只需要注冊(cè)一個(gè)賬號(hào))。這里獲取數(shù)據(jù)就采用聚寬平臺(tái)的功能了。
數(shù)據(jù)獲取
本次使用滬深300作為股票池,選獲取一些財(cái)務(wù)指標(biāo):
#創(chuàng)建query對(duì)象,指定獲取股票的代碼、市值、凈運(yùn)營(yíng)資本
#凈債務(wù)、產(chǎn)權(quán)比率、股東權(quán)益比率、營(yíng)收增長(zhǎng)率、換手率、
#市盈率(PE)、市凈率(PB)、市銷率(PS)、總資產(chǎn)收益率因子
?
?需要在聚寬的環(huán)境才能獲得上面的數(shù)據(jù),本地Python是出不來(lái)的。
設(shè)置一下股票代碼作為索引,獲取一些時(shí)間格式。
#將股票代碼作為數(shù)據(jù)表的index df.index = df.code.values #使用del也可以刪除列 del df['code'] #下面來(lái)把時(shí)間變量都定義好 today = datetime.datetime.today() #設(shè)定3個(gè)時(shí)間差,分別是50天,1天和2天 delta50 = datetime.timedelta(days=50) delta1 = datetime.timedelta(days=1) delta2 = datetime.timedelta(days=2) #50日前作為一個(gè)歷史節(jié)點(diǎn) history = today - delta50 #再計(jì)算昨天和2天前的日期 yesterday = today - delta1 two_days_ago = today - delta2再然后獲取一些技術(shù)指標(biāo)數(shù)據(jù):
#下面就獲取股票的動(dòng)量線、成交量、累計(jì)能量線、平均差、
#指數(shù)移動(dòng)平均、移動(dòng)平均、乖離率等因子
#時(shí)間范圍都設(shè)為10天
這樣就獲得了很多X,即特征變量,即因子。
下面構(gòu)建y,我們的響應(yīng)變量是一個(gè)分類的變量,即是否獲得了超過(guò)市場(chǎng)的平均回報(bào)的收益率,是的話為1,不是為0 。
這里使用前一日的收盤價(jià)除以前50天的收盤價(jià)?然后減去1,作為收益率的值,計(jì)算出那些收益率大于均值的樣本股則y為1 ,否則為0 。
#獲取股票前一日的收盤價(jià) df['close1']=list(get_price(stocks, end_date=yesterday, count = 1,fq='pre',panel=False)['close']) #獲取股票50日前的收盤價(jià) df['close2']=list(get_price(stocks, end_date=history, count = 1,fq ='pre',panel=False)['close'])#計(jì)算出收益 df['return']=df['close1']/df['close2']-1 #如果收益大于平均水平,則標(biāo)記為1 #否則標(biāo)記為0 df['signal']=np.where(df['return']<df['return'].mean(),0,1) #檢查是否成功 df.head()?可以看到最后一列是我們的響應(yīng)變量y。
模型構(gòu)建
將X和y都準(zhǔn)備好。劃分訓(xùn)練集和測(cè)試集,導(dǎo)入隨機(jī)森林分類器。
#導(dǎo)入數(shù)據(jù)集拆分工具 from sklearn.model_selection import train_test_split #導(dǎo)入隨機(jī)森林分類器 from sklearn.ensemble import RandomForestClassifier #把因子值作為樣本的特征,所以要去掉剛剛添加的幾個(gè)字段 X = df.drop(['close1', 'close2', 'return', 'signal'], axis = 1) #把signal作為分類標(biāo)簽 y = df['signal'] #將數(shù)據(jù)拆分為訓(xùn)練集和驗(yàn)證集 X_train,X_test,y_train,y_test=train_test_split(X,y,test_size = 0.2) #創(chuàng)建隨機(jī)森林分類器實(shí)例,指定random_state便于復(fù)現(xiàn) clf = RandomForestClassifier(n_estimators=5000,random_state=100) #擬合訓(xùn)練集數(shù)據(jù) clf.fit(X_train, y_train) #查看分類器在訓(xùn)練集和驗(yàn)證集中的準(zhǔn)確率 print(clf.score(X_train, y_train),clf.score(X_test, y_test))?
分類問(wèn)題,所以采用隨機(jī)森林分類器,然后進(jìn)行擬合和評(píng)價(jià)。
可以看到在訓(xùn)練集上的準(zhǔn)確率為100%,在測(cè)試集刪高的準(zhǔn)確率為0.9333,說(shuō)明模型的擬合效果很不錯(cuò)。
?
?因子重要性
接下來(lái)使用隨機(jī)森林的變量的重要性排序,原理是基礎(chǔ)學(xué)習(xí)器決策樹(shù)分裂時(shí),若一個(gè)變量分裂時(shí)讓損失函數(shù)下降得越多,說(shuō)明這個(gè)變量越重要。
#為了便于觀察,我們創(chuàng)建一個(gè)數(shù)據(jù)表
#數(shù)據(jù)表有兩個(gè)字段,分別是特征名和重要性
#特征名就是因子的名稱
?可以看到最重要的變量是技術(shù)指標(biāo)平均差。這也是肯定的,因?yàn)槠骄罾锩姘诉^(guò)去和現(xiàn)在的股價(jià)信息最多,和我們的響應(yīng)變量最為相似。
畫圖更加直觀的查看變量重要性排序。
import seaborn as sns plt.figure(figsize=(6,4),dpi=128) sns.barplot(y=factor_weight['features'],x=factor_weight['importance'],orient="h") plt.xlabel('重要程度') plt.ylabel('因子名稱') plt.xticks(fontsize=10,rotation=35) plt.title("因子重要性對(duì)比") plt.show()?和上面結(jié)論一樣,技術(shù)指標(biāo)平均差對(duì)我們的響應(yīng)變量是否獲得超額回報(bào)的影響最大,然后是公司本身的財(cái)務(wù)指標(biāo),營(yíng)業(yè)收入增長(zhǎng)率,凈收運(yùn)營(yíng)資本等。
選股策略
接下來(lái)我們使用對(duì)于表格數(shù)據(jù)最強(qiáng)的機(jī)器學(xué)習(xí)方法,輕量梯度提升方法——LGBM模型,對(duì)我們的股票市值進(jìn)行預(yù)測(cè),然后選取實(shí)際值和預(yù)測(cè)值差距最大的股票作為選股策略。即選取價(jià)值被低估的股票。
此時(shí)y是股票市值,X是前面那些財(cái)務(wù)技術(shù)指標(biāo)
X=df.iloc[:,1:-3] y=df.iloc[:,0]構(gòu)建回歸器
from lightgbm import LGBMRegressor model = LGBMRegressor(n_estimators=100,objective='regression', random_state=0) model.fit(X, y) model.score(X, y)?整體模型的擬合優(yōu)度為86%,還不錯(cuò)。
用真實(shí)值減去預(yù)測(cè)值,然后進(jìn)行排序,算的找出前10 的被低估的公司
diff = pd.DataFrame(np.array(y)-model.predict(X), index = y.index, columns = ['預(yù)測(cè)值和真實(shí)值的差值']) #將該數(shù)據(jù)表中的值,按生序進(jìn)行排列 diff = diff.sort_values(by = '預(yù)測(cè)值和真實(shí)值的差值', ascending = True) #找到市值被低估最多的10只股票 diff.head(10)?前十都是被低估了,負(fù)得越多說(shuō)明被低估的越厲害。
?受限于框架的使用,該策略我本人沒(méi)有進(jìn)行回測(cè)檢驗(yàn)其收益率。書上的收益率大概是年化6%,不高,但是也算不錯(cuò)了。
(本案例僅作為策略研究,不構(gòu)成任何投資意見(jiàn)。)
總結(jié)
以上是生活随笔為你收集整理的Python量化交易05——基于多因子选择和选股策略(随机森林,LGBM)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 理解并实现 你自己的 订阅-发布模式
- 下一篇: websocket python爬虫_p