書接上回,關於《用多因子模型構建強大的加密資產投資組合》系列文章中,我們已經發布了三篇:《理論基礎篇》、《數據預處理篇》、《因子有效性檢驗篇》。
前三篇分別解釋了多因子策略的理論與單因子測試的步驟。
一、因子相關性檢驗的原因:多重共線性
我們通過單因子測試部分篩選出一批有效因子,但以上因子不能直接入庫。因子本身可以根據具體的經濟含義進行大類劃分,同類型的因子間存在較強的相關性,若不經相關性篩選直接入庫,根據不同因子進行多元線性迴歸求預期收益率時,會出現多重共線性問題。計量經濟學中,多重共線性是指回歸模型中的一些或全部解釋變量存在“完全”或準確的線性關係(各變量間高度相關)。
因此,有效因子篩選出後,首先需要根據大類對因子的相關性進行T檢驗,對於相關性較高的因子,要麼捨棄顯著性較低的因子,要麼進行因子合成。
多重共線性的數學解釋如下:
$$$ Y = β₁ + β₂X₂ᵢ + β₃X₃ᵢ + ... + βₖXₖᵢ + μᵢ , i = 1,2,...,n $$$
會存在兩種情況:
1.$$C₂X₂ᵢ + C₃X₃ᵢ + … + CₖXₖᵢ = 常數向量$$,$$ Cᵢ$$不全為$$0→Xᵢ$$ 間存在完全共線
2.$$C₂X₂ᵢ + C₃X₃ᵢ + … + CₖXₖᵢ + Vᵢ = 常數向量$$,$$Cᵢ$$不全為0,$$Vᵢ$$為隨機誤差項,$$→Xᵢ$$間存在完全共線
多重共線性導致的後果:
1.完全共線性下參數估計量不存在
2.近似共線性下OLS估計量非有效
我們首先定義方差膨脹因子(variance- inflating factor, VIF)為 $$VIF=1 / (1 - rᵢⱼ)$$ ,指參數估計量的方差由於出現多重共線性而膨脹,隨著相關係數增加,VIF顯著增加。
以二元線性模型為例:$$Y = β₁ + β₂X₂ᵢ + β₃X₃ᵢ + μᵢ$$
$$$ var(β₂) = (σ²/ΣX²₂)·(1/(1-r²₂₃)) $$$
$$$ 相關係數的平方和r²₂₃=(ΣX₂ᵢX₃ᵢ)²/ ΣX²₂ᵢΣX²₃ᵢ ≤ 1 $$$
$$$ 1/(1-r²₂₃)≥ 1 $$$
-
完全不共線(完全不相關):$$r²₂₃ = 0 → var(β₂) = σ²/ΣX²₂$$
-
近似共線:$$0<r²₂₃<1 → var(β₂) = (σ²/ΣX²₂)·(1/(1-r²₂₃)) > σ²/ΣX²₂,越接近1,方差↑$$
-
完全共線:$$r²₂₃ = 1 → var(β₂) = ∞,方差無限大$$
3.參數估計量經濟含義不合理
4.變量的顯著性檢驗(t檢驗)失去意義
5.模型的預測功能失效:通過多元線性模型擬合出的預測收益率極其不準確,模型失效。
二、步驟一:同類型因子的相關性檢驗
檢驗新求出的因子與已入庫因子的相關性。通常來說,有兩類數據求相關性:
1.根據所有token在回測期間的因子值求相關
2.根據所有token在回測期間的因子超額收益值求相關
$$$ 超額收益 = 多頭組收益 - 基準收益,收益 = ln(closeₜ / closeₜ ₋₁) $$$
我們所求的每個因子對token的收益率都有一定的貢獻和解釋能力。進行相關性檢驗**,是為了找到對策略收益有不同解釋和貢獻的因子,策略的最終目的是收益**。如果兩個因子對收益的刻畫是相同的,即使兩個因子值存在很大差別也無意義。因此,我們並不是想找到因子值本身差異大的因子,而是想找到因子對收益刻畫不同的因子,所以最終選擇了用因子超額收益值求相關。
我們的策略是日頻,所以按回測區間的日期計算因子超額收益之間的相關係數矩陣
編程求解與庫內相關最高的前n個因子:
def get_n_max_corr(self, factors, n=1):
factors_excess = self.get_excess_returns(factors)
save_factor_excess = self.get_excess_return(self.factor_value, self.start_date, self.end_date)
if len(factors_excess) < 1:
return factor_excess, 1.0, None
factors_excess[self.factor_name] = factor_excess['excess_return']
factors_excess = pd.concat(factors_excess, axis=1)
factors_excess.columns = factors_excess.columns.levels[0]
# get corr matrix
factor_corr = factors_excess.corr()
factor_corr_df = factor_corr.abs().loc[self.factor_name]
max_corr_score = factor_corr_df.sort_values(ascending=False).iloc[1:].head(n)
return save_factor_excess, factor_corr_df, max_corr_score
三、步驟二:因子取捨、因子合成
對於相關性較高的因子集合,可以採取兩種方式處理:
(1)因子取捨
根據因子本身的ICIR值、收益率、換手率、Sharpe 比率,挑選某維度下最有效的因子進行保留,刪除其他因子。
(2)因子合成
對因子集合中的因子進行合成,截面上儘可能多的保留有效信息
$$$ F = w1 * f1 + w2f2+...+wnfn,F為最終的合成因子,f為需要進行合成的因子 $$$
假設當前有3個待處理的因子矩陣:
synthesis = pd.concat([a,b,c],axis = 1)
synthesis
a b c
BTC.BN 0.184865 -0.013253 -0.001557
ETH.BN 0.185691 0.022708 0.031793
BNB.BN 0.242072 -0.180952 -0.067430
LTC.BN 0.275923 -0.125712 -0.049596
AAVE.BN 0.204443 -0.000819 -0.006550
... ... ... ...
SOC.BN 0.231638 -0.095946 -0.049495
AVAX.BN 0.204714 -0.079707 -0.041806
DAO.BN 0.194990 0.022095 -0.011764
ETC.BN 0.184236 -0.021909 -0.013325
TRX.BN 0.175118 -0.055077 -0.039513
2.1 等權加權
各因子權重相等$$( w = 1/因子個數 )$$,綜合因子=各因子值加總求平均。
Eg.動量類因子,一個月收益率、兩個月收益率、三個月收益率、六個月收益率、十二個月收益率,這六個因子的因子載荷各佔1/6的權重,合成新的動量因子載荷,然後再重新進行標準化處理。
synthesis1 = synthesis.mean(axis=1) # 按行求均值
2.2 歷史IC加權、歷史ICIR、歷史收益加權
用回測期的IC值(ICIR值、歷史收益值)對因子進行加權。過去有很多期,每一期都有一個IC值,所以用它們的均值作為因子的權重。通常使用回測期IC的均值(算數平均值)作為權重。
# 權重歸一化(後文中的因子加權方式也基本都需要進行權重歸一化)
w_IC = ic.mean() / ic.mean().sum()
w_ICIR = icir.mean() / icir.mean().sum()
w_Ret = Return.mean() / Return.mean().sum()
synthesis2 = (synthesis * w_IC).sum(axis=1)
synthesis2 = (synthesis * w_ICIR).sum(axis=1)
synthesis2 = (synthesis * w_Ret).sum(axis=1)
2.3歷史IC半衰加權、歷史ICIR半衰加權
2.1與2.2都是計算算數平均值,回測期的每一次IC、ICIR對於因子的作用被默認為相同。
但現實中,回測期的每一期對於當期的影響程度不完全相同,存在時間上的衰減。越接近當前期的時期,影響越大,越遠影響越小。在此原理,求IC權重前首先定義一個半衰權重,距離當期越近的權重值越大、越遠權重越小。
半衰權重數學推導:
# 半衰權重
def Decay(H,T):
t = np.arange(T+1)[1:]
wt = 2**((t-T-1)/H) #半衰權重
decay = wt/wt.sum() #歸一化
return decay
# 歷史IC半衰加權
w_bs = Decay(6,12) # 假設T=12,H=6
ic_bs = ic.mul(w_bs,axis=0)
w = ic_bs.mean()/ic.mean().sum()
synthesis3 = (synthesis * w).sum(axis=1)
# 歷史ICIR半衰加權
# 歷史ICIR半衰加權在歷史IC半衰加權的基礎上,除以IC值的標準差。
w_bs = bs(6,12)
ic_bs = ic.mul(w_bs,axis=0)
ir_bs = ic_bs.mean()/ic.std()
w = ir_bs.mean()/ir_bs.mean().sum()
synthesis3 = (synthesis * w).sum(axis=1)
2.4 最大化ICIR加權
通過求解方程,計算最優因子權重w使得ICIR最大化
協方差矩陣的估計問題:協方差矩陣用於衡量不同資產之間的關聯性。統計學中常以樣本協方差矩陣代替總體協方差矩陣,但在樣本量不足時,樣本協方差矩陣與總體協方差矩陣的差異會很大。所以有人提出了壓縮估計的方法,原理是使估計協方差矩陣與實際協方差矩陣之間的均方誤差最小
方式:
1.樣本協方差矩陣
# 最大化ICIR加權(樣本協方差)
ic_cov = np.array(ic.cov())
inv_ic_cov = np.linalg.inv(ic_cov)
ic_vector = np.mat(ic.mean())
w = inv_ic_cov * ic_vector.T
w = w / w.sum()
synthesis4 = (synthesis * pd.DataFrame(w,index=synthesis.columns)[0]).sum(axis=1)
2.Ledoit-Wolf收縮:引入一個縮小系數,將原始的協方差矩陣與單位矩陣進行混合,以減少噪音的影響。
# 最大化ICIR加權(Ledoit-Wolf壓縮估計協方差)
from sklearn.covariance import LedoitWolf
model=LedoitWolf()
model.fit(ic)
ic_cov_lw = model.covariance_
inv_ic_cov = np.linalg.inv(ic_cov_lw)
ic_vector = np.mat(ic.mean())
w = inv_ic_cov*ic_vector.T
w = w/w.sum()
synthesis4 = (synthesis * pd.DataFrame(w,index=synthesis.columns)[0]).sum(axis=1)
3.Oracle近似收縮:對Ledoit-Wolf收縮的改進,目標是通過對協方差矩陣進行調整,從而在樣本大小較小的情況下更準確地估計真實的協方差矩陣。(編程實現與Ledoit-Wolf收縮同理)
2.5 主成分分析PCA
主成分分析(Principal Component Analysis,PCA)是一種用於降維和提取數據主要特徵的統計方法。其目標是通過線性變換,將原始數據映射到一個新的座標系,使得數據在新座標系下的方差最大化。
具體而言,PCA首先找到數據中的主成分,也就是數據中方差最大的方向。然後,它找到與第一個主成分正交(無關)且具有最大方差的第二個主成分。這個過程一直重複,直到找到數據中所有的主成分。
# 主成分分析(PCA)
from sklearn.decomposition import PCA
model1 = PCA(n_components=1)
model1.fit(f)
w=model1.components_
w=w/w.sum()
weighted_factor=(f*pd.DataFrame(w,columns=f.columns).iloc[0]).sum(axis=1)
關於LUCIDA & FALCON
Lucida (https://www.lucida.fund/ )是行業領先的量化對沖基金,在2018年4月進入Crypto市場,主要交易CTA / 統計套利 / 期權波動率套利等策略,現管理規模3000萬美元。
Falcon (https://falcon.lucida.fund /)是新一代的Web3投資基礎設施,它基於多因子模型,幫助用戶“選”、“買”、“管”、“賣”加密資產。Falcon在2022年6月由Lucida所孵化。
更多內容可訪問 https://linktr.ee/lucida_and_falcon
往期文章
-
From Tech Breakthroughs to Market Boom: Understanding the Link in the Crypto Bull Market
-
Development as the Driving Force: Understanding the Impact on Token Price Performance?
-
5 Million Rows of Data Recap: Investigating The Crypto Market’s 3-Year Bull Run @LUCIDA
-
LUCIDA × SnapFingers DAO:21 top public chains in three-year bull market recap