书接上回,关于《用多因子模型构建强大的加密资产投资组合》系列文章中,我们已经发布了四篇:《理论基础篇》、《数据预处理篇》、《因子有效性检验篇》、《大类因子分析:因子合成篇》。
在上一篇中,我们具体解释了因子共线性(因子之间相关性较高)的问题,在进行大类因子合成前,需要进行因子正交化来消除共线性。
通过因子正交化,重新调整原始因子的方向,使他们相互正交([fi,fj]=0,即两个向量相互垂直),本质是对原始因子在坐标轴上的旋转。这种旋转不改变因子之间的线性关系也不改变原本蕴含的信息,并且新因子之间的相关性为零(内积为零等价于相关性为零),因子对于收益的解释度保持不变。
一、因子正交化的数学推导
从多因子截面回归角度,建立因子正交化体系。
每个截面上可以获得全市场token在各个因子上的取值,N代表截面上全市场token数量,K表示因子的数量,fk=[f1k,f2k,...,fNk]′表示全市场token在第k个因子上的取值,并且已对每个因子进行了z-score归一化处理,即 fkˉ=0,∣∣fk∣∣=1。
FN×K=[f1,f2,...,fK]为截面上K个线性独立的因子列向量组成的矩阵,假设以上因子线性无关(相关性不为100%或-100%,正交化处理的理论基础)。
因子矩阵 FN×K=f11f21⋮fN1f12f22⋮fN2……⋱…f1Kf2K⋮fNK(1)
通过对Fmn线性变换,得到一个新的因子正交矩阵Fmn′=[f1k,f2k,……fnk]′ ,新矩阵的列向量相互正交,即任意两个新因子向量内积为零,∀i,j,i=j,[(f~i)′f~j]=0。
定义一个从 FN×K旋转到F~N×K的过渡矩阵 SK×K
F~N×K=FN×K⋅SK×K(2)
1.1 过度矩阵SK×K
以下开始求解过渡矩阵Skk,首先计算Fnk的协方差矩阵∑kk,则 Fnk 的重叠矩阵Mkk=(N−1)∑kk,即
重叠矩阵 MK×K=(f1)′(f1)(f2)′(f1)⋮(fK)′(f1)(f1)′(f2)(f2)′(f2)⋮(fK)′(f2)……⋱…(f1)′(fK)(f2)′(fK)⋮(fK)′(fK)(3)
旋转后的F~N×K是正交矩阵,根据正交矩阵的性质 AAT=I,则有
(F~N×K)′F~N×K=(FN×KSK×K)′FN×KSK×K=SK×K′FN×K′FN×KSK×K=SK×K′MK×KSK×K=IK×K(4)
所以,
SK×K′SK×K=MK×K−1(7)
满足该条件的 Skk 即为一个符合条件的过渡矩阵。上面公式的通解为:
SK×K=MK×K−1/2CK×K(8)
其中,CK×K 为任意正交矩阵
1.2对称矩阵MK×K−1/2
下面开始求解 M∗K×K−1/2,因为 M∗K×K 是对称矩阵,因此一定存在一个正定矩阵 UK×K 满足:
UK×K′MK×KUK×K=DK×K(9)
其中,
DK×K=λ10⋮00λ2⋮0……⋱…00⋮λK(10)
U∗K×K,D∗K×K 分别为 M∗K×K 的特征向量矩阵和特征根对角矩阵,并且 U∗K×K′=UK×K−1,∀k,λK>0。 由公式(13)可得
MK×KMK×K−1MK×K−1/2MK×K−1/2=UK×KDK×KUK×K′=UK×KDK×K−1UK×K′=UK×KDK×K−1/2IK×KDK×K−1/2UK×K′(11)
由于 M∗K×K−1/2 是对称矩阵,且 U∗K×KU∗K×K′=I∗K×K,可基于上式得到 MK×K−1/2 的一个特解为:
MK×K−1/2MK×K−1/2MK×K−1/2=UK×KDK×K−1/2UK×K′UK×KDK×K−1/2UK×K′=UK×KDK×K−1/2UK×K′(12)
其中
DK×K−1/2=1/λ10⋮001/λ2⋮0……⋱…00⋮1/λK(13)
将 MK×K−1/2 的解带入公式(6)可求的过渡矩阵:
SK×K=MK×K−1/2CK×K=UK×KDK×K−1/2UK×K′CK×K(14)
其中,CK×K 为任意正交矩阵。
根据公式(12),任何一种因子正交都可以转化为选择不同的正交矩阵 CK×K 对原始因子进行旋转。
1.3消除共线性主要用到3种正交方法
1.3.1 施密特正交
故,S∗K×K 为上三角矩阵,C∗K×K=U∗K×KD∗K×K−1/2U∗K×K′S∗K×K
1.3.2 规范正交
故,SK×K=UK×KDK×K−1/2 ,CK×K=UK×K
1.3.3 对称正交
故,SK×K=UK×KDK×K−1/2UK×K′,CK×K=IK×K
二、三种正交方法的具体实现
1.施密特正交
有一组线性无关的因子列向量 f1,f2,...,fK,可以逐步的构造出一组正交的向量组 f~1,f~2,...,f~K,正交后的向量为:
f~1f~2f~3…f~k=f1=f2−[f~1,f~1][f2,f~1]f~1=f3−[f~1,f~1][f3,f~1]f~1−[f~2,f~2][f3,f~2]f~2=…=fk−[f~1,f~1][fk,f~1]f~1−[f~2,f~2][fk,f~2]f~2−⋯−[f~k−1,f~k−1][fk,f~k−1]f~k−1(15)
并对 f~1,f~2,...,f~K 进行单位化后:
ek=∣∣f~k∣∣f~k,(k=1,2,…,k)(16)
经过以上处理,得到一组标准正交基。由于 e1,e2,…,eK 与 f1,f2,...,fK 等价,二者可以相互线性表示,即 ek是 f1,f2,...,fk 的线性组合,有 ek=β1kf1+β2kf2+...+βkkfk,因此对应于原矩阵 F∗K×K 的过渡矩阵S∗K×K 为一个上三角矩阵,形如:
SK×K=β110⋮0β12β22⋮0……⋱…β1Kβ2K⋮βKK(17)
其中 βkk=∣∣f~k∣∣1>0。基于公式(17),施密特正交选取的任意正交矩阵为:
CK×K=UK×KDK×K−1/2UK×K′SK×K(1)
施密特正交是一种顺序正交方法,因此需要确定因子正交的顺序,常见的正交顺序有固定顺序(不同截面上取同样的正交次序),以及动态顺序(在每个截面上根据一定规则确定其正交次序)。施密特正交法的优点是按同样顺序正交的因子有显式的对应关系,但是正交顺序没有统一的选择标准,正交后的表现可能受到正交顺序标准和窗口期参数的影响。
from sympy.matrices import Matrix, GramSchmidt
Schmidt = GramSchmidt(f.apply(lambda x: Matrix(x),axis=0),orthonormal=True)
f_Schmidt = pd.DataFrame(index=f.index,columns=f.columns)
for i in range(3):
f_Schmidt.iloc[:,i]=np.array(Schmidt[i])
res = f_Schmidt.astype(float)
2.规范正交
选取正交矩阵 CK×K=UK×K,则过渡矩阵为:
SK×K=UK×KDK×K−1/2UK×K′UK×K=UK×KDK×K−1/2(2)
其中 U∗K×K 为特征向量矩阵,用于对因子旋转,D∗K×K−1/2 为对角矩阵,用于对旋转后因子的缩放。此处的旋转与不做降维的PCA一致。
def Canonical(self):
overlapping_matrix = (time_tag_data.shape[1] - 1) * np.cov(time_tag_data.astype(float))
eigenvalue, eigenvector = np.linalg.eig(overlapping_matrix)
eigenvector = np.mat(eigenvector)
transition_matrix = np.dot(eigenvector, np.mat(np.diag(eigenvalue ** (-0.5))))
orthogonalization = np.dot(time_tag_data.T.values, transition_matrix)
orthogonalization_df = pd.DataFrame(orthogonalization.T,index = pd.MultiIndex.from_product([time_tag_data.index, [time_tag]]),columns=time_tag_data.columns)
self.factor_orthogonalization_data = self.factor_orthogonalization_data.append(orthogonalization_df)
3.对称正交
施密特正交由于在过去若干个截面上都取同样的因子正交顺序,因此正交后的因子和原始因子有显式的对应关系,而规范正交在每个截面上选取的主成分方向可能不一致,导致正交前后的因子没有稳定的对应关系。由此可见,正交后组合的效果,很大一部分取决于正交前后因子是否有稳定的对应关系。
对称正交尽可能的减少对原始因子矩阵的修改而得到一组正交基。这样能够最大程度地保持正交后因子和原因子的相似性。并且避免像施密特正交法中偏向正交顺序中靠前的因子。
选取正交矩阵 CK×K=IK×K,则过渡矩阵为:
SK×K=UK×KDK×K−1/2UK×K′(1)
对称正交的性质:
-
与施密特正交相比,对称正交不需要提供正交次序,对每个因子是平等看待的
-
在所有正交过渡矩阵中,对称正交后的矩阵和原始矩阵的相似性最大,即正交前后矩阵的距离最小。
def Symmetry(factors):
col_name = factors.columns
D, U = np.linalg.eig(np.dot(factors.T, factors))
U = np.mat(U)
d = np.diag(D**(-0.5))
S = U*d*U.T
F_hat = np.mat(factors)*S
factors_orthogonal = pd.DataFrame(F_hat, columns=col_name, index=factors.index)
return factors_orthogonal
res = Symmetry(f)
关于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
往期文章