# 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
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
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
# 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>
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.
According to the table. Portfolio 94 is the one least affected by adverse market movements. Using the descending alpha, performance_fun function it showed the alpha was 2.05%.
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>
Based on the weights of the stocks in the portfolio that are least affected by adverse market movements, starting with Amazon, they have a 3.99% weight, Netflix has a 88.19%, and Tesla has a 7.81% based on a monthly basis.
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().
When VaR is used as the measure of risk, Netflix is the portfolio that would yield the greatest return per risk would be Netflix with a 9.45% as a monthly return. Where as Amazon has a return of 6.76% monthly and Tesla is -3.61% monthly.
# 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
Hint: Use message, echo and results in the chunk options. Refer to the RMarkdown Reference Guide.