# Load packages

# Core
library(tidyverse)
library(tidyquant)

Goal

Collect individual returns into a portfolio by assigning a weight to each stock

five stocks: “SPY”, “EFA”, “IJS”, “EEM”, “AGG”

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

1 Import stock prices

symbols <- c("NFLX", "MSFT", "NVDA", "AAPL", "SPY")
prices <- tq_get(x = symbols,
                 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     = "monthly",
                  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" "MSFT" "NFLX" "NVDA" "SPY"
#weights
weight <- c(0.25,0.1,0.2,0.35,0.1)
weight
## [1] 0.25 0.10 0.20 0.35 0.10
w_tbl <- tibble(symbols,weight)
w_tbl
## # A tibble: 5 × 2
##   symbols weight
##   <chr>    <dbl>
## 1 AAPL      0.25
## 2 MSFT      0.1 
## 3 NFLX      0.2 
## 4 NVDA      0.35
## 5 SPY       0.1

4 Build a portfolio

#?tq_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: 60 × 2
##    date       returns
##    <date>       <dbl>
##  1 2013-01-31  0.0847
##  2 2013-02-28  0.0362
##  3 2013-03-28  0.0133
##  4 2013-04-30  0.0678
##  5 2013-05-31  0.0422
##  6 2013-06-28 -0.0583
##  7 2013-07-31  0.0691
##  8 2013-08-30  0.0617
##  9 2013-09-30  0.0331
## 10 2013-10-31  0.0337
## # ℹ 50 more rows

5 Calculate Kurtosis

portfolio_kurt <- portfolio_returns_tbl %>%
    tq_performance(Ra = returns, 
                   performance_fun = table.Stats) %>%
    select(Kurtosis) 
portfolio_kurt
## # A tibble: 1 × 1
##   Kurtosis
##      <dbl>
## 1   -0.359

6 Plot

Returns Distribution

portfolio_returns_tbl %>%
    
    ggplot(aes(x=returns)) +
    geom_histogram()

Expected Return Vs Downside Risk

#Transform Data

mean_kurt_tbl <- asset_returns_tbl %>%
    
    group_by(asset) %>%
    summarise(mean=mean(returns),
    kurt=kurtosis(returns)) %>%
    ungroup() %>%

add_row(portfolio_returns_tbl %>%
    summarise(mean=mean(returns),
    kurt=kurtosis(returns)) %>%
    
    mutate(asset = "portfolio"))
#plot
mean_kurt_tbl %>%
    ggplot(aes(x = kurt, y = mean)) +
    geom_point() +
    ggrepel::geom_label_repel(aes(label = asset, color = asset)) +
    theme(legend.position="none") +
    scale_y_continuous(labels = scales::percent_format(accuracy = 0.1)) +
    
    labs(x = "Kurtosis",
         y = "Expected Returns")

Rolling 24 Month Kurtosis

window = 24
rolling_kurt_tbl <- portfolio_returns_tbl %>%
    tq_mutate(select = returns,
              mutate_fun = rollapply,
              width = window,
              FUN = kurtosis, col_rename = "kurt") %>%
    na.omit() %>%
    select(-returns)


# Plot
rolling_kurt_tbl %>%
    ggplot(aes(x = date, y = kurt)) +
    geom_line(color = "cornflowerblue") +

    scale_y_continuous(breaks = seq(-1,4,0.5)) +
        scale_x_date(breaks = scales::pretty_breaks(n = 7)) +
        theme(plot.title = element_text(hjust = 0.5)) +
    
    labs(x = "Date", 
         y = "Kurtosis",
         title = paste0("Rolling", window, "Month Kurtosis")) +
        
        annotate(geom = "text",
                 x = as.Date("2016-07-01"), y = 3,
                 size = 5,
                 label = "Downside risk skyrocketed near the end of 2017")

The kurtosis has increased slightly over the data set for this selected portfolio, however it has not increased anywhere near as much as the portfolio in code along 8. This small increase, and overall very low kurtosis stat, suggests this is a very low risk and predicable portfolio allocation. Most returns will occur near the mean and severe gains or losses are still unlikely. The potential downside risk has increased over the dataset, however it is still lower than many other investment options.