# Load packages
# Core
library(tidyverse)
library(tidyquant)
library(readr)
# Time series
library(lubridate)
library(tibbletime)
# modeling
library(broom)
Examine how each asset contributes to portfolio standard deviation. This is to ensure that our risk is not concentrated in any one asset.
five stocks: “SPY”, “EFA”, “IJS”, “EEM”, “AGG” from 2012-12-31 to 2017-12-31
symbols <- c("SPY", "EFA", "IJS", "EEM", "AGG")
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"))
Refresh your memory on covariance with this video. Click this link Refresh your memory on matrix multiplication. Click this link
# Transform data into wide form
asset_returns_wide_tbl <- asset_returns_tbl %>%
pivot_wider(names_from = asset, values_from = returns) %>%
column_to_rownames(var = "date")
asset_returns_wide_tbl
## AGG EEM EFA IJS SPY
## 2013-01-31 -0.0062311778 -0.0029354630 0.0366063983 0.052133418 4.992310e-02
## 2013-02-28 0.0058915923 -0.0231053436 -0.0129694779 0.016175507 1.267840e-02
## 2013-03-28 0.0009847549 -0.0102350107 0.0129694779 0.040258020 3.726786e-02
## 2013-04-30 0.0096387911 0.0120849040 0.0489678045 0.001222381 1.903017e-02
## 2013-05-31 -0.0202136325 -0.0494836088 -0.0306557725 0.041976433 2.333516e-02
## 2013-06-28 -0.0157785484 -0.0547281409 -0.0271445664 -0.001403003 -1.343435e-02
## 2013-07-31 0.0026884075 0.0131592640 0.0518606176 0.063541391 5.038668e-02
## 2013-08-30 -0.0082985000 -0.0257054296 -0.0197464637 -0.034743613 -3.045244e-02
## 2013-09-30 0.0111441585 0.0695887308 0.0753385871 0.063874036 3.115667e-02
## 2013-10-31 0.0082913747 0.0408614200 0.0320814768 0.034233800 4.526645e-02
## 2013-11-29 -0.0025093823 -0.0025941418 0.0054498606 0.041661124 2.920690e-02
## 2013-12-31 -0.0055832953 -0.0040743622 0.0215281319 0.012892056 2.559620e-02
## 2014-01-31 0.0152914662 -0.0903223827 -0.0534132981 -0.035775224 -3.588433e-02
## 2014-02-28 0.0037571357 0.0332205366 0.0595049263 0.045257418 4.451010e-02
## 2014-03-31 -0.0014816571 0.0380216407 -0.0046025666 0.013315272 8.261429e-03
## 2014-04-30 0.0081830915 0.0077727427 0.0165294466 -0.023184200 6.927661e-03
## 2014-05-30 0.0117220573 0.0290911914 0.0158280491 0.006205220 2.294122e-02
## 2014-06-30 -0.0005757154 0.0237336143 0.0091655596 0.037718802 2.043440e-02
## 2014-07-31 -0.0025128264 0.0135559023 -0.0263796333 -0.052009583 -1.352881e-02
## 2014-08-29 0.0114308629 0.0279048943 0.0018007271 0.043657707 3.870509e-02
## 2014-09-30 -0.0061674913 -0.0808570067 -0.0395986396 -0.061260029 -1.389279e-02
## 2014-10-31 0.0105851858 0.0140965659 -0.0026547315 0.068874496 2.327762e-02
## 2014-11-28 0.0065487496 -0.0155412963 0.0006250717 0.004773802 2.710162e-02
## 2014-12-31 0.0014749274 -0.0404422264 -0.0407467308 0.025295892 -2.539875e-03
## 2015-01-30 0.0203147686 -0.0068954969 0.0062265872 -0.054628257 -3.007700e-02
## 2015-02-27 -0.0089881425 0.0431360138 0.0614506124 0.056914874 5.468202e-02
## 2015-03-31 0.0037409929 -0.0150864834 -0.0143889400 0.010156453 -1.583005e-02
## 2015-04-30 -0.0032334867 0.0662814223 0.0358167361 -0.018417599 9.785645e-03
## 2015-05-29 -0.0043836244 -0.0419110200 0.0019527233 0.007509579 1.277421e-02
## 2015-06-30 -0.0108257805 -0.0297468486 -0.0316788228 0.004171458 -2.052136e-02
## 2015-07-31 0.0085850777 -0.0651778992 0.0201144044 -0.027375123 2.233786e-02
## 2015-08-31 -0.0033635070 -0.0925122731 -0.0771524036 -0.047268574 -6.288684e-02
## 2015-09-30 0.0080812418 -0.0318249209 -0.0451949791 -0.038464378 -2.584681e-02
## 2015-10-30 0.0006853211 0.0618082331 0.0640259730 0.063589312 8.163501e-02
## 2015-11-30 -0.0038984014 -0.0255604713 -0.0075557984 0.024415388 3.648306e-03
## 2015-12-31 -0.0019187549 -0.0389470337 -0.0235951109 -0.052157112 -1.743356e-02
## 2016-01-29 0.0123299744 -0.0516368254 -0.0567579081 -0.060306948 -5.106835e-02
## 2016-02-29 0.0088316178 -0.0082113800 -0.0339139958 0.020605483 -8.265146e-04
## 2016-03-31 0.0087087865 0.1218787762 0.0637458709 0.089910262 6.510017e-02
## 2016-04-29 0.0025458871 0.0040794826 0.0219751824 0.021044146 3.933410e-03
## 2016-05-31 0.0001358556 -0.0376286433 -0.0008561299 0.004397100 1.686853e-02
## 2016-06-30 0.0191670016 0.0445823386 -0.0244915362 0.008292486 3.469985e-03
## 2016-07-29 0.0054291370 0.0524422848 0.0390002796 0.049347963 3.582190e-02
## 2016-08-31 -0.0021562545 0.0087985997 0.0053269447 0.011261358 1.196701e-03
## 2016-09-30 0.0005159284 0.0248728717 0.0132789127 0.008614720 5.828014e-05
## 2016-10-31 -0.0082053628 -0.0083123122 -0.0224035856 -0.038134891 -1.748908e-02
## 2016-11-30 -0.0259897704 -0.0451617714 -0.0179744820 0.125246544 3.617604e-02
## 2016-12-30 0.0025381246 -0.0025301382 0.0267027783 0.031491782 2.006896e-02
## 2017-01-31 0.0021264221 0.0644316436 0.0323818793 -0.012143782 1.773656e-02
## 2017-02-28 0.0064378151 0.0172574827 0.0118365508 0.013428484 3.853930e-02
## 2017-03-31 -0.0005522683 0.0361893362 0.0318056345 -0.006532707 1.248925e-03
## 2017-04-28 0.0090288038 0.0168660615 0.0239522905 0.005107417 9.877367e-03
## 2017-05-31 0.0068471308 0.0280602104 0.0348101850 -0.022862697 1.401422e-02
## 2017-06-30 -0.0001822873 0.0092238728 0.0029558548 0.029151949 6.354611e-03
## 2017-07-31 0.0033342493 0.0565943318 0.0261880794 0.007481562 2.034571e-02
## 2017-08-31 0.0093691464 0.0232437740 -0.0004485032 -0.027564590 2.913491e-03
## 2017-09-29 -0.0057318311 -0.0004460965 0.0233428450 0.082321441 1.994900e-02
## 2017-10-31 0.0009775887 0.0322785683 0.0166534617 0.005916043 2.329077e-02
## 2017-11-30 -0.0014838910 -0.0038969517 0.0068701733 0.036913125 3.010798e-02
## 2017-12-29 0.0047402086 0.0369251093 0.0133983369 -0.003730867 1.205551e-02
# Covariance of asset returns
covariance_matrix <- cov(asset_returns_wide_tbl)
covariance_matrix
## AGG EEM EFA IJS SPY
## AGG 7.398403e-05 0.0001042088 4.178258e-05 -7.811671e-05 -9.029471e-06
## EEM 1.042088e-04 0.0017547094 1.039018e-03 6.437712e-04 6.795438e-04
## EFA 4.178258e-05 0.0010390179 1.064239e-03 6.490304e-04 6.975432e-04
## IJS -7.811671e-05 0.0006437712 6.490304e-04 1.565448e-03 8.290255e-04
## SPY -9.029471e-06 0.0006795438 6.975432e-04 8.290255e-04 7.408313e-04
# Standard deviation of portfolio
# Summarizes how much each asset's returns vary with those of other assets within the portfolio into a single number
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.02347491
# Component contribution
# Similar to the formula for sd_portfolio
# Mathematical trick to summarize the same, sd_portfolio, by asset instead of a single number
component_contribution <- (t(w) %*% covariance_matrix * w) / sd_portfolio[1,1]
component_contribution
## AGG EEM EFA IJS SPY
## [1,] 0.0003874183 0.009257134 0.005815641 0.005684466 0.002330255
rowSums(component_contribution)
## [1] 0.02347491
# Component contribution in percentage
component_percentages <- (component_contribution / sd_portfolio[1,1]) %>%
round(3) %>%
as_tibble()
component_percentages
## # A tibble: 1 × 5
## AGG EEM EFA IJS SPY
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.017 0.394 0.248 0.242 0.099
component_percentages %>%
as_tibble() %>%
gather(key = "asset", value = "contribution")
## # A tibble: 5 × 2
## asset contribution
## <chr> <dbl>
## 1 AGG 0.017
## 2 EEM 0.394
## 3 EFA 0.248
## 4 IJS 0.242
## 5 SPY 0.099
# Transform data into wide form
asset_returns_wide_tbl <- asset_returns_tbl %>%
pivot_wider(names_from = asset, values_from = returns) %>%
column_to_rownames(var = "date")
asset_returns_wide_tbl
## AGG EEM EFA IJS SPY
## 2013-01-31 -0.0062311778 -0.0029354630 0.0366063983 0.052133418 4.992310e-02
## 2013-02-28 0.0058915923 -0.0231053436 -0.0129694779 0.016175507 1.267840e-02
## 2013-03-28 0.0009847549 -0.0102350107 0.0129694779 0.040258020 3.726786e-02
## 2013-04-30 0.0096387911 0.0120849040 0.0489678045 0.001222381 1.903017e-02
## 2013-05-31 -0.0202136325 -0.0494836088 -0.0306557725 0.041976433 2.333516e-02
## 2013-06-28 -0.0157785484 -0.0547281409 -0.0271445664 -0.001403003 -1.343435e-02
## 2013-07-31 0.0026884075 0.0131592640 0.0518606176 0.063541391 5.038668e-02
## 2013-08-30 -0.0082985000 -0.0257054296 -0.0197464637 -0.034743613 -3.045244e-02
## 2013-09-30 0.0111441585 0.0695887308 0.0753385871 0.063874036 3.115667e-02
## 2013-10-31 0.0082913747 0.0408614200 0.0320814768 0.034233800 4.526645e-02
## 2013-11-29 -0.0025093823 -0.0025941418 0.0054498606 0.041661124 2.920690e-02
## 2013-12-31 -0.0055832953 -0.0040743622 0.0215281319 0.012892056 2.559620e-02
## 2014-01-31 0.0152914662 -0.0903223827 -0.0534132981 -0.035775224 -3.588433e-02
## 2014-02-28 0.0037571357 0.0332205366 0.0595049263 0.045257418 4.451010e-02
## 2014-03-31 -0.0014816571 0.0380216407 -0.0046025666 0.013315272 8.261429e-03
## 2014-04-30 0.0081830915 0.0077727427 0.0165294466 -0.023184200 6.927661e-03
## 2014-05-30 0.0117220573 0.0290911914 0.0158280491 0.006205220 2.294122e-02
## 2014-06-30 -0.0005757154 0.0237336143 0.0091655596 0.037718802 2.043440e-02
## 2014-07-31 -0.0025128264 0.0135559023 -0.0263796333 -0.052009583 -1.352881e-02
## 2014-08-29 0.0114308629 0.0279048943 0.0018007271 0.043657707 3.870509e-02
## 2014-09-30 -0.0061674913 -0.0808570067 -0.0395986396 -0.061260029 -1.389279e-02
## 2014-10-31 0.0105851858 0.0140965659 -0.0026547315 0.068874496 2.327762e-02
## 2014-11-28 0.0065487496 -0.0155412963 0.0006250717 0.004773802 2.710162e-02
## 2014-12-31 0.0014749274 -0.0404422264 -0.0407467308 0.025295892 -2.539875e-03
## 2015-01-30 0.0203147686 -0.0068954969 0.0062265872 -0.054628257 -3.007700e-02
## 2015-02-27 -0.0089881425 0.0431360138 0.0614506124 0.056914874 5.468202e-02
## 2015-03-31 0.0037409929 -0.0150864834 -0.0143889400 0.010156453 -1.583005e-02
## 2015-04-30 -0.0032334867 0.0662814223 0.0358167361 -0.018417599 9.785645e-03
## 2015-05-29 -0.0043836244 -0.0419110200 0.0019527233 0.007509579 1.277421e-02
## 2015-06-30 -0.0108257805 -0.0297468486 -0.0316788228 0.004171458 -2.052136e-02
## 2015-07-31 0.0085850777 -0.0651778992 0.0201144044 -0.027375123 2.233786e-02
## 2015-08-31 -0.0033635070 -0.0925122731 -0.0771524036 -0.047268574 -6.288684e-02
## 2015-09-30 0.0080812418 -0.0318249209 -0.0451949791 -0.038464378 -2.584681e-02
## 2015-10-30 0.0006853211 0.0618082331 0.0640259730 0.063589312 8.163501e-02
## 2015-11-30 -0.0038984014 -0.0255604713 -0.0075557984 0.024415388 3.648306e-03
## 2015-12-31 -0.0019187549 -0.0389470337 -0.0235951109 -0.052157112 -1.743356e-02
## 2016-01-29 0.0123299744 -0.0516368254 -0.0567579081 -0.060306948 -5.106835e-02
## 2016-02-29 0.0088316178 -0.0082113800 -0.0339139958 0.020605483 -8.265146e-04
## 2016-03-31 0.0087087865 0.1218787762 0.0637458709 0.089910262 6.510017e-02
## 2016-04-29 0.0025458871 0.0040794826 0.0219751824 0.021044146 3.933410e-03
## 2016-05-31 0.0001358556 -0.0376286433 -0.0008561299 0.004397100 1.686853e-02
## 2016-06-30 0.0191670016 0.0445823386 -0.0244915362 0.008292486 3.469985e-03
## 2016-07-29 0.0054291370 0.0524422848 0.0390002796 0.049347963 3.582190e-02
## 2016-08-31 -0.0021562545 0.0087985997 0.0053269447 0.011261358 1.196701e-03
## 2016-09-30 0.0005159284 0.0248728717 0.0132789127 0.008614720 5.828014e-05
## 2016-10-31 -0.0082053628 -0.0083123122 -0.0224035856 -0.038134891 -1.748908e-02
## 2016-11-30 -0.0259897704 -0.0451617714 -0.0179744820 0.125246544 3.617604e-02
## 2016-12-30 0.0025381246 -0.0025301382 0.0267027783 0.031491782 2.006896e-02
## 2017-01-31 0.0021264221 0.0644316436 0.0323818793 -0.012143782 1.773656e-02
## 2017-02-28 0.0064378151 0.0172574827 0.0118365508 0.013428484 3.853930e-02
## 2017-03-31 -0.0005522683 0.0361893362 0.0318056345 -0.006532707 1.248925e-03
## 2017-04-28 0.0090288038 0.0168660615 0.0239522905 0.005107417 9.877367e-03
## 2017-05-31 0.0068471308 0.0280602104 0.0348101850 -0.022862697 1.401422e-02
## 2017-06-30 -0.0001822873 0.0092238728 0.0029558548 0.029151949 6.354611e-03
## 2017-07-31 0.0033342493 0.0565943318 0.0261880794 0.007481562 2.034571e-02
## 2017-08-31 0.0093691464 0.0232437740 -0.0004485032 -0.027564590 2.913491e-03
## 2017-09-29 -0.0057318311 -0.0004460965 0.0233428450 0.082321441 1.994900e-02
## 2017-10-31 0.0009775887 0.0322785683 0.0166534617 0.005916043 2.329077e-02
## 2017-11-30 -0.0014838910 -0.0038969517 0.0068701733 0.036913125 3.010798e-02
## 2017-12-29 0.0047402086 0.0369251093 0.0133983369 -0.003730867 1.205551e-02
calculate_component_contribution <- function(.data,w) {
# Covariance of asset returns
covariance_matrix <- cov(.data)
# Standard deviation of portfolio
# Summarizes how much each asset's returns vary with those of other assets within the portfolio into a single number
sd_portfolio <- sqrt(t(w) %*% covariance_matrix %*% w)
# Component contribution
# Similar to the formula for sd_portfolio
# Mathematical trick to summarize the same, sd_portfolio, by asset instead of a single number
component_contribution <- (t(w) %*% covariance_matrix * w) / sd_portfolio[1,1]
component_contribution
rowSums(component_contribution)
# Component contribution in percentage
component_percentages <- (component_contribution / sd_portfolio[1,1]) %>%
round(3) %>%
as_tibble()
return (component_percentages)
}
Column chart of component contribution
plot_data <- asset_returns_wide_tbl %>%
calculate_component_contribution(w = c(.25, .25, .2, .2, .1)) %>%
pivot_longer(cols = everything(), names_to = "asset", values_to = "Contribution")
plot_data %>%
ggplot(aes(x = asset, y = Contribution)) +
geom_col(fill = "cornflowerblue") +
scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
theme(plot.title = element_text(hjust = 0.5)) +
labs(title = "Percent contribution to portfolio volatility")
#Column chart of component contribution and weight
plot_data <- asset_returns_wide_tbl %>%
calculate_component_contribution(w = c(.25, .25, .2, .2, .1)) %>%
pivot_longer(cols = everything(), names_to = "Asset", values_to = "Contribution") %>%
add_column(weight = c(.25, .25, .2, .2, .1)) %>%
# Transform to long
pivot_longer(cols = c(Contribution, weight), names_to = "type", values_to = "Value")
plot_data %>%
ggplot(aes(x = Asset, y = Value, fill = type)) +
geom_col(position = "dodge") +
scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
scale_fill_tq() +
theme(plot.title = element_text(hjust = 0.5)) +
theme_tq() +
labs(title = "Percent contribution to portfolio volatility and Weight",
y = "Percent",
x = NULL)