# 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.
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>
The weight least affected by adverse market movements is 94 becasue it’s the highest, with an alpha of 2.05%.
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.
Hint: Use message
, echo
and results
in the chunk options. Refer to the RMarkdown Reference Guide.