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