Q1 Import stock prices of Netflix, Tesla and Amazon for the last 5 years.

# Load packages  
library(tidyquant)
library(tidyverse)

from <- today() - years(5)
stock_prices <- c("NFLX", "TSLA", "AMZN") %>%
    tq_get(get  = "stock.prices",
           from = from)
stock_prices
## # A tibble: 3,774 x 8
##    symbol date        open  high   low close   volume adjusted
##    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>    <dbl>    <dbl>
##  1 NFLX   2014-11-26  50.2  50.5  49.7  50.2 10063200     50.2
##  2 NFLX   2014-11-28  50.5  50.6  49.4  49.5  6702500     49.5
##  3 NFLX   2014-12-01  49.3  49.6  48.2  48.8 11964400     48.8
##  4 NFLX   2014-12-02  48.8  50.5  48.7  50.3 14271600     50.3
##  5 NFLX   2014-12-03  50.2  50.7  49.2  50.7 13819400     50.7
##  6 NFLX   2014-12-04  50.4  51.1  49.9  50.1 11853800     50.1
##  7 NFLX   2014-12-05  50.1  50.6  49.7  50.1  9930200     50.1
##  8 NFLX   2014-12-08  49.9  50.0  48.3  48.5 13621300     48.5
##  9 NFLX   2014-12-09  47.8  49.3  47.0  49.1 17976700     49.1
## 10 NFLX   2014-12-10  49.0  49.2  47.7  47.8 12644800     47.8
## # … with 3,764 more rows

Q2 Calculate monthly returns.

Hint: Use NASDAQ Compsite Index as baseline.

stock_returns_monthly <- stock_prices %>%
    group_by(symbol) %>%
    tq_transmute(select     = adjusted, 
                 mutate_fun = periodReturn, 
                 period     = "monthly", 
                 col_rename = "Ra")
stock_returns_monthly
## # A tibble: 183 x 3
## # Groups:   symbol [3]
##    symbol date             Ra
##    <chr>  <date>        <dbl>
##  1 NFLX   2014-11-28 -0.0130 
##  2 NFLX   2014-12-31 -0.0144 
##  3 NFLX   2015-01-30  0.293  
##  4 NFLX   2015-02-27  0.0749 
##  5 NFLX   2015-03-31 -0.123  
##  6 NFLX   2015-04-30  0.336  
##  7 NFLX   2015-05-29  0.121  
##  8 NFLX   2015-06-30  0.0527 
##  9 NFLX   2015-07-31  0.218  
## 10 NFLX   2015-08-31  0.00630
## # … with 173 more rows

baseline_returns_monthly <- "^IXIC" %>%
    tq_get(get  = "stock.prices",
           from <- today() - years(5)) %>%
    tq_transmute(select     = adjusted, 
                 mutate_fun = periodReturn, 
                 period     = "monthly", 
                 col_rename = "Rb")
baseline_returns_monthly
## # A tibble: 131 x 2
##    date            Rb
##    <date>       <dbl>
##  1 2009-01-30 -0.0954
##  2 2009-02-27 -0.0668
##  3 2009-03-31  0.109 
##  4 2009-04-30  0.123 
##  5 2009-05-29  0.0332
##  6 2009-06-30  0.0342
##  7 2009-07-31  0.0782
##  8 2009-08-31  0.0154
##  9 2009-09-30  0.0564
## 10 2009-10-30 -0.0364
## # … with 121 more rows

Q3 Aggregate.

Hint: Create 100 portfolios.

# scaling a single portfolio to num_port number 
num_port = 100

stock_returns_monthly_multi <- stock_returns_monthly %>%
    tq_repeat_df(n = num_port)
