我正在寻找一种高效/快速的方法,用多维numpy数组计算几个weithings/投资组合的波动率/标准差
我有一个多维核协方差数组,即形状为260,5,5的cov_3d
对于260个案例中的每一个,我有5个资产的10个权重,即形状为260,10,5的权重
利用numpy-Einstein求和,我可以计算260s10x10协方差,并提取对角矩阵。
因为,我只需要对角矩阵,一个更快、更有效的方式应该存在,这样我就省去了上下矩阵的计算。

import numpy as np

# observations just for covariance matrix
observations_3d = np.random.normal(size=(260,5,200))

#260 covariance matrix for 5 assets
cov_3d = np.einsum('nij,njk->nik', observations_3d, observations_3d.transpose([0,2,1]))/(200-1)

#for each 260 cases, 10 weightings of the 5 assets
weights_3d  = np.random.uniform(size=(260,10,5))

print(weights_3d.shape) #260x10x5

print(cov_3d.shape) #260x5x5

#aim: calculate standard deviation/volatility of the 10 weightings/portfolios for each of the 260 cases

#now, its gets ugly
wCovw_3d = np.einsum('nij,njk->nik',weights_3d,  np.einsum('nij,njk->nik', cov_3d, weights_3d.transpose([0,2,1])))

print (wCovw_3d.shape) #260x10x10

std_3d = np.diagonal(wCovw_3d,axis1=1,axis2=2)**.5

python - 使用numpy多维数组计算多个投资组合的标准差/波动率的有效方法-LMLPHP
输出应为v,T=1,…,260和P=1,…,10的元素如上所述

最佳答案

我们可以直接去那里-

std_3d = np.einsum('nij,njl,nil->ni',weights_3d, cov_3d, weights_3d)

导致的进展是-
从-
wCovw_3d = np.einsum('nij,njk->nik',weights_3d,  np.einsum('nij,njk->nik', cov_3d, weights_3d.transpose([0,2,1])))

简化转置部分-
wCovw_3d = np.einsum('nij,njk->nik',weights_3d,  np.einsum('nij,nkj->nik', cov_3d, weights_3d))

把这个带到一个电话里-
wCovw_3d = np.einsum('nij,njl,nkl->nik',weights_3d, cov_3d, weights_3d)

因为我们对最终输出的对角线很感兴趣,所以我们可以将对角线字符串(i和k)等价,从而得到最终表达式-
std_3d = np.einsum('nij,njl,nil->ni',weights_3d, cov_3d, weights_3d)

别忘了在结尾加上那一部分。
或者,使用**.5-
p1 = np.matmul(weights_3d,cov_3d)
std_3d_out = np.matmul(p1[...,None,:],weights_3d[...,None])[...,0,0]

在Python 3.x上使用等效的@operator-
((weights_3d@cov_3d)[...,None,:]@weights_3d[...,None])[...,0,0]

09-15 18:48