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("AMZN", "NFLX", "TSLA") %>%
    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 AMZN   2014-11-26  334.  335.  332.  334. 1983600     334.
##  2 AMZN   2014-11-28  336.  341.  336.  339. 3051800     339.
##  3 AMZN   2014-12-01  338.  341.  326.  326  4944900     326 
##  4 AMZN   2014-12-02  328.  328.  323.  326. 2790300     326.
##  5 AMZN   2014-12-03  326.  327.  314.  316. 5681000     316.
##  6 AMZN   2014-12-04  316.  319.  313.  317. 3290300     317.
##  7 AMZN   2014-12-05  317.  317.  311.  313. 3265200     313.
##  8 AMZN   2014-12-08  312.  317.  305.  307. 3639200     307.
##  9 AMZN   2014-12-09  303.  314.  301.  312. 4049500     312.
## 10 AMZN   2014-12-10  312   313.  305.  306. 3245900     306.
## # … 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 AMZN   2014-11-28  0.0152
##  2 AMZN   2014-12-31 -0.0835
##  3 AMZN   2015-01-30  0.142 
##  4 AMZN   2015-02-27  0.0723
##  5 AMZN   2015-03-31 -0.0212
##  6 AMZN   2015-04-30  0.134 
##  7 AMZN   2015-05-29  0.0177
##  8 AMZN   2015-06-30  0.0113
##  9 AMZN   2015-07-31  0.235 
## 10 AMZN   2015-08-31 -0.0434
## # … with 173 more rows

# Baseline Period Returns
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: 61 x 2
##    date              Rb
##    <date>         <dbl>
##  1 2014-11-28  0.000900
##  2 2014-12-31 -0.0116  
##  3 2015-01-30 -0.0213  
##  4 2015-02-27  0.0708  
##  5 2015-03-31 -0.0126  
##  6 2015-04-30  0.00827 
##  7 2015-05-29  0.0260  
##  8 2015-06-30 -0.0164  
##  9 2015-07-31  0.0284  
## 10 2015-08-31 -0.0686  
## # … with 51 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 AMZN   2014-11-28  0.0152
##  2         1 AMZN   2014-12-31 -0.0835
##  3         1 AMZN   2015-01-30  0.142 
##  4         1 AMZN   2015-02-27  0.0723
##  5         1 AMZN   2015-03-31 -0.0212
##  6         1 AMZN   2015-04-30  0.134 
##  7         1 AMZN   2015-05-29  0.0177
##  8         1 AMZN   2015-06-30  0.0113
##  9         1 AMZN   2015-07-31  0.235 
## 10         1 AMZN   2015-08-31 -0.0434
## # … 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 AMZN   0.0639 
##  2         1 NFLX   0.327  
##  3         1 TSLA   0.609  
##  4         2 AMZN   0.667  
##  5         2 NFLX   0.0835 
##  6         2 TSLA   0.249  
##  7         3 AMZN   0.949  
##  8         3 NFLX   0.0501 
##  9         3 TSLA   0.00121
## 10         4 AMZN   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.0129
##  2         1 2014-12-31 -0.0651
##  3         1 2015-01-30  0.0603
##  4         1 2015-02-27  0.0359
##  5         1 2015-03-31 -0.0903
##  6         1 2015-04-30  0.251 
##  7         1 2015-05-29  0.108 
##  8         1 2015-06-30  0.0582
##  9         1 2015-07-31  0.109 
## 10         1 2015-08-31 -0.0278
## # … 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.0129  0.000900
##  2         1 2014-12-31 -0.0651 -0.0116  
##  3         1 2015-01-30  0.0603 -0.0213  
##  4         1 2015-02-27  0.0359  0.0708  
##  5         1 2015-03-31 -0.0903 -0.0126  
##  6         1 2015-04-30  0.251   0.00827 
##  7         1 2015-05-29  0.108   0.0260  
##  8         1 2015-06-30  0.0582 -0.0164  
##  9         1 2015-07-31  0.109   0.0284  
## 10         1 2015-08-31 -0.0278 -0.0686  
## # … with 6,090 more rows

# Beta and Alpha
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.136  0.0103          0.131  1.21     1.25   0.940
##  2         2        0.216  0.0134          0.173  1.33     1.55   1.16 
##  3         3        0.268  0.0163          0.214  1.41     1.67   1.38 
##  4         4        0.204  0.0132          0.171  1.32     1.44   1.17 
##  5         5        0.238  0.0163          0.214  1.38     1.47   1.35 
##  6         6        0.234  0.0144          0.187  1.36     1.55   1.26 
##  7         7        0.0605 0.0062          0.0775 0.999    1.08   0.354
##  8         8        0.134  0.0092          0.116  1.17     1.35   0.760
##  9         9        0.194  0.0126          0.163  1.30     1.43   1.13 
## 10        10        0.190  0.012           0.154  1.28     1.48   1.05 
## # … 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        94         0.293 0.0205           0.276  1.44    1.56    1.53
##  2        82         0.285 0.0197           0.264  1.44    1.55    1.50
##  3        46         0.282 0.0193           0.258  1.43    1.55    1.49
##  4        67         0.281 0.0193           0.258  1.43    1.54    1.49
##  5        89         0.273 0.0192           0.256  1.42    1.52    1.47
##  6        65         0.279 0.0191           0.254  1.43    1.54    1.48
##  7        78         0.296 0.0191           0.255  1.45    1.59    1.51
##  8        92         0.273 0.0185           0.247  1.42    1.53    1.46
##  9        33         0.272 0.0184           0.245  1.42    1.53    1.46
## 10        38         0.281 0.0184           0.244  1.43    1.56    1.47
## # … with 90 more rows, and 6 more variables: Correlation <dbl>,
## #   `Correlationp-value` <dbl>, InformationRatio <dbl>, `R-squared` <dbl>,
## #   TrackingError <dbl>, TreynorRatio <dbl>

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

The weight least affected by adverse market movements is 94 becasue it’s the highest, with an alpha of 2.05%.

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

# Retrieve performance metrics
stock_returns_monthly %>%
    tq_performance(Ra = Ra,
                   Rb = NULL, # Calculataing downside risk measures doesn't require Rb
                   performance_fun = SharpeRatio, p=.99, Rf=.02)
## # A tibble: 3 x 4
## # Groups:   symbol [3]
##   symbol `ESSharpe(Rf=2%,p=99… `StdDevSharpe(Rf=2%,p=… `VaRSharpe(Rf=2%,p=…
##   <chr>                  <dbl>                   <dbl>                <dbl>
## 1 AMZN                  0.0532                  0.133                0.0677
## 2 NFLX                  0.0945                  0.143                0.0945
## 3 TSLA                 -0.0305                 -0.0702              -0.0362

The Var most affected was Netflix with a Var of 0.095.

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.