stock_returns_monthly_multi
## # A tibble: 18,300 x 4
## # Groups:   portfolio [100]
##    portfolio symbol date             Ra
##        <int> <chr>  <date>        <dbl>
##  1         1 NFLX   2014-11-28 -0.0130 
##  2         1 NFLX   2014-12-31 -0.0144 
##  3         1 NFLX   2015-01-30  0.293  
##  4         1 NFLX   2015-02-27  0.0749 
##  5         1 NFLX   2015-03-31 -0.123  
##  6         1 NFLX   2015-04-30  0.336  
##  7         1 NFLX   2015-05-29  0.121  
##  8         1 NFLX   2015-06-30  0.0527 
##  9         1 NFLX   2015-07-31  0.218  
## 10         1 NFLX   2015-08-31  0.00630
## # … with 18,290 more rows

# Create Vector of Weights
# not all symbols need to be specified. Any symbol not specified by default gets a weight of zero.
# The following is what I tried based on the info on the Web.
# https://stackoverflow.com/questions/5622608/choosing-n-numbers-with-fixed-sum
# n = number of stocks in the portfolio
# Choose n - 1 numbers between 0 and 1
# Sort them and calculate the distance between each number

# Create a data frame # of columns = # of stocks in the portfolio and # of rows = # of portfolio
# n = # of stocks in the portfolio
# Case of two portfolios with three stocks
num_stocks <- stock_returns_monthly %>%
  distinct(symbol) %>%
  n_distinct()
num_stocks
## [1] 3

# Initialize data frame
weights <- list()

# Set the seed of random numbers so that they can be reproduced
set.seed(06182019)

# Loop through the values 1 to number of portfolios, to generate weights for stocks in the portfolio
for(i in 1:num_port){
  # Generate n-1 number of random numbers b/t 0 and 1
  weights[[i]] = runif(num_stocks-1, 0, 1)
  # Add 0 and 1
  weights[[i]] = append(weights[[i]], c(0, 1))
  # Sort the random numbers
  weights[[i]] = sort(weights[[i]])
  # Calculate the differences b/t the random numbers
  weights[[i]] = diff(weights[[i]])
}
weights[[1]]
## [1] 0.06385721 0.32707606 0.60906672

