Step 1: Import Stock Prices

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

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

prices
## # A tibble: 6,290 × 8
##    symbol date        open  high   low close    volume adjusted
##    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>     <dbl>    <dbl>
##  1 SPY    2012-01-03  128.  128.  127.  128. 193697900     98.8
##  2 SPY    2012-01-04  127.  128.  127.  128. 127186500     99.0
##  3 SPY    2012-01-05  127.  128.  126.  128. 173895000     99.2
##  4 SPY    2012-01-06  128.  128.  127.  128. 148050000     99.0
##  5 SPY    2012-01-09  128   128.  127.  128.  99530200     99.2
##  6 SPY    2012-01-10  129.  130.  129.  129. 115282000    100. 
##  7 SPY    2012-01-11  129.  129.  129.  129. 111540700    100. 
##  8 SPY    2012-01-12  130.  130.  129.  130. 118983700    100. 
##  9 SPY    2012-01-13  129.  129.  128.  129. 179836200     99.9
## 10 SPY    2012-01-17  130.  130.  129.  129. 132209200    100. 
## # ℹ 6,280 more rows

Step 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) %>%          # drop the first observation per stock (0% return with no prior month)
  ungroup() %>%
  set_names(c("asset", "date", "returns"))

asset_returns_tbl
## # A tibble: 295 × 3
##    asset date            returns
##    <chr> <date>            <dbl>
##  1 AGG   2012-02-29 -0.000136   
##  2 AGG   2012-03-30 -0.00575    
##  3 AGG   2012-04-30  0.00902    
##  4 AGG   2012-05-31  0.0107     
##  5 AGG   2012-06-29 -0.000197   
##  6 AGG   2012-07-31  0.0135     
##  7 AGG   2012-08-31  0.000000501
##  8 AGG   2012-09-28  0.00266    
##  9 AGG   2012-10-31 -0.000472   
## 10 AGG   2012-11-30  0.00270    
## # ℹ 285 more rows

Step 3: Assign a Weight to Each Asset

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

w_tbl
## # A tibble: 5 × 2
##   asset weights
##   <chr>   <dbl>
## 1 AGG      0.25
## 2 EEM      0.25
## 3 EFA      0.2 
## 4 IJS      0.2 
## 5 SPY      0.1

Step 4: Build a Portfolio

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.
portfolio_returns_tbl
## # A tibble: 59 × 2
##    date         returns
##    <date>         <dbl>
##  1 2012-02-29  0.0299  
##  2 2012-03-30  0.000374
##  3 2012-04-30 -0.0108  
##  4 2012-05-31 -0.0703  
##  5 2012-06-29  0.0387  
##  6 2012-07-31  0.00328 
##  7 2012-08-31  0.0178  
##  8 2012-09-28  0.0274  
##  9 2012-10-31 -0.00483 
## 10 2012-11-30  0.0139  
## # ℹ 49 more rows

Step 5: Scatter Plot

portfolio_returns_tbl %>%
  ggplot(aes(x = date, y = returns)) +
  geom_point(color = "cornflowerblue") +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
  labs(title = "Portfolio Returns Scatter Plot", y = "Monthly Returns", x = "") +
  theme_tq()

Step 6: Histogram

portfolio_returns_tbl %>%
  ggplot(aes(x = returns)) +
  geom_histogram(binwidth = 0.005, fill = "cornflowerblue") +
  labs(title = "Portfolio Returns Distribution", x = "Returns", y = "Count") +
  theme_tq()

Step 7: Histogram and Density Plot

portfolio_returns_tbl %>%
  ggplot(aes(x = returns)) +
  geom_histogram(binwidth = 0.01, fill = "cornflowerblue") +
  geom_density() +
  scale_x_continuous(labels = scales::percent_format()) +
  labs(title = "Portfolio Historical Returns: Histogram and Density", x = "Returns", y = "Distribution") +
  theme_tq()