使用 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]
我正在寻找一种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]