# Convert the list to a vector
weights <- unlist(weights)
weights
##   [1] 0.0638572143 0.3270760642 0.6090667215 0.6674315634 0.0835250188
##   [6] 0.2490434179 0.9486860994 0.0501059340 0.0012079666 0.3082285074
##  [11] 0.3311331158 0.3606383768 0.1122350958 0.6053920568 0.2823728474
##  [16] 0.5903503322 0.2067945255 0.2028551423 0.2308615067 0.0173753274
##  [21] 0.7517631659 0.4117328513 0.0418477936 0.5464193551 0.3082213739
##  [26] 0.2995600218 0.3922186042 0.5221402226 0.1136128758 0.3642469016
##  [31] 0.0857777279 0.6071222641 0.3071000080 0.1944349897 0.0029123276
##  [36] 0.8026526826 0.1962747315 0.0904070712 0.7133181973 0.1588861502
##  [41] 0.1306861357 0.7104277140 0.8440541434 0.1414887353 0.0144571213
##  [46] 0.7966482679 0.0351519424 0.1681997897 0.1807254998 0.6042723870
##  [51] 0.2150021133 0.2389462919 0.5176046358 0.2434490724 0.3562180211
##  [56] 0.3205262697 0.3232557091 0.4174840255 0.1583388411 0.4241771335
##  [61] 0.1504051252 0.3887717656 0.4608231091 0.4359975604 0.2236178115
##  [66] 0.3403846282 0.2422919362 0.5420307070 0.2156773568 0.2298394081
##  [71] 0.4745642522 0.2955963397 0.6258799869 0.0470416916 0.3270783215
##  [76] 0.0375024606 0.5680024794 0.3944950600 0.0067017451 0.4451984253
##  [81] 0.5480998296 0.1778505542 0.0676041283 0.7545453175 0.6894674809
##  [86] 0.1230664686 0.1874660505 0.2058625557 0.2131162025 0.5810212418
##  [91] 0.2013536913 0.3865516332 0.4120946755 0.0952859495 0.0685476365
##  [96] 0.8361664140 0.1381823656 0.7144982803 0.1473193541 0.3775856681
## [101] 0.2000978957 0.4223164362 0.0258709076 0.0040990973 0.9700299951
## [106] 0.2257158658 0.4868523953 0.2874317388 0.4520090686 0.0244057050
## [111] 0.5235852264 0.2803844183 0.6376286114 0.0819869703 0.0697063785
## [116] 0.0290425441 0.9012510774 0.2231925349 0.6202506609 0.1565568042
## [121] 0.0009567274 0.6347501962 0.3642930763 0.4652535468 0.5267369885
## [126] 0.0080094647 0.2455690326 0.5717535003 0.1826774671 0.3309030798
## [131] 0.3034736423 0.3656232778 0.2554464112 0.0708831192 0.6736704696
## [136] 0.1052531952 0.7828613615 0.1118854433 0.7046088497 0.0596986255
## [141] 0.2356925248 0.3761585231 0.1659869477 0.4578545291 0.3481856456
## [146] 0.3822073762 0.2696069782 0.5244447065 0.2792275760 0.1963277175
## [151] 0.6065907234 0.2213197036 0.1720895730 0.3427638044 0.5191903980
## [156] 0.1380457976 0.1276013840 0.4892495682 0.3831490478 0.1110758134
## [161] 0.2420915307 0.6468326559 0.0106872793 0.4357936298 0.5535190909
## [166] 0.1927190754 0.4503961648 0.3568847599 0.5162877000 0.4488447069
## [171] 0.0348675931 0.0060355372 0.2789414194 0.7150230433 0.2701046988
## [176] 0.4184351300 0.3114601711 0.2568394218 0.5781026899 0.1650578883
## [181] 0.1619223342 0.4994306306 0.3386470352 0.3610243672 0.0146180678
## [186] 0.6243575651 0.2348479216 0.0849322565 0.6802198219 0.5817097924
## [191] 0.1324886060 0.2858016016 0.1098506262 0.7657505460 0.1243988278
## [196] 0.6334049297 0.1678676454 0.1987274250 0.0912114033 0.7903820183
## [201] 0.1184065784 0.1932190827 0.1458225858 0.6609583315 0.4054246263
## [206] 0.2570355292 0.3375398444 0.3087824071 0.1639304662 0.5272871268
## [211] 0.6402869809 0.0111529650 0.3485600541 0.6183618691 0.0447616260
## [216] 0.3368765048 0.4133743953 0.2577889026 0.3288367020 0.5067144651
## [221] 0.0076246934 0.4856608415 0.7231894799 0.1317818118 0.1450287083
## [226] 0.5244801973 0.2174437300 0.2580760727 0.4000706738 0.3209665995
## [231] 0.2789627267 0.3616019287 0.6374677932 0.0009302781 0.3023019873
## [236] 0.1927107023 0.5049873104 0.1554450225 0.0488181734 0.7957368041
## [241] 0.0097467289 0.1565462507 0.8337070204 0.0703802700 0.8226276855
## [246] 0.1069920445 0.5283486014 0.1723249501 0.2993264485 0.2353959384
## [251] 0.4908058548 0.2737982068 0.9296928791 0.0003363329 0.0699707880
## [256] 0.6333949310 0.2909886991 0.0756163700 0.0715088164 0.2376923505
## [261] 0.6907988330 0.1826897927 0.3067737606 0.5105364467 0.0269268886
## [266] 0.8082488808 0.1648242306 0.1397872302 0.1511347455 0.7090780244
## [271] 0.4692959369 0.4335684299 0.0971356332 0.1340574222 0.7232535251
## [276] 0.1426890527 0.8350737332 0.0936780574 0.0712482093 0.0399914719
## [281] 0.8819474026 0.0780611255 0.1437206552 0.2424383720 0.6138409728
## [286] 0.1119870632 0.4740645280 0.4139484088 0.4601041367 0.2248874852
## [291] 0.3150083781 0.1636324150 0.2519571851 0.5844103999 0.3345076842
## [296] 0.4942367005 0.1712556153 0.7141235650 0.0222984271 0.2635780079

