蒙特卡洛模拟R代码生成的收益图出现直线异常求助
蒙特卡洛模拟投资组合收益出现直线异常问题
我刚接触蒙特卡洛模拟,用R写了基础代码模拟指定投资组合的收益,但部分模拟收益在图表里始终是直线。已经减少模拟次数方便观察,调整其他参数后问题依旧,其余输出符合随机特性。代码和效果图如下:
library(quantmod) library(ggplot2) maxDate<- "2000-01-01" tickers<-c("MSFT", "AAPL", "BRK-B") getSymbols(tickers, from=maxDate) Port.p<-na.omit(merge(Cl(AAPL),Cl(MSFT),Cl(`BRK-B`))) Port.r<-ROC(Port.p, type = "discrete")[-1,] stock_Price<- as.matrix(Port.p[,1:3]) stock_Returns <- as.matrix(Port.r[,1:3]) mc_rep = 50 # Number of Sims training_days = 200 portfolio_Weights = c(0.5,0.3,0.2) coVarMat = cov(stock_Returns) miu = colMeans(stock_Returns) Miu = matrix(rep(miu, training_days), nrow = 3) portfolio_Returns_m = matrix(0, training_days, mc_rep) set.seed(2000) for (i in 1:mc_rep) { Z = matrix ( rnorm( dim(stock_Returns)[2] * training_days ), ncol = training_days ) L = t( chol(coVarMat) ) daily_Returns = Miu + L %*% Z portfolio_Returns_200 = cumprod( portfolio_Weights %*% daily_Returns + 1 ) portfolio_Returns_m[,i] = portfolio_Returns_200; } x_axis = rep(1:training_days, mc_rep) y_axis = as.vector(portfolio_Returns_m-1) plot_data = data.frame(x_axis, y_axis) ggplot(data = plot_data, aes(x = x_axis, y = y_axis)) + geom_path(col = 'red', size = 0.1) + xlab('Days') + ylab('Portfolio Returns') + ggtitle('Simulated Portfolio Returns in 200 days')+ theme_bw() + theme(plot.title = element_text(hjust = 0.5))

问题根源
绘图时未对不同模拟路径进行分组,导致ggplot将所有模拟的点按x轴顺序直接连接,跨路径的连线形成了看似直线的异常效果,并非模拟结果本身是直线。
修正后的代码
library(quantmod) library(ggplot2) maxDate<- "2000-01-01" tickers<-c("MSFT", "AAPL", "BRK-B") getSymbols(tickers, from=maxDate) Port.p<-na.omit(merge(Cl(AAPL),Cl(MSFT),Cl(`BRK-B`))) Port.r<-ROC(Port.p, type = "discrete")[-1,] stock_Returns <- as.matrix(Port.r[,1:3]) mc_rep = 50 # Number of Sims training_days = 200 portfolio_Weights = c(0.5,0.3,0.2) coVarMat = cov(stock_Returns) miu = colMeans(stock_Returns) # 简化均值矩阵的创建逻辑 Miu = matrix(miu, nrow = 3, ncol = training_days) portfolio_Returns_m = matrix(0, training_days, mc_rep) set.seed(2000) for (i in 1:mc_rep) { Z = matrix(rnorm(3 * training_days), nrow = 3, ncol = training_days) L = t(chol(coVarMat)) daily_Returns = Miu + L %*% Z portfolio_Returns_200 = cumprod(portfolio_Weights %*% daily_Returns + 1) portfolio_Returns_m[,i] = portfolio_Returns_200; } # 关键修改:添加模拟路径分组变量 plot_data = data.frame( x_axis = rep(1:training_days, mc_rep), y_axis = as.vector(portfolio_Returns_m - 1), simulation = rep(1:mc_rep, each = training_days) # 标记每条路径所属的模拟次数 ) ggplot(data = plot_data, aes(x = x_axis, y = y_axis, group = simulation)) + geom_path(col = 'red', size = 0.1) + xlab('Days') + ylab('Portfolio Returns') + ggtitle('Simulated Portfolio Returns in 200 days')+ theme_bw() + theme(plot.title = element_text(hjust = 0.5))
修正说明
- 添加分组变量:在
plot_data中加入simulation列,标记每个点所属的模拟路径,确保ggplot为每条路径单独连线,避免跨路径连接。 - 简化均值矩阵创建:用
matrix(miu, nrow=3, ncol=training_days)替代原代码,逻辑更清晰。 - 优化代码注释:调整随机数矩阵的生成注释,提升代码可读性。
修改后所有模拟路径会独立绘制,不会再出现异常直线。
内容的提问来源于stack exchange,提问作者Quantmax
相关产品推荐
相关产品推荐

