【问题标题】:Portfolio simulation using Cholesky decomposition使用 Cholesky 分解的投资组合模拟
【发布时间】:2015-07-28 08:29:05
【问题描述】:

我对具有 4 种资产(债券、股票、股票、现货市场)的投资组合进行 MC 模拟 我使用每月步数,我的模拟范围是 10 年,即 120 步。我的最终目标是计算年度预期缺口,即获取投资组合回报中最差的 5%。

模拟似乎没问题 - 乍一看。然而,我的印象是,随着时间的推移,漂移在整个过程中占主导地位,所以我预期的短缺对长期而言甚至是积极的。当我增加股权权重时,预期的缺口最终也会减少。当我将每种资产的预期回报设置为零时也是如此,因此增加的风险应该会拉低预期的缺口。 我预计我的代码中有一个错误,但看不到它。任何建议都非常感谢!

#maturity in years
maturity <- 10
#Using monthly steps
nsteps <- maturity*12
dt <-  maturity / nsteps
#number of assets
nAssets = 4
#number of simulations
nTrails = 10000

#expected return p.a. for each asset, stored in vector BM.mu
BM.mu <- rep(NA,nAssets)
BM.mu[1] <- 0.0072
BM.mu[2] <- 0.0365
BM.mu[3] <- 0.04702
BM.mu[4] <- 0.0005

#defining variable size
simulated.Returns   <- array(NA,    dim = c(nsteps+1, nTrails, nAssets))
cumulative.PortReturns  <- matrix(rep(NA,nsteps*nTrails), nrow = nsteps, ncol = nTrails)
ES  <- rep(NA, maturity)

#defining my monthly correlation and covariance matrix
corr_matrix <- matrix(c(1.000000000, -0.05081574, -0.07697585,  0.0051,
            -0.050815743,  1.00000000,  0.80997805, -0.3540,
            -0.076975850,  0.80997805,  1.00000000, -0.3130,
            0.005095699, -0.35365332, -0.31278506,  1.0000), nrow = 4, ncol = 4)

cov_matrix <- matrix(c(1.44e-04, -2.20e-05, -3.86e-05,  8.44e-08,
            -2.20e-05,  1.30e-03,  1.22e-03, -1.76e-05,
            -3.86e-05,  1.22e-03,  1.75e-03, -1.81e-05,
            8.44e-08, -1.76e-05, -1.81e-05,  1.90e-06), nrow = 4, ncol = 4)

#defining my portfolio weights
port.weights <- c(0.72, 0.07, 0.07, 0.14)

#performing cholesky decomposition
R <- (chol(corr_matrix))

#generating standard-normal, random variables
x <- array(rnorm(nsteps*nTrails*nAssets), c(nsteps*nTrails,nAssets))

#generating correlated standard-normal, random variables
ep <- x %*% R

#defining the drift 
drift <- BM.mu - 0.5 * diag(cov_matrix) 

#generating asset paths
temp = array(exp(as.vector(drift %*% t(dt)) + t(ep *sqrt(diag(cov_matrix)))), c(nAssets,nsteps,nTrails))

for(i in 2:nsteps) temp[,i,] = temp[,i,] * temp[,(i-1),] 

#changing dimension of the array temp from dim(nAssets, nsteps, nTrails) to dim(nsteps, nAssets, nTrails)
simulated.Returns <- aperm(temp,c(2,1,3))

#computing portfolio returns for each simulation (nTrails). To do this, each step is weighted with "port.weights"
#Since I generate continuous returns, I first transform them into discrete, multiply with weights and then transform back into continuous.
for (z in 1:nTrails) {
for (i in 1:nsteps) cumulative.PortReturns[i,z] = log(1+((exp(simulated.Returns[i,,z]-1)-1) %*% port.weights))
}

#Finally I compute the monthly expected shortfall (5%-level) by taking the average of the 5% worst portfolio yields
#I do steps of 12 as I calculate the ES at the end of each year
z = 0
for (i in seq(12, nsteps, by = 12 )) {
z = z + 1 
ES[z]   <- mean(sort(cumulative.PortReturns[i,]) [1:(0.05*nTrails)])
}

#plotting a sample of simulated portfolio returns
#library(QRM)
plot(as.timeSeries(cumulative.PortReturns[,1:100]), plot.type = 'single')

【问题讨论】:

  • 与您的预期相比,我不确定您的输出的影响,但协方差矩阵(以及相关矩阵)在定义上必须是对称的。上面代码中的corr_matrix 不是对称的。
  • 你能set.seed 并显示ES 的输出和评论吗?目前尚不清楚您所看到的确切输出或可疑输出的原因。
  • 我认为相关正态变量的生成不是问题,但请注意 R 提供了cov2cor,因此您实际上只需要指定协方差矩阵。库MASS 中的mvrnorm 也被广泛用于生成相关随机变量。

标签: r montecarlo


【解决方案1】:

根据您的 cmets,您已将 BM.mu 定义为每项资产的年度预期回报。但是,您正在使用每月而不是每年的步骤来模拟每个示例路径。然后需要通过将 BM.mu 缩放到相应的预期每月回报来将其纳入您的 drift 变量:

#defining the drift
drift <- BM.mu/12 - 0.5 * diag(cov_matrix)

如果没有这个,您将使用 annual 预期返回值和 monthly 协方差矩阵计算 drift 值。这会导致比您预期的更大的漂移,这会影响您看到的结果。

【讨论】:

  • 我相信这就是drift 乘以dt=1/12 的原因,但是是的,协方差需要以年化术语表示,如果是,则缺少sqrt(dt)
  • 感谢到目前为止的 cmets。我使用每月数据来计算协方差矩阵。所以我认为“缩小”协方差是没有必要的。我还更改了代码并仅使用协方差矩阵。现在,预期的短缺数字似乎是有道理的,即当将权重转移到风险较高的资产时,ES 会增加。谢谢你的提示!我稍后会更新我的代码。但是,我的漂移(10 年末的预期投资组合价值)仍然太高。上述投资组合的年回报率为 1.11%,但我的值为 18%
  • 我相信漂移必须是:漂移
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-18
  • 2016-09-12
  • 2013-02-12
  • 1970-01-01
  • 1970-01-01
  • 2011-11-16
  • 2021-12-18
相关资源
最近更新 更多