# Load packages
# Core
library(tidyverse)
library(tidyquant)
Examine how each asset contributes to portfolio standard deviation. This is to ensure that our risk is not concentrated in any one asset.
Choose your stocks from 2012-12-31 to present.
symbols <- c("AAPL", "TSLA", "NFLX", "MTN", "DIS")
prices <- tq_get(x = symbols,
get = "stock.prices",
from = "2012-12-31",
to = "2017-12-31")
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"))
asset_returns_wide_tbl <- asset_returns_tbl %>%
pivot_wider(names_from = asset, values_from = returns) %>%
column_to_rownames(var = "date")
asset_returns_wide_tbl
## AAPL DIS MTN NFLX TSLA
## 2013-01-31 -1.555892e-01 0.078945343 -0.0231918724 0.579217807 0.102078114
## 2013-02-28 -2.561112e-02 0.013091424 0.0442297378 0.129468379 -0.074128640
## 2013-03-28 2.850342e-03 0.039685715 0.1239325401 0.006360071 0.084208138
## 2013-04-30 2.710681e-04 0.101055590 -0.0329506326 0.132375020 0.354111531
## 2013-05-31 2.217210e-02 0.003811641 0.0603319018 0.046038179 0.593716684
## 2013-06-28 -1.258960e-01 0.001109263 -0.0370411874 -0.069356059 0.093672163
## 2013-07-31 1.321022e-01 0.023475036 0.0850321341 0.146848883 0.223739522
## 2013-08-30 8.044283e-02 -0.060904939 0.0151132706 0.149523815 0.229971642
## 2013-09-30 -2.172321e-02 0.058427054 0.0200911441 0.085363345 0.134706620
## 2013-10-31 9.201521e-02 0.061636785 0.0183269115 0.042020452 -0.189806595
## 2013-11-29 6.770803e-02 0.028033167 0.0730628028 0.126045633 -0.228409405
## 2013-12-31 8.862431e-03 0.092072694 -0.0046405259 0.006458091 0.167108541
## 2014-01-31 -1.139495e-01 -0.050879802 -0.0988388515 0.105976906 0.187261714
## 2014-02-28 5.591824e-02 0.106997830 0.0313453514 0.084967340 0.299722785
## 2014-03-31 1.975631e-02 -0.009199477 -0.0028627076 -0.235772622 -0.160783242
## 2014-04-30 9.476113e-02 -0.009158724 -0.0067660048 -0.089040653 -0.002690122
## 2014-05-30 7.576526e-02 0.057193347 0.0066226754 0.260398864 -0.000577422
## 2014-06-30 2.728649e-02 0.020383646 0.1075734020 0.053062785 0.144457224
## 2014-07-31 2.832618e-02 0.001631637 -0.0220076250 -0.041427371 -0.072372676
## 2014-08-29 7.465184e-02 0.045524219 0.0514985456 0.122147235 0.188794007
## 2014-09-30 -1.722096e-02 -0.009502046 0.0875144905 -0.056990921 -0.105566477
## 2014-10-31 6.948911e-02 0.026053373 0.0002988081 -0.138642147 -0.004046477
## 2014-11-28 1.007308e-01 0.012290061 0.0147128915 -0.125081717 0.011599801
## 2014-12-31 -7.460609e-02 0.030627226 0.0436537363 -0.014472733 -0.094774519
## 2015-01-30 5.961153e-02 -0.034894290 -0.0376810830 0.257187512 -0.088365289
## 2015-02-27 9.601606e-02 0.134740106 0.0005695887 0.072268016 -0.001277808
## 2015-03-31 -3.187436e-02 0.007752275 0.1699390530 -0.130782770 -0.074350051
## 2015-04-30 5.769568e-03 0.035863546 -0.0415595895 0.289324652 0.180226808
## 2015-05-29 4.434121e-02 0.015062589 0.0446488031 0.114579343 0.103899574
## 2015-06-30 -3.793802e-02 0.033587462 0.0569933105 0.051346180 0.067300935
## 2015-07-31 -3.348100e-02 0.055865152 0.0044771246 0.197231490 -0.007896616
## 2015-08-31 -6.848885e-02 -0.163696244 -0.0163607695 0.006278919 -0.066366250
## 2015-09-30 -2.205779e-02 0.003136098 -0.0303893068 -0.107942853 -0.002653519
## 2015-10-30 8.011263e-02 0.106983559 0.0927711646 0.048393445 -0.182659777
## 2015-11-30 -5.821329e-03 -0.002376683 0.0547906642 0.129220160 0.106828586
## 2015-12-31 -1.167903e-01 -0.070426735 0.0644606296 -0.075337490 0.041471519
## 2016-01-29 -7.822376e-02 -0.092250540 -0.0236383431 -0.219478322 -0.227360626
## 2016-02-29 -1.288089e-03 -0.003135750 0.0190963881 0.016950552 0.003810669
## 2016-03-31 1.197460e-01 0.038910635 0.0546075157 0.090226765 0.179948109
## 2016-04-29 -1.507308e-01 0.039003695 -0.0308369548 -0.127082275 0.046721797
## 2016-05-31 6.931422e-02 -0.039910424 0.0123425492 0.130402555 -0.075597968
## 2016-06-30 -4.359686e-02 -0.014210490 0.0575821650 -0.114425083 -0.050296440
## 2016-07-29 8.623558e-02 -0.012063988 0.0344152620 -0.002517413 0.100785334
## 2016-08-31 2.337629e-02 -0.015650851 0.1019784574 0.065736402 -0.102058091
## 2016-09-30 6.344843e-02 -0.017083223 -0.0098317846 0.011224670 -0.038366372
## 2016-10-31 4.324929e-03 -0.001832563 0.0213716193 0.236709154 -0.031364583
## 2016-11-30 -2.183771e-02 0.067070612 -0.0065441011 -0.065099283 -0.043041267
## 2016-12-30 4.684044e-02 0.057850108 0.0231786958 0.056493450 0.120665178
## 2017-01-31 4.664191e-02 0.059868052 0.0614884585 0.128033698 0.164624916
## 2017-02-28 1.255554e-01 -0.005073886 0.0546744400 0.010041084 -0.007730364
## 2017-03-31 4.754166e-02 0.029534975 0.0631143976 0.039185483 0.107278727
## 2017-04-28 -6.988896e-05 0.019302741 0.0295740196 0.029267777 0.120916212
## 2017-05-31 6.560722e-02 -0.068560258 0.0789604501 0.068984176 0.082295892
## 2017-06-30 -5.891597e-02 -0.015780857 -0.0481440735 -0.087485372 0.058654468
## 2017-07-31 3.218079e-02 0.041460580 0.0383517328 0.195442599 -0.111459860
## 2017-08-31 1.016528e-01 -0.082745077 0.0784062317 -0.039009333 0.095543446
## 2017-09-29 -6.213463e-02 -0.026331693 0.0007453902 0.037301404 -0.042474144
## 2017-10-31 9.240361e-02 -0.007740164 0.0088134673 0.079877197 -0.028457409
## 2017-11-30 2.007518e-02 0.069217765 -0.0169978733 -0.046100666 -0.070862541
## 2017-12-29 -1.536360e-02 0.033351510 -0.0531049851 0.023081621 0.008061928
covariance_matrix <- cov(asset_returns_wide_tbl)
covariance_matrix
## AAPL DIS MTN NFLX TSLA
## AAPL 0.0048301465 5.731109e-04 1.066263e-03 0.0006512443 4.839080e-04
## DIS 0.0005731109 2.786559e-03 8.463741e-05 0.0019003221 1.349722e-03
## MTN 0.0010662635 8.463741e-05 2.427744e-03 -0.0003491263 -3.105694e-05
## NFLX 0.0006512443 1.900322e-03 -3.491263e-04 0.0177864943 4.989080e-03
## TSLA 0.0004839080 1.349722e-03 -3.105694e-05 0.0049890797 2.095735e-02
w <- c(0.25, 0.25, 0.2, 0.2, 0.1)
sd_portfolio <- sqrt(t(w) %*% covariance_matrix %*% w)
sd_portfolio
## [,1]
## [1,] 0.04688438
component_contribution <- (t(w) %*% covariance_matrix * w) / sd_portfolio[1,1]
component_contribution
## AAPL DIS MTN NFLX TSLA
## [1,] 0.009292576 0.007315237 0.002987533 0.01972629 0.007562748
rowSums(component_contribution)
## [1] 0.04688438
component_percentages <- (component_contribution / sd_portfolio[1,1]) %>%
round(3) %>%
as_tibble()
component_percentages
## # A tibble: 1 × 5
## AAPL DIS MTN NFLX TSLA
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.198 0.156 0.064 0.421 0.161
component_percentages %>%
as_tibble() %>%
gather(key = "asset", value = "contribution")
## # A tibble: 5 × 2
## asset contribution
## <chr> <dbl>
## 1 AAPL 0.198
## 2 DIS 0.156
## 3 MTN 0.064
## 4 NFLX 0.421
## 5 TSLA 0.161
asset_returns_wide_tbl <- asset_returns_tbl %>%
pivot_wider(names_from = asset, values_from = returns) %>%
column_to_rownames(var = "date")
calculate_component_contribution <- function(asset_returns_wide_tbl, w) {
covariance_matrix <- cov(asset_returns_wide_tbl)
sd_portfolio <- sqrt(t(w) %*% covariance_matrix %*% w)
component_contribution <- (t(w) %*% covariance_matrix * w) / sd_portfolio[1,1]
component_percentages <- (component_contribution / sd_portfolio[1,1]) %>%
round(3) %>%
as_tibble()
return(component_percentages)
}
asset_returns_wide_tbl %>% calculate_component_contribution(w = c(0.25,0.25,0.2,0.2,0.1))
## # A tibble: 1 × 5
## AAPL DIS MTN NFLX TSLA
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.198 0.156 0.064 0.421 0.161
Which of the assets in your portfolio the largest contributor to the portfolio volatility? Do you think your portfolio risk is concentrated in any one asset?
calculate_comp_contrib_by_window <- function(asset_returns_wide_tbl,
start = 1,
window = 24,
weights) {
start_date <- rownames(asset_returns_wide_tbl)[start]
end_date <- rownames(asset_returns_wide_tbl)[start + window]
df_subset <- asset_returns_wide_tbl %>%
rownames_to_column(var = "date") %>%
filter(date >= start_date & date < end_date) %>%
column_to_rownames(var = "date")
component_percentages <-df_subset %>%
calculate_component_contribution(w = weights)
component_percentages %>%
mutate(date = ymd(end_date)) %>%
select(date, everything())
}
asset_returns_wide_tbl %>% calculate_comp_contrib_by_window(start = 1, window = 24,
w = c(0.25,0.25,0.2,0.2,0.1))
## # A tibble: 1 × 6
## date AAPL DIS MTN NFLX TSLA
## <date> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2015-01-30 0.108 0.118 0.07 0.477 0.227
asset_returns_wide_tbl %>% calculate_comp_contrib_by_window(start = 2, window = 24,
w = c(0.25,0.25,0.2,0.2,0.1))
## # A tibble: 1 × 6
## date AAPL DIS MTN NFLX TSLA
## <date> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2015-02-27 0.183 0.108 0.088 0.379 0.242
dump(list = c("calculate_component_contribution",
"calculate_comp_contrib_by_window"),
file = "../00_scripts/calculate_comp_contrib_to_portfolio_volatility.R")
w <- c(0.25,0.25,0.2,0.2,0.1)
window <- 24
rolling_comp_contrib_tbl <- 1:(nrow(asset_returns_wide_tbl) - window) %>%
map_df(.x = ., .f = ~calculate_comp_contrib_by_window(asset_returns_wide_tbl,
start = .x,
weights = w,
window = window))
rolling_comp_contrib_tbl
## # A tibble: 36 × 6
## date AAPL DIS MTN NFLX TSLA
## <date> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2015-01-30 0.108 0.118 0.07 0.477 0.227
## 2 2015-02-27 0.183 0.108 0.088 0.379 0.242
## 3 2015-03-31 0.188 0.126 0.083 0.377 0.227
## 4 2015-04-30 0.197 0.126 0.054 0.393 0.231
## 5 2015-05-29 0.199 0.111 0.053 0.422 0.215
## 6 2015-06-30 0.213 0.121 0.049 0.45 0.167
## 7 2015-07-31 0.174 0.126 0.034 0.469 0.197
## 8 2015-08-31 0.144 0.148 0.013 0.508 0.187
## 9 2015-09-30 0.157 0.236 0.027 0.422 0.158
## 10 2015-10-30 0.165 0.224 0.038 0.428 0.146
## # ℹ 26 more rows
rolling_comp_contrib_tbl %>%
pivot_longer(cols = -date, names_to = "asset", values_to = "contribution") %>%
ggplot(aes(date, contribution, color = asset)) +
geom_line() +
scale_x_date(breaks = scales::pretty_breaks(n = 7)) +
scale_y_continuous(labels = scales::percent_format()) +
annotate(geom = "text",
x = as.Date("2016-07-01"),
y = 0.03,
color = "red", size = 5,
label = str_glue())
rolling_comp_contrib_tbl %>%
pivot_longer(cols = -date, names_to = "asset", values_to = "contribution") %>%
ggplot(aes(date, contribution, fill = asset)) +
geom_area() +
scale_x_date(breaks = scales::pretty_breaks(n = 7)) +
scale_y_continuous(labels = scales::percent_format()) +
annotate(geom = "text",
x = as.Date("2016-07-01"),
y = 0.08,
color = "red", size = 5,
label = str_glue())