轉自微信公眾號:量化小白上分記
回歸作為數據分析中非常重要的一種方法,在量化中的應用也很多,從最簡單的因子中性化到估計因子收益率,以及整個Barra框架,都是以回歸為基礎,本文總結各種回歸方法以及python實現的代碼。
回歸是研究多組自變量X1,X2,...,Xn與一個因變量Y關係的模型,首先從最簡單的OLS開始,變量假設如下
回歸模型可以表示為
同時線性回歸還必須滿足「BLUE」的假設,在這些假設下,回歸的目標是在已知X,Y的情況下估計回歸係數beta,OLS的思想是最小化殘差平方和,即
OLS估計量具有一致性、無偏性等優點。
接下用用python實現OLS,所用數據為特定日期全A股的PB、ROE、行業、市值數據,部分數據如下,數據和代碼獲取後臺回復「回歸」。
python中實現OLS的模塊很多,numpy、sklearn、statsmodels中都有,這裡給出numpy,statsmodel中的用法。
np.linalg.lstsq(a, b, rcond='warn')lstsq的輸入包括三個參數,a為自變量X,b為因變量Y,rcond用來處理回歸中的異常值,一般不用。
lstsq的輸出包括四部分:回歸係數、殘差平方和、自變量X的秩、X的奇異值。一般只需要回歸係數就可以了。
這裡需要注意的一點是,必須自己在自變量中添加截距項,否則回歸結果是沒有截距項的,其他細節可以參考help。
這裡我們用一個行業股票的數據實現PB-ROE回歸,代碼如下
datas = pd.read_excel('data.xlsx',index_col = 0)
datas = datas.loc[(datas.pb_lf>0) &(datas.pb_lf<10) ]
datas = datas.loc[(datas.roe_ttm2>0) &(datas.roe_ttm2 < 10)]
datas1 = datas.loc[datas.classname == '醫藥生物']
x = datas1[['roe_ttm2']]
x['Intercept'] = 1
y = datas1['pb_lf']
beta,resid,ranks,s = np.linalg.lstsq(x,y)
y_fitted = beta[0]*datas1[['roe_ttm2']] + beta[1]
plt.figure(figsize = (8,6))
plt.plot(datas1.roe_ttm2, datas1.pb_lf,'ko', label='sample')
plt.plot(datas1.roe_ttm2, y_fitted, 'black',label='OLS',linewidth = 2)
plt.xlabel('ROE')
plt.ylabel('PB')
plt.legend()
plt.show()
關於PB-ROE
PB-ROE提供了一種投資的框架,這種框架是說,股票的PB和ROE之間存在近似的線性關係,ROE越高,PB越高,因此如果同時根據PB、ROE值來投資,很難選到同時滿足PB最小、ROE最大的股票。但可以根據他們的線性關係進行選擇,回歸直線上的點可以視為合理的PB、ROE組合水平,這樣位於回歸線下方的股票都是PB被低估的,未來有很大的上升修復空間,而位於回歸線上方的股票都是當前PB被高估的,未來會下降,因此投資可以選擇位於回歸線下方的股票。使用這種方法最重要的點是回歸必須是靠譜的,比如ROE應該是穩定的,確保未來可持續,比如應想辦法消除行業間的差異等等。
lstsq比較方便用在只需要回歸係數的情況下,如果需要對回歸結果做評估,比如算擬合值、算殘差、算R2,做t檢驗、F檢驗、算P值,就很麻煩了,而statsmodel恰好適合這種情況。
statsmodels.formula.api(sml)statsmodels中做回歸有很多模塊都能實現,sml.ols的優點是可以寫成公式型的回歸,類似R中做回歸的過程,比如PB和ROE的回歸可以用公式表示為'pb~roe',多個自變量之間用加號連接。sml.ols一般包括formula和data兩個輸入,formula是回歸的公式,data為使用的數據。此外,還有missing這個參數,對於回歸數據包含缺失值時很好用,比如設置missing = 'drop'表示回歸時刪除包含缺失值的樣本。代碼如下
import statsmodels.formula.api as sml
model = sml.ols(formula='pb_lf~roe_ttm2',data = datas1)
result=model.fit()
result.params # 回歸係數
result.rsquared # R方
result.resid # 殘差
result.fittedvalues # 擬合值
用summary函數可以出比較美觀的結果。
sm.ols是statsmodels中另一個回歸的模塊,它的輸入類似lstsq,輸入變量y,x即可,這裡使用patsy中的dmatrics生成x,y,需要注意的是,dmatrices生生成的x是自帶截距項的,代碼如下,summary輸出結果同上。
import statsmodels.api as sm
from patsy import dmatrices
from scipy.linalg import toeplitz
import numpy.linalg as la
y,X=dmatrices('pb_lf~roe_ttm2',data=datas1,return_type='dataframe')
mod = sm.OLS(y,X)
res = mod.fit()
res.summary()
GLS是廣義最小二乘法的縮寫,剛才總結的OLS滿足很多假設,但實際數據往往沒有那麼好的性質,GLS用來解決異方差的問題,在數據有異方差的問題時,OLS的結果不再具有無偏性等性質,GLS的結果更好。它的主要思想是給解釋變量加上一個權重,從而使得加上權重後的回歸方程方差是相同的.因此在GLS方法下可以得到估計量的無偏和一致估計。
使用這種方法的前提時,你已經對誤差項的協方差陣有了較好的估計。statsmodel中實現GLS的模塊如下
常用的輸入包括因變量endog,自變量exog,殘差的協方差陣sigma,missing設定樣本中缺失值的處理方法,這裡exog也是不帶截距項的,需要自己加入,可以用sm.add_constant(),代碼如下
x = datas1[['roe_ttm2','mktcap']]
x['mktcap'] = np.log(x.mktcap)
sigma = x.T.var()
x = sm.add_constant(x)
y = datas1['pb_lf']
sm.GLS(y, x,sigma = sigma).fit().params
WLS是加權最小二乘法的簡稱,如果仔細看上一張圖GLS函數的說明,可以看到,當sigma是一個向量的時候,GLS等價於WLS,即WLS表示殘差的協方差陣是對角陣。可以用sm.WLS或者sm.GLS實現,代碼同上。
RLS表示帶約束的最小二乘法,這裡的約束只包括線性約束,可以表示為AX = B的形式,如果有其他類型的約束,需要用其他方法,數學上可以證明,線性約束下,最小二乘法仍有最優解。rls的實現可以使用statsmodels.sandbox.rls。函數說明如下
endog表示Y,exog表示X,constr線性約束的A,params表示線性約束的B,默認為0,sigma是權重,同GLS。大部分跟之前都是一樣的,唯一需要注意的是約束的輸入,根據約束條件寫出A,B然後輸入。
帶約束的最小二乘法在量化中非常常用,比如做行業中性化時,如果所有行業虛擬變量都保留,並且添加了截距項的情況下,會出現變量多重共線性,回歸結果無效,這時候一種方法是刪除一個虛擬變量,還有一種方法是添加一個約束。比如可以添加行業的市值佔比和係數乘積的和為0:
其中,w為各行業流通市值佔比,這種方法下,對pb因子做中性化的代碼如下
from statsmodels.sandbox.rls import *
weights = datas.mktcap.groupby(datas.classname).sum()/datas.mktcap.sum()
class_var = pd.get_dummies(datas['classname'],columns=['classname'],prefix='class',
prefix_sep="_", dummy_na=False, drop_first = False)
x = class_var
x = pd.concat([class_var,np.log(datas.mktcap)],axis = 1)
x = sm.add_constant(x)
y = datas['pb_lf']
con1= [0] + list(weights) + [0]
models = RLS(y, x,constr = con1).fit()
models.resid
Logistic回歸是一種用來做Y是類別變量的方法,可以用statsmodels.discrete.discrete_model.Logit實現,代碼輸入跟之前的差不多
【相關文章】
量化 | 從零開始學量化(四):用python寫一個擇時策略回測
量化 | 從零開始學量化(三):數據獲取途徑
量化 | 從零開始學量化(二):python/matlab/r/sas/vba選哪個
量化 | 從零開始學量化(一):量化如何入門