# Load packages
library(tidyverse)
library(tidyquant)
library(moments)
library(ggrepel)
library(scales)
library(stringr)
library(timetk)
library(PerformanceAnalytics)

1. Import Prices

symbols <- c("AAPL", "MSFT", "GOOG", "AMZN", "TSLA", "NFLX")

prices <- tq_get(
  x = symbols,
  get = "stock.prices",
  from = "2012-01-01",
  to   = "2022-12-31"
)

2. Convert to Monthly log Returns

asset_returns_tbl <- prices %>%
  group_by(symbol) %>%
  tq_transmute(select = adjusted,
               mutate_fun = periodReturn,
               period = "monthly",
               type = "log") %>%
  ungroup()
# Create portfolio returns
weights <- rep(1/6, 6)

portfolio_returns_tbl <- asset_returns_tbl %>%
  tq_portfolio(
    assets_col = symbol,
    returns_col = monthly.returns,
    weights = weights,
    col_rename = "returns"
  )
# Step 1: Calculate kurtosis for the portfolio
portfolio_kurt_tbl <- portfolio_returns_tbl %>%
  tq_performance(Ra = returns, performance_fun = table.Stats) %>%
  select(Kurtosis)
# Step 2: Histogram of portfolio returns
portfolio_returns_tbl %>%
  ggplot(aes(x = returns)) +
  geom_histogram(binwidth = 0.01, fill = "cornflowerblue", alpha = 0.5) +
  geom_vline(xintercept = 0.0003, color = "green", size = 1) +
  annotate("text", x = 0.0015, y = 13, label = "Risk-free rate", angle = 90)

Step 3: Scatterplot of Expected Return vs. Kurtosis

mean_kurt_tbl <- asset_returns_tbl %>%
  group_by(symbol) %>%
  summarise(mean = mean(monthly.returns),
            kurt = kurtosis(monthly.returns)) %>%
  ungroup()

portfolio_stats <- portfolio_returns_tbl %>%
  summarise(mean = mean(returns), kurt = kurtosis(returns)) %>%
  mutate(symbol = "portfolio")

mean_kurt_tbl <- bind_rows(mean_kurt_tbl, portfolio_stats)
# Plot
mean_kurt_tbl %>%
  ggplot(aes(x = kurt, y = mean, color = symbol)) +
  geom_point() +
  geom_text_repel(aes(label = symbol)) +
  theme(legend.position = "none") +
  labs(x = "Kurtosis", y = "Expected Return") +
  scale_y_continuous(labels = scales::percent_format(accuracy = 0.1))

Step 4: Rolling 24-Month Kurtosis Line Plot

# Define the rolling window
window <- 24

rolling_kurt_tbl <- portfolio_returns_tbl %>%
  tq_mutate(
    select     = returns,
    mutate_fun = rollapply,
    width      = window,
    FUN        = kurtosis,
    col_rename = "kurt"
  ) %>%
  na.omit() %>%
  select(date, kurt)
# Plot Rolling Kurtosis
rolling_kurt_tbl %>%
  ggplot(aes(x = date, y = kurt)) +
  geom_line(color = "cornflowerblue") +
  scale_y_continuous(breaks = seq(-1, 4, 0.5)) +
  scale_x_date(breaks = scales::pretty_breaks(n = 7)) +
  labs(
    x = NULL,
    y = "Kurtosis",
    title = paste0("Rolling ", window, " Month Kurtosis")
  ) +
  theme(plot.title = element_text(hjust = 0.5)) +
  annotate(
    "text",
    x = as.Date("2017-07-01"),
    y = 3.3,
    label = str_glue("Downside risk\nskyrocketed toward end of 2017"),
    size = 5,
    color = "red"
  )

Step 5: Rolling 24-Month Sharpe Ratio

# Define risk-free rate
risk_free_rate <- 0.0003

# Define custom function
calculate_rolling_sharpe_ratio <- function(data) {
  SharpeRatio(
    R  = data,
    Rf = risk_free_rate,
    FUN = "StdDev"
  )
}

# Calculate rolling Sharpe Ratio
rolling_sharpe_tbl <- portfolio_returns_tbl %>%
  tq_mutate(
    select     = returns,
    mutate_fun = rollapply,
    width      = window,
    FUN        = calculate_rolling_sharpe_ratio,
    col_rename = "rolling_sharpe"
  ) %>%
  na.omit() %>%
  select(date, rolling_sharpe)
# Plot Rolling Sharpe Ratio
rolling_sharpe_tbl %>%
  ggplot(aes(x = date, y = rolling_sharpe)) +
  geom_line(color = "cornflowerblue") +
  labs(
    x = NULL,
    y = "Rolling Sharpe Ratio",
    title = paste0("Rolling ", window, "-Month Sharpe Ratio")
  ) +
  annotate(
    "text",
    x = as.Date("2016-06-01"),
    y = 0.5,
    label = "This portfolio has done quite well since 2016",
    color = "red",
    size = 5
  ) +
  theme(plot.title = element_text(hjust = 0.5))