# Load packages
# Core
library(tidyverse)
library(tidyquant)
# Source function
# source("../Downloads/CodeAlong13_Ch11_shell.Rmd")
Revise the code below.
symbols <- c("AAPL", "MSFT", "INTC", "GOOG", "NVDA")
prices <- tq_get(x = symbols,
get = "stock.prices",
from = "2012-12-31",
to = "2017-12-31")
asset_returns_tbl <- prices %>%
group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = "monthly",
type = "log") %>%
slice(-1) %>%
ungroup() %>%
set_names(c("asset", "date", "returns"))
Revise the code for weights.
# symbols
symbols <- asset_returns_tbl %>% distinct(asset) %>% pull()
symbols
## [1] "AAPL" "GOOG" "INTC" "MSFT" "NVDA"
# weights
weights <- c(0.25, 0.25, 0.2, 0.2, 0.1)
weights
## [1] 0.25 0.25 0.20 0.20 0.10
w_tbl <- tibble(symbols, weights)
w_tbl
## # A tibble: 5 × 2
## symbols weights
## <chr> <dbl>
## 1 AAPL 0.25
## 2 GOOG 0.25
## 3 INTC 0.2
## 4 MSFT 0.2
## 5 NVDA 0.1
portfolio_returns_tbl <- asset_returns_tbl %>%
tq_portfolio(assets_col = asset,
returns_col = returns,
weights = w_tbl,
rebalance_on = "months",
col_rename = "returns")
portfolio_returns_tbl
## # A tibble: 60 × 2
## date returns
## <date> <dbl>
## 1 2013-01-31 -0.0129
## 2 2013-02-28 0.0168
## 3 2013-03-28 0.0146
## 4 2013-04-30 0.0641
## 5 2013-05-31 0.0414
## 6 2013-06-28 -0.0344
## 7 2013-07-31 0.0142
## 8 2013-08-30 0.0119
## 9 2013-09-30 0.0160
## 10 2013-10-31 0.0867
## # ℹ 50 more rows
# Get mean portfolio return
mean_port_return <- mean(portfolio_returns_tbl$returns)
mean_port_return
## [1] 0.02054497
# Get standard deviation of portfolio returns
stddev_port_return <- sd(portfolio_returns_tbl$returns)
stddev_port_return
## [1] 0.04355608
simulate_accumulation <- function(initial_value, N, mean_return, sd_return) {
# Add a dollar
simulated_returns_add_1 <- tibble(returns = c(initial_value, 1 + rnorm(N, mean_return, sd_return)))
# Calculate the cumulative growth of a dollar
simulated_growth <- simulated_returns_add_1 %>%
mutate(growth = accumulate(returns, function(x, y) x*y)) %>%
select(growth)
return(simulated_growth)
}
simulate_accumulation(initial_value = 100, N = 240, mean_return = 0.05, sd_return = 0.01) %>%
tail()
## # A tibble: 6 × 1
## growth
## <dbl>
## 1 10919590.
## 2 11681132.
## 3 12269415.
## 4 12639456.
## 5 13211020.
## 6 14060537.
# Create a vector of 1s as a starting point
sims <- 51
starts <- rep(100, sims) %>%
set_names (paste("sim", 1:sims))
starts
## sim 1 sim 2 sim 3 sim 4 sim 5 sim 6 sim 7 sim 8 sim 9 sim 10 sim 11
## 100 100 100 100 100 100 100 100 100 100 100
## sim 12 sim 13 sim 14 sim 15 sim 16 sim 17 sim 18 sim 19 sim 20 sim 21 sim 22
## 100 100 100 100 100 100 100 100 100 100 100
## sim 23 sim 24 sim 25 sim 26 sim 27 sim 28 sim 29 sim 30 sim 31 sim 32 sim 33
## 100 100 100 100 100 100 100 100 100 100 100
## sim 34 sim 35 sim 36 sim 37 sim 38 sim 39 sim 40 sim 41 sim 42 sim 43 sim 44
## 100 100 100 100 100 100 100 100 100 100 100
## sim 45 sim 46 sim 47 sim 48 sim 49 sim 50 sim 51
## 100 100 100 100 100 100 100
# Simulate
monte_carlo_sim_51 <- starts %>%
# Simulate
map_dfc(.x = .,
.f = ~simulate_accumulation(initial_value = .x,
N = 240,
mean_return = mean_port_return,
sd_return = stddev_port_return)) %>%
# Add column month
mutate (month = 1:nrow(.)) %>%
select(month, everything()) %>%
# Rearrange column names
set_names(c("month", names (starts))) %>%
# Transform to long form
pivot_longer(cols = -month, names_to = "sim", values_to = "growth")
monte_carlo_sim_51
## # A tibble: 12,291 × 3
## month sim growth
## <int> <chr> <dbl>
## 1 1 sim 1 100
## 2 1 sim 2 100
## 3 1 sim 3 100
## 4 1 sim 4 100
## 5 1 sim 5 100
## 6 1 sim 6 100
## 7 1 sim 7 100
## 8 1 sim 8 100
## 9 1 sim 9 100
## 10 1 sim 10 100
## # ℹ 12,281 more rows
# Find quantiles
monte_carlo_sim_51 %>%
group_by(sim) %>%
summarise(growth = last(growth)) %>%
ungroup() %>%
pull(growth) %>%
quantile(probs = c(0, 0.25, 0.5, 0.75, 1)) %>%
round(2)
## 0% 25% 50% 75% 100%
## 1807.33 4835.81 8099.68 15771.37 71000.22
Line Plot of Simulations with Max, Median, and Min
Line plot with max, median, and min
# Step 1: Summarize data into max, median, and min of last value
sim_summary <- monte_carlo_sim_51 %>%
group_by(sim) %>%
summarise(growth = last(growth)) %>%
ungroup() %>%
summarise(max = max(growth),
median = median(growth),
min = min(growth))
sim_summary
## # A tibble: 1 × 3
## max median min
## <dbl> <dbl> <dbl>
## 1 71000. 8100. 1807.
# Step 2: Plot
monte_carlo_sim_51 %>%
# Filter for max, median, and min sim
group_by(sim) %>%
filter(last(growth) == sim_summary$max |
last(growth) == sim_summary$median |
last(growth) == sim_summary$min) %>%
ungroup() %>%
# Plot
ggplot(aes(x = month, y = growth, color = sim)) +
geom_line()+
theme(legend.position = "none") +
theme(plot.title = element_text(hjust = 0.5)) +
theme(plot.subtitle = element_text(hjust = 0.5)) +
labs(title = "Simulating growth of $100 over 240 months",
subtitle = "Maximum, Median, and Minimum Simulation")
Based on the Monte Carlo simulation results, how much should you expect from your $100 investment after 20 years? What is the best-case scenario? What is the worst-case scenario? What are limitations of this simulation analysis?