例えば、現在5000万円を持っているとして、 A: 毎年250万円ずつ投資して20年かけて投資額(元本)を5000万円にする B: 半分の2500万を一括投資して運用 どちらのほうがリスクが少ないか?
リスクの測定として、20年間運用した後の総資産額についての期待標準偏差を比較する。 投資ポートフォリオの特性として、1年あたりのリターンが、年率期待リターンmu, 年率期待標準偏差 sigmaの正規分布に従うi.i.d系列とする。 ポートフォリオリターンをBootstrap法により繰り返し発生させて比較を行う。
運用後の総資産額は指数的な分布になることが予測されるため、対数変換した値を比較する。 また、最終資産額についての95%信頼区間(2.5パーセンタイル値, 97.5パーセンタイル値)も合わせて求める。
対数変換した後の期待値、SDおよびその比率も示す。
#ライブラリ読み込み
library(ggplot2)
library(ggsci)
Simulation <- function(mu, sigma, year, initialPrice){
# mu: 年率の期待リターン(算術平均リターン)
# sigma: 年率の期待標準偏差
# year: 投資する年数
# initialPrice: 開始時の資産額
# Parameters
N <- year
# Return Generation
yearlyReturn <- rnorm(N, mu, sigma) # 年率リターンを正規分布(N(mu, sigma))に従うi.i.d系列として発生
# 分割して投資する(A)
totalAssetA <- rep(0, N) # 総資産額の格納
cash <- rep(0, N) # キャッシュ格納用
investPrice <- rep(0, N) # 投資評価額の格納用
cash[1] <- initialPrice # はじめのcashを設定
contributeAmountA <- initialPrice/N # 1回あたり(毎年)の投資額
# N年分シミュレーション
for(i in 1:N){
# 年初に投資
investPrice[i] <- investPrice[i]+contributeAmountA
cash[i] <- cash[i] - contributeAmountA
# リターン計算
investPrice[i] <- investPrice[i]*(yearlyReturn[i]+1)
if(investPrice[i]<=0){investPrice[i] <- 0} # 0以下(破産)になったら0を代入
totalAssetA[i] <- investPrice[i] + cash[i]
if(i == N){break}
# 繰越
investPrice[i+1] <- investPrice[i]
cash[i+1] <- cash[i]
}
# 半分を一括投資して運用し続ける(B)
contributeAmountB <- initialPrice/2 # はじめに投資する額
investPrice <- rep(0, N) # 投資評価額の格納用
investPrice[1] <- contributeAmountB
for(i in 1:N){
investPrice[i] <- max(0, investPrice[i] * (1+yearlyReturn[i]))
if(i==N){break}
investPrice[i+1] <- investPrice[i]
}
totalAssetB <- investPrice[N] + (initialPrice - contributeAmountB)
return(c(totalAssetA[N], totalAssetB)) # A, Bの最終資産額を出力
}
Simulation(0.09, 0.2, 20, 5000) # mu=0.09, sigma=0.2としてシミュレーションした結果
## [1] 4614.643 6227.518
Bootstrap法による反復試行は、1組の(mu, sigma)あたり100,000回とする。
repeatN <- 100000 #1組のパラメータあたりの試行数
resultA <- rep(0, repeatN) # Aの最終資産額(対数変換後)格納用
resultB <- rep(0, repeatN) # Bの最終資産額(対数変換後)格納用
# 以下のmu, sigmaの総当りの組み合わせで検定を行う。
m <- c(0.03, 0.06, 0.09, 0.12, 0.15) # mu(vector)
s <- c(0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5) # sigma(vector)
# 結果の格納用
sd_ratio_df <- data.frame(matrix(rep(0, length(m) * length(s)), nrow=length(s)))
mean_ratio_df <- data.frame(matrix(rep(0, length(m) * length(s)), nrow=length(s)))
mean_A_df <- data.frame(matrix(rep(0, length(m) * length(s)), nrow=length(s)))
mean_B_df <- data.frame(matrix(rep(0, length(m) * length(s)), nrow=length(s)))
median_A_df <- data.frame(matrix(rep(0, length(m) * length(s)), nrow=length(s)))
median_B_df <- data.frame(matrix(rep(0, length(m) * length(s)), nrow=length(s)))
sd_A_df <- data.frame(matrix(rep(0, length(m) * length(s)), nrow=length(s)))
sd_B_df <- data.frame(matrix(rep(0, length(m) * length(s)), nrow=length(s)))
lCI_A_df <- data.frame(matrix(rep(0, length(m) * length(s)), nrow=length(s)))
uCI_A_df <- data.frame(matrix(rep(0, length(m) * length(s)), nrow=length(s)))
lCI_B_df <- data.frame(matrix(rep(0, length(m) * length(s)), nrow=length(s)))
uCI_B_df <- data.frame(matrix(rep(0, length(m) * length(s)), nrow=length(s)))
results <- data.frame(matrix(rep(NA, 4), nrow=1))[numeric(0), ]
colnames(results) <- c("method", "mu", "sigma", "value")
# ループ
for(k in 1:length(m)){ # muについてのループ
for(j in 1:length(s)){ # sigmaについてのループ
for(i in 1:repeatN){ # bootstrap
# 特定の(mu, sigma)についてのシミュレーション
res <- Simulation(m[k], s[j], 20, 50000000) # 1試行での結果(最終資産額)
resultA[i] <- log10(max(res[1],1)) # A: 積立投資
resultB[i] <- log10(max(res[2],1)) # B: 一括投資
}
# 結果(対数変換した最終総資産額の統計量を求める)
mean_A <- mean(resultA)
mean_B <- mean(resultB)
median_A <- median(resultA)
median_B <- median(resultB)
sd_A <- sd(resultA)
sd_B <- sd(resultB)
sd_ratio <- (sd_B/mean_B) / (sd_A/mean_A)
mean_ratio <- mean_B - mean_A
CI_A <- quantile(resultA, c(0.025, 0.975))
CI_B <- quantile(resultB, c(0.025, 0.975))
results <- rbind(results,
data.frame(method=rep("Dollar Cost",repeatN),
mu=rep(m[k], repeatN),
sigma=rep(s[j], repeatN),
value=resultA),
data.frame(method=rep("Bulk",repeatN),
mu=rep(m[k], repeatN),
sigma=rep(s[j], repeatN),
value=resultB))
# テーブルにまとめる
mean_A_df[j,k] <- mean_A
mean_B_df[j,k] <- mean_B
median_A_df[j,k] <- median_A
median_B_df[j,k] <- median_B
sd_A_df[j,k] <- sd_A
sd_B_df[j,k] <- sd_B
sd_ratio_df[j,k] <- sd_ratio
mean_ratio_df[j,k] <- mean_ratio
lCI_A_df[j,k] <- CI_A[1]
uCI_A_df[j,k] <- CI_A[2]
lCI_B_df[j,k] <- CI_B[1]
uCI_B_df[j,k] <- CI_B[2]
}
}
library(ggplot2)
library(ggsci)
# 箱ひげ図でそれぞれのsigmaについての中央値、四分位を示す。
plot_est_ci_bp <- function(results, sigma){
title = paste("Final wealth distribution after 20 years in sigma = ", sigma, sep="")
df_plot <- results[results$sigma==sigma,]
g <- ggplot(df_plot, aes(x=as.factor(mu), y=value, fill=method))+
geom_boxplot() +
scale_color_nejm() +
xlab("mu") + ylab("Wealth") +
labs(title=title) +
ylim(c(6,NA))
return(g)
}
plot_est_ci_bp(results, 0.05)
plot_est_ci_bp(results, 0.1)
plot_est_ci_bp(results, 0.2)
plot_est_ci_bp(results, 0.3)
## Warning: Removed 135 rows containing non-finite values (stat_boxplot).
plot_est_ci_bp(results, 0.4)
## Warning: Removed 2227 rows containing non-finite values (stat_boxplot).
plot_est_ci_bp(results, 0.5)
## Warning: Removed 9816 rows containing non-finite values (stat_boxplot).
library(ggplot2)
library(reshape2)
library(ggsci)
plot_result <- function(df, colname, rowname, ylabel, title_char){
colnames(df) <- colname
rownames(df) <- rowname
df <- stack(df)
df$sigma <- rep(s, length(m))
df$mu <- df$ind
g <- ggplot(df, aes(x=sigma, y=values, color=mu)) +
geom_line() +
scale_color_nejm() +
ylab(ylabel) +
labs(title=title_char)
return(g)
}
plot_result2 <- function(df1, df2, colname, rowname, ylabel, title_char){
colnames(df1) <- colname
rownames(df1) <- rowname
df1 <- stack(df1)
df1$sigma <- rep(s, length(m))
df1$mu <- df1$ind
df1$Method <- "Dollar Cost"
colnames(df2) <- colname
rownames(df2) <- rowname
df2 <- stack(df2)
df2$sigma <- rep(s, length(m))
df2$mu <- df2$ind
df2$Method <- "Bulk"
df <- rbind(df1, df2)
g <- ggplot(df, aes(x=sigma, y=values, color=mu, linetype=Method)) +
geom_line() +
scale_color_nejm() +
ylab(ylabel) +
labs(title=title_char)
return(g)
}
(g_sd <- plot_result(sd_ratio_df, m, s, "SD ratio: B/A", "SD ratio")) # meanで除した標準偏差の比率(B/A)
(g_mean <- plot_result(mean_ratio_df, m, s, "Mean ratio: B/A", "Mean ratio")) # 対数変換した総資産額のmeanの比率(B/A)
#(mean_A <- plot_result(mean_A_df, m, s, "Mean", "Mean of A (logged)")) # 対数化したA資産額のmean
#(mean_B <- plot_result(mean_B_df, m, s, "Mean", "Mean of B (logged)")) # 対数化したB資産額のmean
#(sd_A <- plot_result(sd_A_df, m, s, "SD", "StdDev of A (logged)")) # 対数化したA資産額の標準偏差
#(sd_B <- plot_result(sd_B_df, m, s, "SD", "StdDev of B (logged)")) # 対数化したB資産額の標準偏差
(plot_result2(mean_A_df, mean_B_df, m, s, "Wealth", "Mean Wealth (logged)"))
(plot_result2(sd_A_df, sd_B_df, m, s, "SD", "SD (logged)"))