# 
weights_table <-  stock_returns_monthly %>%
  distinct(symbol) %>%
    tq_repeat_df(n = num_port) %>%
    bind_cols(tibble(weights)) %>%
    group_by(portfolio)
weights_table
## # A tibble: 300 x 3
## # Groups:   portfolio [100]
##    portfolio symbol weights
##        <int> <chr>    <dbl>
##  1         1 NFLX   0.0639 
##  2         1 TSLA   0.327  
##  3         1 AMZN   0.609  
##  4         2 NFLX   0.667  
##  5         2 TSLA   0.0835 
##  6         2 AMZN   0.249  
##  7         3 NFLX   0.949  
##  8         3 TSLA   0.0501 
##  9         3 AMZN   0.00121
## 10         4 NFLX   0.308  
## # … with 290 more rows

# Aggregate a Portfolio using Vector of Weights
portfolio_returns_monthly_multi  <-
  stock_returns_monthly_multi %>%
    tq_portfolio(assets_col  = symbol, 
                 returns_col = Ra, 
                 weights     = weights_table, 
                 col_rename  = "Ra")
portfolio_returns_monthly_multi 
## # A tibble: 6,100 x 3
## # Groups:   portfolio [100]
##    portfolio date             Ra
##        <int> <date>        <dbl>
##  1         1 2014-11-28  0.00327
##  2         1 2014-12-31 -0.0814 
##  3         1 2015-01-30  0.0804 
##  4         1 2015-02-27  0.0527 
##  5         1 2015-03-31 -0.0424 
##  6         1 2015-04-30  0.165  
##  7         1 2015-05-29  0.0500 
##  8         1 2015-06-30  0.0308 
##  9         1 2015-07-31  0.166  
## 10         1 2015-08-31 -0.0434 
## # … with 6,090 more rows

Q4 Calculate performance metrics, CAPM measures.

# Merging Ra and Rb
RaRb_multi_portfolio <- left_join(portfolio_returns_monthly_multi ,
                                   baseline_returns_monthly,
                                   by = "date")
RaRb_multi_portfolio
## # A tibble: 6,100 x 4
## # Groups:   portfolio [100]
##    portfolio date             Ra       Rb
##        <int> <date>        <dbl>    <dbl>
##  1         1 2014-11-28  0.00327  0.0347 
##  2         1 2014-12-31 -0.0814  -0.0116 
##  3         1 2015-01-30  0.0804  -0.0213 
##  4         1 2015-02-27  0.0527   0.0708 
##  5         1 2015-03-31 -0.0424  -0.0126 
##  6         1 2015-04-30  0.165    0.00827
##  7         1 2015-05-29  0.0500   0.0260 
##  8         1 2015-06-30  0.0308  -0.0164 
##  9         1 2015-07-31  0.166    0.0284 
## 10         1 2015-08-31 -0.0434  -0.0686 
## # … with 6,090 more rows


RaRb_multi_portfolio %>%
tq_performance(Ra = Ra, Rb = Rb, performance_fun = table.CAPM)
## # A tibble: 100 x 13
## # Groups:   portfolio [100]
##    portfolio ActivePremium  Alpha AnnualizedAlpha  Beta `Beta-` `Beta+`
##        <int>         <dbl>  <dbl>           <dbl> <dbl>   <dbl>   <dbl>
##  1         1         0.188 0.0117           0.150  1.28    1.51   1.04 
##  2         2         0.275 0.018            0.239  1.41    1.56   1.44 
##  3         3         0.294 0.0208           0.280  1.43    1.57   1.51 
##  4         4         0.202 0.0129           0.166  1.31    1.47   1.15 
##  5         5         0.113 0.0082           0.103  1.14    1.28   0.695
##  6         6         0.246 0.0163           0.214  1.38    1.51   1.35 
##  7         7         0.267 0.016            0.210  1.40    1.63   1.40 
##  8         8         0.271 0.0167           0.219  1.41    1.59   1.42 
##  9         9         0.210 0.0132           0.171  1.32    1.48   1.18 
## 10        10         0.262 0.0166           0.219  1.40    1.55   1.39 
## # … with 90 more rows, and 6 more variables: Correlation <dbl>,
## #   `Correlationp-value` <dbl>, InformationRatio <dbl>, `R-squared` <dbl>,
## #   TrackingError <dbl>, TreynorRatio <dbl>

