# Load packages
# Core
library(tidyverse)
library(tidyquant)
Visualize and examine changes in the underlying trend in the downside risk of your portfolio in terms of kurtosis.
Choose your stocks.
from 2017-12-31 to 2022-12-31
# Choose stocks
symbols <- c("MSFT", "JPM", "GM", "TMUS", "IRVRF")
prices <- tq_get(x = symbols,
get = "stock.prices",
from = "2017-12-31",
to = "2022-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"))
# symbols
symbols <- asset_returns_tbl %>% distinct(asset) %>% pull()
symbols
## [1] "GM" "IRVRF" "JPM" "MSFT" "TMUS"
# weights
weights <- c(0.25, 0.25, 0.2, 0.2, 0.1)
weights
## [1] 0.25 0.25 0.20 0.20 0.10
w_tbl <- tibble(symbols, weights)
w_tbl
## # A tibble: 5 × 2
## symbols weights
## <chr> <dbl>
## 1 GM 0.25
## 2 IRVRF 0.25
## 3 JPM 0.2
## 4 MSFT 0.2
## 5 TMUS 0.1
portfolio_returns_tbl <- asset_returns_tbl %>%
tq_portfolio(assets_col = asset,
returns_col = returns,
weights = w_tbl,
rebalance_on = "months",
col_rename = "returns")
portfolio_returns_tbl
## # A tibble: 59 × 2
## date returns
## <date> <dbl>
## 1 2018-02-28 0.0296
## 2 2018-03-29 -0.0283
## 3 2018-04-30 0.0459
## 4 2018-05-31 0.00510
## 5 2018-06-29 -0.0272
## 6 2018-07-31 -0.00462
## 7 2018-08-31 0.0213
## 8 2018-09-28 -0.0278
## 9 2018-10-31 0.0614
## 10 2018-11-30 0.0806
## # … with 49 more rows
portfolio_kurt_tidyquant_builtin_percent <- portfolio_returns_tbl %>%
tq_performance(Ra = returns,
performance_fun = table.Stats) %>%
select(Kurtosis)
portfolio_kurt_tidyquant_builtin_percent
## # A tibble: 1 × 1
## Kurtosis
## <dbl>
## 1 1.73
# Assign a value for window
window = 24
# Transform data: calculate 24 month rolling kurtosis
rolling_kurt_tbl <- portfolio_returns_tbl %>%
tq_mutate(select = returns,
mutate_fun = rollapply,
width = window,
FUN = kurtosis,
col_rename = "kurt") %>%
na.omit() %>%
select(-returns)
rolling_kurt_tbl
## # A tibble: 36 × 2
## date kurt
## <date> <dbl>
## 1 2020-01-31 -0.782
## 2 2020-02-28 0.268
## 3 2020-03-31 3.40
## 4 2020-04-30 2.87
## 5 2020-05-29 2.81
## 6 2020-06-30 3.03
## 7 2020-07-31 3.16
## 8 2020-08-31 3.09
## 9 2020-09-30 2.47
## 10 2020-10-30 2.38
## # … with 26 more rows
# Plot
rolling_kurt_tbl %>%
ggplot(aes(x = date, y = kurt)) +
geom_line(color = "cornflowerblue") +
# Formatting
scale_y_continuous(breaks = seq(-1, 6, 0.5)) +
scale_x_date(breaks = scales::pretty_breaks(n = 7)) +
theme(plot.title = element_text(hjust = 0.5)) +
#Labeling
labs(x = NULL,
y = "Kurtosis",
title = paste0("Rolling ", window, " Month Kurtosis")) +
annotate(geom = "text", x = as.Date("2021-07-31"), y = 1,
size = 5, color = "red",
label = str_glue("Downside risk plummeted
in the first quarter of 2022"))
# Data transformation: calculate skewness
asset_skewness_tbl <- asset_returns_tbl %>%
group_by(asset) %>%
summarise(skew = skewness(returns)) %>%
ungroup() %>%
# Add portfolio skewness
add_row(tibble(asset = "Portfolio",
skew = skewness(portfolio_returns_tbl$returns)))
asset_skewness_tbl
## # A tibble: 6 × 2
## asset skew
## <chr> <dbl>
## 1 GM -0.303
## 2 IRVRF -0.376
## 3 JPM -0.339
## 4 MSFT -0.129
## 5 TMUS 0.363
## 6 Portfolio -0.882
# Plot skewness
asset_skewness_tbl %>%
ggplot(aes(x = asset, y = skew, color = asset)) +
geom_point() +
ggrepel::geom_text_repel(aes(label = asset),
data = asset_skewness_tbl %>%
filter(asset == "Portfolio")) +
labs(y = "skewness")
# Plot distribution of returns
asset_returns_tbl %>%
ggplot(aes(x = returns)) +
geom_density(aes(color = asset), show.legend = FALSE, alpha = 1) +
geom_histogram(aes(fill = asset), show.legend = FALSE, alpha = 0.3, binwidth = 0.01) +
facet_wrap(~asset, ncol = 1, scales = "free_y") +
# Labeling
labs(title = "Distribution of Monthly Returns, 2017-2022",
y = "Frequency",
x = "Rate of Returns")
```
The portfolio presented has downside risk that has slightly improved in the previous year. During the pandemic, the portfolios kurtosis drastically increased, indicating that the distribution of returns had a high degree of risk. These investments had high probabilities of extremely large and extremely small returns, which caused the asymetry seen in the portfolios overall skenwess. The returns data now follows a trend that shows the portfolio having negatively skewed distribution and a small kurtosis. The small kurtosis signals a moderate level of risk because the probabilities of extreme return outliers are relatively low, which could be considered an improvement to the downside risk seen in prior years. The decrease in the fatness of the tails however, does not mean that the weight to the left side of the distribution is no longer present. While historical data shows unattractive prospects for the portfolio, the investments would make more consistent returns now, than they did over the last 24 months.