本系列的第一篇因子加權方法中提到,對於因子間有相關性的情況,可以通過最大化IR來解決,但也會存在另一個問題:因子協方差矩陣的估計,文中對比了最原始的樣本協差陣和Ledoit壓縮估計量結果的差異,表明協方差矩陣的估計效果對於結果有很大影響。本文給出另一種更為常用的解決因子間相關性的方法:因子正交化。
因子多重共線性
如上一篇所述,傳統的多因子模型一般採用IC加權、ICIR加權等方法,這些方法都是以IC為基礎確定各因子在模型中的權重。而IC是當期因子暴露與下一期收益間的相關係數。如果因子間存在較強的相關性/相關性,通過上述加權方式,最終會導致因子對於某種風格的因子重複暴露。使得整個組合的表現嚴重偏向於該因子,削弱其他因子的效果。具體來說,當因子表現好時,組合會獲得更高的超額收益,但因子表現不好時,也會出現更大幅的回撤。
舉個慄子,在上篇三因子組合市淨率、1個月動量、市值的基礎上,加入流通市值因子進行四因子組合。採用過去24個月ICIR加權、月度調倉的方式。組合從2012年1月-2018年12月的表現如下
基準採用滬深300指數,顯然,四因子組合由於在估摸因子上的重複暴露,導致15年股災之後,相較於三因子組合出現了超額增長,但在17年規模因子失效後出現了更大回撤。
正交相關定義
首先給出正交相關的一些概念,忘記的可以再翻一翻線性代數/高等代數。
此外,有興趣可以再去看看正交變換、旋轉放縮變換的矩陣表達式,可以加深理解。
因子正交化統一框架
對於因子多重共線性的問題,可以通過因子正交化的方法來解決。因子正交化有多種方式。目前應用最多的有四種:回歸取殘差、施密特正交化、規範正交化、對稱正交化。其中,後三種都是通過因子旋轉的方式來消除因子間的相關性,而第一種,後文會給出證明,實質上跟施密特正交化是一致的。因此,首先對後三種正交化方式給出統一說明(這部分參考了報告[1][2],覺得描述不清楚的可以再去看看報告):
標準化的意義在於,正交跟不相關的概念本來是不等價的,正交不一定不相關,但加上Z-SCORE標準化之後,正交等價於線性相關係數為0。
以上是因子正交框架,不同的正交化方法具有不同的特性,接下來一一說明,並給出代碼。
施密特正交化就是高等代數教科書上的方法,給定一組向量後,分兩步操作,第一步按照一定順序把每個向量與之前所有向量進行正交。第二步對於正交後的向量進行歸一化,最終得到的所有向量兩兩正交且模為1,正交後的因子暴露矩陣為正交陣,用公式表達為
這裡給出的代碼裡正交順序是直接按照輸入因子矩陣的順序,從左向右依次正交。輸入factors為已經標準化後的因子矩陣,返回Q為正交因子矩陣。
# 固定順序的施密特正交化
def Schimidt(self,factors):
class_mkt = factors[['mkt_cap','classname']]
factors1 = factors.drop(['mkt_cap','classname'],axis = 1)
col_name = factors1.columns
factors1 = factors1.values
R = np.zeros((factors1.shape[1], factors1.shape[1]))
Q = np.zeros(factors1.shape)
for k in range(0, factors1.shape[1]):
R[k, k] = np.sqrt(np.dot(factors1[:, k], factors1[:, k]))
Q[:, k] = factors1[:, k]/R[k, k]
for j in range(k+1, factors1.shape[1]):
R[k, j] = np.dot(Q[:, k], factors1[:, j])
factors1[:, j] = factors1[:, j] - R[k, j]*Q[:, k]
Q = pd.DataFrame(Q,columns = col_name,index = factors.index)
Q = pd.concat([Q,class_mkt],axis = 1)
return Q
注意這裡不能用python中的QR分解函數np.linalg.qr計算,施密特正交化是QR分解的一種方法,但numpy的QR分解函數並不是用這種方法做的。
回歸取殘差的方法過程類似施密特正交化,按照一定的順序將每個向量同之前的所有向量回歸取殘差代替原值。接下裡證明,施密特正交化與最小二乘下的回歸取殘差是一致的。差別僅在於,施密特正交化多了一步歸一化。
規範正交化實際上跟主成分分析思路是一樣的,但主成分分析在截面上應用可以,用在時間序列上就會出現對應關係不一致的問題,這也是規範正交化的問題。
# 規範正交
def Canonial(self,factors):
class_mkt = factors[['mkt_cap','classname']]
factors1 = factors.drop(['mkt_cap','classname'],axis = 1)
col_name = factors1.columns
D,U=np.linalg.eig(np.dot(factors1.T,factors1))
S = np.dot(U,np.diag(D**(-0.5)))
Fhat = np.dot(factors1,S)
Fhat = pd.DataFrame(Fhat,columns = col_name,index = factors.index)
Fhat = pd.concat([Fhat,class_mkt],axis = 1)
return Fhat
# 對稱正交
def Symmetry(self,factors):
class_mkt = factors[['mkt_cap','classname']]
factors1 = factors.drop(['mkt_cap','classname'],axis = 1)
col_name = factors1.columns
D,U=np.linalg.eig(np.dot(factors1.T,factors1))
S = np.dot(U,np.diag(D**(-0.5)))
Fhat = np.dot(factors1,S)
Fhat = np.dot(Fhat,U.T)
Fhat = pd.DataFrame(Fhat,columns = col_name,index = factors.index)
Fhat = pd.concat([Fhat,class_mkt],axis = 1)
return Fhat
對於四因子組合,分別用上述三種因子正交化方法正交之後,組合表現如下
可以看出,對稱正交化後的四因子組合表現與三因子表現幾乎完全一致,表明對稱正交非常完美的剔除了因子相關性的影響,其他三種正交化方法的效果一般,這也與文獻【1】【2】中的結論一致。
【1】20171030-天風證券-天風證券金工專題報告:因子正交全攻略,理論、框架與實踐
【2】20180310-光大證券-光大證券多因子系列報告之十:因子正交與擇時,基於分類模型的動態權重配置
【3】20170119-海通證券-選股因子系列研究(十七):選股因子的正交
多因子嘗試(一):因子加權
資產瞎配模型(一):MVO、風險平價等
資產瞎配模型(二):對(一)的糾正