Q5 Find the portfolio that is least affected by adverse market movements.

Hint: Sort the portfolios based on the relevant measure you calcualted in Q4. Use dplyr::arrange(). Discuss your answer based on the measure you used to sort.

RaRb_multi_portfolio %>%
  tq_performance(Ra = Ra, Rb = Rb, performance_fun = table.CAPM) %>%
  arrange(desc(Alpha))
## # A tibble: 100 x 13
## # Groups:   portfolio [100]
##    portfolio ActivePremium  Alpha AnnualizedAlpha  Beta `Beta-` `Beta+`
##        <int>         <dbl>  <dbl>           <dbl> <dbl>   <dbl>   <dbl>
##  1        85         0.302 0.0209           0.282  1.44    1.59    1.52
##  2         3         0.294 0.0208           0.280  1.43    1.57    1.51
##  3        16         0.290 0.0195           0.260  1.43    1.58    1.49
##  4        93         0.281 0.0194           0.259  1.42    1.55    1.47
##  5        15         0.272 0.0191           0.256  1.41    1.53    1.45
##  6       100         0.289 0.0189           0.252  1.43    1.58    1.48
##  7        47         0.281 0.0185           0.246  1.42    1.57    1.46
##  8        71         0.287 0.0184           0.245  1.43    1.59    1.48
##  9        75         0.268 0.0181           0.240  1.40    1.54    1.43
## 10         2         0.275 0.018            0.239  1.41    1.56    1.44
## # … with 90 more rows, and 6 more variables: Correlation <dbl>,
## #   `Correlationp-value` <dbl>, InformationRatio <dbl>, `R-squared` <dbl>,
## #   TrackingError <dbl>, TreynorRatio <dbl>

Portfolio 85 is the portfolio that is the least effected by adverse market movements by having the highest Alpha at .0209.

Q6 What are the weights of the stocks in the portfolio that is least affected by adverse market movements?

   Portfolio 85
NFLX    0.9296928791    93%
TSLA    0.0003363329    <1%
AMZN    0.0699707880    7%

Q7 Calculate the Sharpe ratios with an annualized risk-free rate of 2% and a confidence interval of 0.99. Which portfolio would yield the greatest return per risk when VaR is used as the measure of risk?

Hint: Use SharpeRatio for the performance_fun argument, instead of SharpeRatio.annualized, which doesn’t work with the Rf and p arguments. Sort the results using dplyr::arrange().

stock_returns_monthly %>%
    tq_performance(Ra              = Ra, 
                   performance_fun = SharpeRatio,
                   Rf              = 0.02/12, p =.99)
## # A tibble: 3 x 4
## # Groups:   symbol [3]
##   symbol `ESSharpe(Rf=0.2%,p=… `StdDevSharpe(Rf=0.2%… `VaRSharpe(Rf=0.2%,p…
##   <chr>                  <dbl>                  <dbl>                 <dbl>
## 1 NFLX                  0.193                  0.291                 0.193 
## 2 TSLA                  0.0370                 0.0851                0.0438
## 3 AMZN                  0.141                  0.353                 0.180

Netflix has the greatest return per risk when VaR is used at .193, then Amazon at .179, then Tesla at .043.

Q8 Hide the messages, but display the code and its results on the webpage.

Hint: Use message, echo and results in the chunk options. Refer to the RMarkdown Reference Guide.

Q9 Display the title and your name correctly at the top of the webpage.

Q10 Use the correct slug.