# Load packages

# Core
library(tidyverse)
library(tidyquant)

Goal

Visualize expected returns and risk to make it easier to compare the performance of multiple assets and portfolios.

Choose your stocks.

from 2012-12-31 to 2017-12-31

1 Import stock prices

symbols <- c("NVDA", "INTC", "GOOG", "AMD", "AAPL")
prices <- tq_get(x = symbols, 
                 get = "stock.prices",
                 from = "2012-12-31",
                 to   = "2017-12-31") 

2 Convert prices to returns

asset_returns_tbl <- prices %>%

    
    group_by(symbol) %>%

    tq_transmute(select     = adjusted, 
                 mutate_fun = periodReturn, 
                 period     = "quarterly",
                 type       = "log") %>%
    slice(-1) %>%
    
    ungroup() %>%

    set_names(c("asset", "date", "returns"))


## 3 Assign a weight to each asset
# symbols
symbols <- asset_returns_tbl %>% distinct(asset) %>% pull()
symbols
## [1] "AAPL" "AMD"  "GOOG" "INTC" "NVDA"
## [1] "NVDA" "INTC" "GOOG" "AMD" "AAPL" 
# weights
weights <- c(0.20, 0.15, 0.15, 0.30, 0.20)
weights
## [1] 0.20 0.15 0.15 0.30 0.20
## [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.2 
## 2 AMD        0.15
## 3 GOOG       0.15
## 4 INTC       0.3 
## 5 NVDA       0.2

4 Build a portfolio

portfolio_returns_tbl <- asset_returns_tbl %>%
    
    tq_portfolio(assets_col     = asset,
                  returns_col  = returns,
                  weights      = w_tbl, 
                  rebalance_on = "quarters")

portfolio_returns_tbl 
## # A tibble: 20 × 2
##    date       portfolio.returns
##    <date>                 <dbl>
##  1 2013-03-28          0.0216  
##  2 2013-06-28          0.118   
##  3 2013-09-30          0.0349  
##  4 2013-12-31          0.120   
##  5 2014-03-31          0.0212  
##  6 2014-06-30          0.115   
##  7 2014-09-30          0.0245  
##  8 2014-12-31          0.000410
##  9 2015-03-31         -0.00182 
## 10 2015-06-30         -0.0346  
## 11 2015-09-30         -0.0101  
## 12 2015-12-31          0.203   
## 13 2016-03-31          0.00429 
## 14 2016-06-30          0.115   
## 15 2016-09-30          0.217   
## 16 2016-12-30          0.158   
## 17 2017-03-31          0.0969  
## 18 2017-06-30          0.0310  
## 19 2017-09-29          0.107   
## 20 2017-12-29          0.0757

5 Calculate Standard Deviation

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

portfolio_sd_tidyquant_builtin_percent
## # A tibble: 1 × 2
##    Stdev  tq_sd
##    <dbl>  <dbl>
## 1 0.0722 0.0722
# Mean of portfolio returns
portfolio_mean_tidyquant_builtin_percent <- 
mean(portfolio_returns_tbl$portfolio.returns)
portfolio_mean_tidyquant_builtin_percent 
## [1] 0.07085562

6 Plot

# Expected Returns vs Risk
sd_mean_tbl <- asset_returns_tbl %>%
    
    group_by(asset) %>%
    tq_performance(Ra = returns,
                   performance_fun = table.Stats) %>%
    select(Mean = ArithmeticMean, Stdev) %>%
    ungroup() %>%

    # Add portfolio sd
    add_row(tibble(asset = "Portfolio", 
                   Mean = portfolio_mean_tidyquant_builtin_percent,
                   Stdev = portfolio_sd_tidyquant_builtin_percent$tq_sd))

sd_mean_tbl
## # A tibble: 6 × 3
##   asset       Mean  Stdev
##   <chr>      <dbl>  <dbl>
## 1 AAPL      0.045  0.119 
## 2 AMD       0.0727 0.274 
## 3 GOOG      0.0544 0.0905
## 4 INTC      0.0483 0.0948
## 5 NVDA      0.141  0.134 
## 6 Portfolio 0.0709 0.0722
sd_mean_tbl %>%
    ggplot(aes(x = Stdev, y = Mean, color = asset)) +
    geom_point() +
      geom_text(aes(label = asset),
            vjust = 1.5,
            hjust = 0.5,
            size  = 4)  

## 24 Months Rolling Volitlity

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

rolling_sd_tbl %>% 
   ggplot(aes(x = date, y = rolling_sd)) +
    geom_line(color = "cornflowerblue") +
    
    # Formatting
    scale_y_continuous(labels = scales::percent_format()) +
    
   # Labeling
    labs(x = NULL,
         y = NULL,
         title = " 8-Quarter Rolling Volatility") +
    theme(plot.title = element_text(hjust = 0.5))