# 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 2012-12-31 to present
symbols <- c("AAPL", "MSFT", "JPM", "XOM", "WMT")
prices <- tq_get(x = symbols,
get = "stock.prices",
from = "2012-12-31",
to = Sys.Date())
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] "AAPL" "JPM" "MSFT" "WMT" "XOM"
# weights
weights <- c(0.30, 0.25, 0.20, 0.15, 0.10)
weights
## [1] 0.30 0.25 0.20 0.15 0.10
w_tbl <- tibble(symbols, weights)
w_tbl
## # A tibble: 5 × 2
## symbols weights
## <chr> <dbl>
## 1 AAPL 0.3
## 2 JPM 0.25
## 3 MSFT 0.2
## 4 WMT 0.15
## 5 XOM 0.1
# ?tq_portfolio
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: 166 × 2
## date returns
## <date> <dbl>
## 1 2013-01-31 -0.0150
## 2 2013-02-28 0.00818
## 3 2013-03-28 0.00896
## 4 2013-04-30 0.0433
## 5 2013-05-31 0.0432
## 6 2013-06-28 -0.0491
## 7 2013-07-31 0.0492
## 8 2013-08-30 -0.00494
## 9 2013-09-30 -0.000855
## 10 2013-10-31 0.0508
## # ℹ 156 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 0.342
# 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)
# Plot
rolling_kurt_tbl %>%
ggplot(aes(x = date, y = Kurt)) +
geom_line(color = "cornflowerblue") +
# Formatting
scale_y_continuous(breaks = seq(-1, 4, 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("2020-07-01"), y = 2.5,
size = 4, color = "red",
hjust = 0.5,
label = "Kurtosis fluctuated over time,\nwith noticeable spikes in 2019 and 2025-2026")
Has the downside risk of your portfolio increased or decreased over time? Explain using the plot you created. You may also refer to the skewness of the returns distribution you plotted in the previous assignment.
The portfolio’s downside risk has fluctuated over time rather than consistently increasing or decreasing. Rolling kurtosis fell below -1 around 2016, then increased sharply around 2019 and again in 2025–2026, reaching approximately 1.3. These spikes suggest periods when extreme returns became more likely. Although kurtosis has recently decreased to around 0.1, it remains higher than some earlier periods. Overall, the portfolio has experienced changing levels of tail risk, but kurtosis alone cannot determine whether those extreme returns were positive or negative.