# 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.
symbols <- c("NKE", "MSFT", "GOOG", "TSLA", "AMZN")
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
## AMZN GOOG MSFT NKE TSLA
## 2013-01-31 0.0566799640 0.066063183 0.027328277 0.0463883017 0.102078031
## 2013-02-28 -0.0046435329 0.058479349 0.020915050 0.0114289611 -0.074128613
## 2013-03-28 0.0083654117 -0.008787848 0.028720295 0.0802403050 0.084208141
## 2013-04-30 -0.0487507638 0.037539320 0.145776986 0.0749064104 0.354111527
## 2013-05-31 0.0588686422 0.055032448 0.059941068 -0.0276352997 0.593716693
## 2013-06-28 0.0310507858 0.010447756 -0.010368778 0.0322349473 0.093672182
## 2013-07-31 0.0813355112 0.008347897 -0.081394397 -0.0120064868 0.223739545
## 2013-08-30 -0.0695574024 -0.047107484 0.054854343 0.0017288037 0.229971572
## 2013-09-30 0.1067688764 0.033680642 -0.003599367 0.1452421943 0.134706682
## 2013-10-31 0.1521839130 0.162613748 0.062037340 0.0420550503 -0.189806650
## 2013-11-29 0.0781496951 0.027760300 0.081562724 0.0436481038 -0.228409431
## 2013-12-31 0.0130490358 0.056080333 -0.019063379 -0.0032101363 0.167108548
## 2014-01-31 -0.1059765070 0.052373779 0.011428753 -0.0764778226 0.187261770
## 2014-02-28 0.0094619111 0.028942731 0.019815082 0.0752105396 0.299722757
## 2014-03-31 -0.0737086127 -0.086376126 0.067616940 -0.0583764875 -0.160783192
## 2014-04-30 -0.1007565625 -0.055956216 -0.014498138 -0.0123968514 -0.002690159
## 2014-05-30 0.0273092148 0.061185200 0.020307481 0.0560128329 -0.000577395
## 2014-06-30 0.0383835737 0.027116573 0.018393742 0.0082872339 0.144457218
## 2014-07-31 -0.0369767889 -0.006417530 0.034412912 -0.0054306231 -0.072372711
## 2014-08-29 0.0799468534 0.000000000 0.057485051 0.0212579490 0.188794049
## 2014-09-30 -0.0502010221 0.010026597 0.020264076 0.1271459124 -0.105566506
## 2014-10-31 -0.0540982353 -0.032173432 0.012646455 0.0413956964 -0.004046457
## 2014-11-28 0.1031187000 -0.031340259 0.024438910 0.0657678506 0.011599756
## 2014-12-31 -0.0872368443 -0.028890933 -0.028858133 -0.0292639544 -0.094774520
## 2015-01-30 0.1330922758 0.015307754 -0.139547014 -0.0414070791 -0.088365243
## 2015-02-27 0.0697991955 0.043706410 0.089036319 0.0543410026 -0.001277805
## 2015-03-31 -0.0214295288 -0.018800219 -0.075529508 0.0325174665 -0.074350086
## 2015-04-30 0.1253212631 -0.016902497 0.179201084 -0.0149625708 0.180226844
## 2015-05-29 0.0175090073 -0.009780881 -0.030803957 0.0309566095 0.103899535
## 2015-06-30 0.0112589801 -0.022041136 -0.059571131 0.0605840251 0.067300966
## 2015-07-31 0.2111621241 0.183918112 0.056151123 0.0645270979 -0.007896618
## 2015-08-31 -0.0443525737 -0.011834267 -0.063950893 -0.0305794124 -0.066366266
## 2015-09-30 -0.0019516780 -0.016027473 0.016860468 0.0982087929 -0.002653542
## 2015-10-30 0.2010808557 0.155539760 0.173395111 0.0634861098 -0.182659742
## 2015-11-30 0.0602956898 0.043752376 0.038686218 0.0094946595 0.106828579
## 2015-12-31 0.0165439780 0.021686093 0.020578074 -0.0541863079 0.041471546
## 2016-01-29 -0.1410054619 -0.021214941 -0.007054663 -0.0078707491 -0.227360646
## 2016-02-29 -0.0605352242 -0.062739185 -0.072343945 -0.0067962168 0.003810669
## 2016-03-31 0.0717834457 0.065427593 0.082036266 0.0006245188 0.179948112
## 2016-04-29 0.1053453885 -0.072272671 -0.102086790 -0.0420288113 0.046721799
## 2016-05-31 0.0915002937 0.059805126 0.067842410 -0.0651950656 -0.075597977
## 2016-06-30 -0.0099694796 -0.061119131 -0.035138500 0.0025547583 -0.050296472
## 2016-07-29 0.0586021200 0.105087370 0.102268202 0.0054200146 0.100785361
## 2016-08-31 0.0135476463 -0.002265810 0.019880687 0.0378337649 -0.102058076
## 2016-09-30 0.0848953859 0.013261445 0.002433606 -0.0877707138 -0.038366402
## 2016-10-31 -0.0583892995 0.009284125 0.039487771 -0.0480495757 -0.031364578
## 2016-11-30 -0.0509721788 -0.034361430 0.012390768 -0.0021945446 -0.043041257
## 2016-12-30 -0.0009330597 0.018015208 0.030721634 0.0186660982 0.120665160
## 2017-01-31 0.0936394046 0.031839794 0.039598117 0.0399166113 0.164624944
## 2017-02-28 0.0258446771 0.032620176 -0.004373208 0.0774508422 -0.007730394
## 2017-03-31 0.0479423059 0.007684132 0.028960692 -0.0222248142 0.107278734
## 2017-04-28 0.0424566809 0.088099691 0.038718460 -0.0057585001 0.120916240
## 2017-05-31 0.0725778079 0.062987858 0.025672805 -0.0446567770 0.082295867
## 2017-06-30 -0.0271286060 -0.059934971 -0.013115737 0.1108369772 0.058654469
## 2017-07-31 0.0202278723 0.023674077 0.053250283 0.0008469698 -0.111459838
## 2017-08-31 -0.0072953921 0.009444715 0.033388989 -0.1082532315 0.095543417
## 2017-09-29 -0.0198260414 0.020838979 -0.003751688 -0.0183459146 -0.042474117
## 2017-10-31 0.1395154081 0.058252558 0.110341585 0.0587964431 -0.028457431
## 2017-11-30 0.0626577388 0.004680914 0.016841215 0.0941688267 -0.070862536
## 2017-12-29 -0.0062057977 0.024171696 0.016145829 0.0379617474 0.008061927
covariance_matrix <- cov(asset_returns_wide_tbl)
covariance_matrix
## AMZN GOOG MSFT NKE TSLA
## AMZN 0.0054660217 0.0023733615 0.0012207210 0.0007202259 0.0005128767
## GOOG 0.0023733615 0.0028612905 0.0014481465 0.0003704537 0.0004123950
## MSFT 0.0012207210 0.0014481465 0.0034652264 0.0004282569 0.0009885666
## NKE 0.0007202259 0.0003704537 0.0004282569 0.0028217772 -0.0001432291
## TSLA 0.0005128767 0.0004123950 0.0009885666 -0.0001432291 0.0209573545
w <- c(0.20, 0.30, 0.10, 0.2, 0.2)
sd_portfolio <- sqrt(t(w) %*% covariance_matrix %*% w)
sd_portfolio
## [,1]
## [1,] 0.04604672
component_contribution <- (t(w) %*% covariance_matrix * w) / sd_portfolio[1,1]
component_contribution
## AMZN GOOG MSFT NKE TSLA
## [1,] 0.009442173 0.0106486 0.002841626 0.003621177 0.01949314
rowSums(component_contribution)
## [1] 0.04604672
component_percentages <- (component_contribution / sd_portfolio[1,1]) %>%
round(3) %>%
as_tibble()
component_percentages
## # A tibble: 1 × 5
## AMZN GOOG MSFT NKE TSLA
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.205 0.231 0.062 0.079 0.423
component_percentages %>%
as_tibble() %>%
gather(key = "asset", value = "contribution")
## # A tibble: 5 × 2
## asset contribution
## <chr> <dbl>
## 1 AMZN 0.205
## 2 GOOG 0.231
## 3 MSFT 0.062
## 4 NKE 0.079
## 5 TSLA 0.423
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.2,0.3,0.1,0.2,0.2))
## # A tibble: 1 × 5
## AMZN GOOG MSFT NKE TSLA
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.205 0.231 0.062 0.079 0.423
asset_returns_wide_tbl %>%
calculate_component_contribution(w = c(0.2,0.3,0.1,0.2,0.2)) %>%
gather(key = "asset", value = "contribution") %>%
ggplot(aes(asset, contribution)) +
geom_col(fill = "cornflowerblue") +
theme(plot.title = element_text(hjust = 0.5)) +
scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
labs(title = "Percent Contribution to Portfolio Standard Deviation",
y = "Percent Contribution to Risk",
x = NULL)
asset_returns_wide_tbl %>%
calculate_component_contribution(w = c(0.2,0.3,0.1,0.2,0.2)) %>%
gather(key = "asset", value = "contribution") %>%
add_column(weights = c(0.2,0.3,0.1,0.2,0.2)) %>%
pivot_longer(cols = c(contribution, weights), names_to = "type", values_to = "value") %>%
ggplot(aes(asset, value, fill = type)) +
geom_col(position = "dodge") +
theme(plot.title = element_text(hjust = 0.5)) +
scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
theme_tq() +
scale_fill_tq() +
labs(title = "Percent Contribution to Volatility",
y = "percent",
x = "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.2,0.3,0.1,0.2,0.2))
## # A tibble: 1 × 6
## date AMZN GOOG MSFT NKE TSLA
## <date> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2015-01-30 0.161 0.176 0.017 0.072 0.574
asset_returns_wide_tbl %>% calculate_comp_contrib_by_window(start = 2, window = 24,
w = c(0.2,0.3,0.1,0.2,0.2))
## # A tibble: 1 × 6
## date AMZN GOOG MSFT NKE TSLA
## <date> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2015-02-27 0.14 0.167 0.027 0.078 0.589
w <- c(0.2,0.3,0.1,0.2,0.2)
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 AMZN GOOG MSFT NKE TSLA
## <date> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2015-01-30 0.161 0.176 0.017 0.072 0.574
## 2 2015-02-27 0.14 0.167 0.027 0.078 0.589
## 3 2015-03-31 0.142 0.175 0.029 0.079 0.576
## 4 2015-04-30 0.142 0.176 0.035 0.073 0.574
## 5 2015-05-29 0.184 0.171 0.034 0.058 0.554
## 6 2015-06-30 0.227 0.192 0.033 0.106 0.443
## 7 2015-07-31 0.227 0.193 0.035 0.105 0.441
## 8 2015-08-31 0.254 0.259 0.043 0.108 0.336
## 9 2015-09-30 0.254 0.252 0.048 0.113 0.332
## 10 2015-10-30 0.255 0.269 0.055 0.09 0.33
## # … with 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("TSLA changes rapidly, indicating
it increases the portfolio volatility."))
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("TSLA changes rapidly, indicating
it increases the portfolio volatility."))
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("TSLA changes rapidly, indicating
it increases the portfolio volatility"))
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?
TSLA is the largest contributer to the portfolios volatility, as you can see it take a massive dip only over a few years and the increase within a year span. My portfolios risk is concentrated within TSLA.