使用 numpy 多维数组计算多个投资组合的标准偏差/波动率的有效方法

Efficient way to calculate standard deviation / volatility of multiple portfolios with numpy multidimensional arrays

我正在寻找一种efficient/fast方法来计算volatility/standard具有多维numpy数组weithings/portfolios的偏差

我有一个协方差的多维 numpy 数组,即 cov_3d 形状为 260,5,5 对于 260 个案例中的每一个,我有 5 个资产的 10 个权重,即 weights_3d 形状为 260,10,5

借助 numpy Einstein 求和,我可以计算 260s 10x10 协方差并提取对角矩阵。

因为我只需要对角矩阵,所以应该有一种更快、更有效的方法,这样我就可以省略上矩阵和下矩阵的计算。

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

输出应为 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))

把它带到一个 einsum 电话中 -

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 部分。


或者,np.matmul -

p1 = np.matmul(weights_3d,cov_3d)
std_3d_out = np.matmul(p1[...,None,:],weights_3d[...,None])[...,0,0]

在 Python 3.x -

上使用等效的 @ 运算符
((weights_3d@cov_3d)[...,None,:]@weights_3d[...,None])[...,0,0]