Steps 1-4: Rebuild the Portfolio (from Code Along 5)

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

prices <- tq_get(
  x    = symbols,
  get  = "stock.prices",
  from = "2012-01-01",
  to   = "2017-01-01"
)

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

symbols_vec <- asset_returns_tbl %>%
  distinct(asset) %>%
  pull()

weights <- c(0.25, 0.25, 0.20, 0.20, 0.10)

w_tbl <- tibble(symbols_vec, weights) %>%
  set_names(c("asset", "weights"))

portfolio_returns_tbl <- asset_returns_tbl %>%
  tq_portfolio(
    assets_col   = asset,
    returns_col  = returns,
    weights      = w_tbl,
    col_rename   = "returns",
    rebalance_on = "months"
  )
## Warning in check_weights(weights, assets_col, map, x): Sum of weights does not
## equal 1.

Step 5: Calculate Standard Deviation

portfolio_sd_tbl <- portfolio_returns_tbl %>%
  tq_performance(Ra = returns, performance_fun = table.Stats) %>%
  select(Stdev) %>%
  mutate(tq_sd = round(Stdev, 4) * 100) %>%
  select(tq_sd)

portfolio_sd_tbl
## # A tibble: 1 × 1
##   tq_sd
##   <dbl>
## 1  2.64

Step 6: Scatter Plot of Expected Return vs. Risk

asset_sd_mean_tbl <- asset_returns_tbl %>%
  tq_performance(Ra = returns, performance_fun = table.Stats) %>%
  select(Stdev, ArithmeticMean) %>%
  set_names(c("stdev", "mean"))
## Warning in zoo(y, order.by = index(x), ...): some methods for "zoo" objects do
## not work if the index entries in 'order.by' are not unique
## Warning in zoo(rval, index(x)[i]): some methods for "zoo" objects do not work
## if the index entries in 'order.by' are not unique
# Note: tq_performance above should be grouped by asset so each stock gets
# its own row -- group_by(asset) before piping into tq_performance.
asset_sd_mean_tbl <- asset_returns_tbl %>%
  group_by(asset) %>%
  tq_performance(Ra = returns, performance_fun = table.Stats) %>%
  ungroup() %>%
  select(asset, Stdev, ArithmeticMean) %>%
  set_names(c("asset", "stdev", "mean"))

portfolio_mean <- mean(portfolio_returns_tbl$returns)

portfolio_row <- tibble(
  asset = "Portfolio",
  stdev = portfolio_sd_tbl$tq_sd / 100,
  mean  = portfolio_mean
)

sd_mean_table <- asset_sd_mean_tbl %>%
  add_row(portfolio_row) %>%
  mutate(
    stdev = stdev * 100,
    mean  = mean * 100
  )

sd_mean_table
## # A tibble: 6 × 3
##   asset     stdev   mean
##   <chr>     <dbl>  <dbl>
## 1 AGG        0.88  0.16 
## 2 EEM        4.49 -0.14 
## 3 EFA        3.8   0.43 
## 4 IJS        4.05  1.18 
## 5 SPY        2.97  1.08 
## 6 Portfolio  2.64  0.437
sd_mean_table %>%
  ggplot(aes(x = stdev, y = mean, color = asset)) +
  geom_point() +
  geom_text_repel(aes(label = asset)) +
  labs(
    title = "Expected Monthly Return vs. Risk",
    x     = "Standard Deviation (Risk)",
    y     = "Mean Return"
  ) +
  theme_tq() +
  theme(legend.position = "none")

Step 7: Line Plot of 24-Month Rolling Volatility

rolling_sd_table <- portfolio_returns_tbl %>%
  tq_mutate(
    select     = returns,
    mutate_fun = rollapply,
    width      = 24,
    FUN        = sd,
    col_rename = "rolling_sd"
  ) %>%
  na.omit() %>%
  select(date, rolling_sd)

rolling_sd_table
## # A tibble: 36 × 2
##    date       rolling_sd
##    <date>          <dbl>
##  1 2014-01-31     0.0274
##  2 2014-02-28     0.0276
##  3 2014-03-31     0.0276
##  4 2014-04-30     0.0273
##  5 2014-05-30     0.0217
##  6 2014-06-30     0.0210
##  7 2014-07-31     0.0215
##  8 2014-08-29     0.0216
##  9 2014-09-30     0.0238
## 10 2014-10-31     0.0239
## # ℹ 26 more rows
rolling_sd_table %>%
  ggplot(aes(x = date, y = rolling_sd)) +
  geom_line(color = "cornflowerblue") +
  scale_y_continuous(labels = scales::percent_format()) +
  labs(title = "24-Month Rolling Volatility", x = "", y = "") +
  theme_tq() +
  theme(plot.title = element_text(hjust = 0.5))