# Load packages

# Core
library(tidyverse)
library(tidyquant)

# Source function
source("../00_scripts/simulate_accumulation.R")

1 Import stock prices

Revise the code below.

symbols <- c("SPY", "EFA", "IJS", "EEM", "AGG")

prices <- tq_get(x    = symbols,
                 get  = "stock.prices",    
                 from = "2012-12-31",
                 to   = "2024-12-11")

2 Convert prices to returns

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"))

3 Assign a weight to each asset

Revise the code for weights.

# symbols
symbols <- asset_returns_tbl %>% distinct(asset) %>% pull()
symbols
## [1] "AGG" "EEM" "EFA" "IJS" "SPY"
# 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 AGG        0.25
## 2 EEM        0.25
## 3 EFA        0.2 
## 4 IJS        0.2 
## 5 SPY        0.1

4 Build a portfolio

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: 144 Ă— 2
##    date        returns
##    <date>        <dbl>
##  1 2013-01-31  0.0204 
##  2 2013-02-28 -0.00239
##  3 2013-03-28  0.0121 
##  4 2013-04-30  0.0174 
##  5 2013-05-31 -0.0128 
##  6 2013-06-28 -0.0247 
##  7 2013-07-31  0.0321 
##  8 2013-08-30 -0.0224 
##  9 2013-09-30  0.0511 
## 10 2013-10-31  0.0301 
## # ℹ 134 more rows

5 Simulating growth of a dollar

# Get mean portfolio return
mean_port_return <- mean(portfolio_returns_tbl$returns)
mean_port_return
## [1] 0.004529814
# Get standard deviation of portfolio returns
stddev_port_return <- sd(portfolio_returns_tbl$returns)
stddev_port_return
## [1] 0.03433387

6 Simulation function

No need

7 Running multiple simulations

# Create a vector of 1s as a starting point
sims <- 100
starts <- rep(100, sims) %>% 
    set_names(paste0("sim", 1:sims))

starts
##   sim1   sim2   sim3   sim4   sim5   sim6   sim7   sim8   sim9  sim10  sim11 
##    100    100    100    100    100    100    100    100    100    100    100 
##  sim12  sim13  sim14  sim15  sim16  sim17  sim18  sim19  sim20  sim21  sim22 
##    100    100    100    100    100    100    100    100    100    100    100 
##  sim23  sim24  sim25  sim26  sim27  sim28  sim29  sim30  sim31  sim32  sim33 
##    100    100    100    100    100    100    100    100    100    100    100 
##  sim34  sim35  sim36  sim37  sim38  sim39  sim40  sim41  sim42  sim43  sim44 
##    100    100    100    100    100    100    100    100    100    100    100 
##  sim45  sim46  sim47  sim48  sim49  sim50  sim51  sim52  sim53  sim54  sim55 
##    100    100    100    100    100    100    100    100    100    100    100 
##  sim56  sim57  sim58  sim59  sim60  sim61  sim62  sim63  sim64  sim65  sim66 
##    100    100    100    100    100    100    100    100    100    100    100 
##  sim67  sim68  sim69  sim70  sim71  sim72  sim73  sim74  sim75  sim76  sim77 
##    100    100    100    100    100    100    100    100    100    100    100 
##  sim78  sim79  sim80  sim81  sim82  sim83  sim84  sim85  sim86  sim87  sim88 
##    100    100    100    100    100    100    100    100    100    100    100 
##  sim89  sim90  sim91  sim92  sim93  sim94  sim95  sim96  sim97  sim98  sim99 
##    100    100    100    100    100    100    100    100    100    100    100 
## sim100 
##    100
# Simulate 
# For reproducable research
set.seed(1234)
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: 24,100 Ă— 3
##    month sim   growth
##    <int> <chr>  <dbl>
##  1     1 sim1     100
##  2     1 sim2     100
##  3     1 sim3     100
##  4     1 sim4     100
##  5     1 sim5     100
##  6     1 sim6     100
##  7     1 sim7     100
##  8     1 sim8     100
##  9     1 sim9     100
## 10     1 sim10    100
## # ℹ 24,090 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% 
##  48.09 168.93 258.11 390.43 943.96

8 Visualizing simulations with ggplot

Line Plot of Simulations with Max, Median, and Min

# Step 1 Summarise 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  944.   258.  48.1
# 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 $1 over 120 months", 
         subtitle = "Max, Median, and Minimum Simulation")

Based on the Monte Carlo simulation results, how much should you expect from your 100 dollar investment after 20 years? What is the best-case scenario? What is the worst-case scenario? What are limitations of this simulation analysis?

Based on the Monte Carlo simulation results you can expect anywhere from 50-900 on your investment, with 50 being the mininum value and 900 being the maximum value. For some reason similarly to the code along assignment, the graph wont display the median but we can assume it would be somewhere in between 50-900. Obviously you wouldn’t be very happy to lose 50 on your original investment but you would be very happy if you were to be on the max side of things and gain 900 dollars on your investment. There are some limitations to this simulation analysis, as it only shows you how your stock has grown over the last few years, and cannot correctly predict the future, however you can use this previous data to make an inference on whether you want to invest your money or not based on the returns on the graph.