library(tidyverse)
library(lubridate)
library(scales)
library(ggrepel)
library(tidyquant)
library(jsonlite)
theme_set(theme_minimal())
invisible(Sys.setlocale("LC_TIME", "en_US.UTF-8"))

library(knitr)

library(elections)
# . $XLC, $XLY, $XLP, $XLE, $XLF, $XLV, $XLI, $XLB, $XLRE, $XLK, $XLU

sector_etfs <- tq_get(c("XLC", "XLY", "XLP", "XLE", "XLF", "XLV", "XLI", "XLB", "XLRE", "XLK", "XLU", "SPY"), from = 0) |> 
  group_by(symbol) |>
  transmute(symbol, date, r = adjusted/lag(adjusted)-1) |> 
  ungroup() |> 
  drop_na()

sector_etfs |> saveRDS("data/sector_etfs.RDS")
sector_etfs <- readRDS("data/sector_etfs.RDS")
# data(eldat)
eldat <- readRDS("data/eldat.RDS")

election_dates <- eldat |> 
  as_tibble() |> 
  filter(electionyear > 1995) |> 
  bind_rows(tibble(electionyear = 2020, presel.Date = as.Date("2020-11-03"),
                   winner = "Joe Biden", winnerparty = "Dem."))

out <- tibble()
for (i in 1:nrow(election_dates)) {
  temp <- sector_etfs |> 
    filter(date >= election_dates$presel.Date[i],
           date <= election_dates$presel.Date[i]+126) |> 
    group_by(symbol) |> 
    summarise(r = prod(1+r)-1) |> 
    mutate(electionyear = election_dates$electionyear[i],
           winner = election_dates$winner[i],
           winnerparty = election_dates$winnerparty[i])
  
  out <- bind_rows(out, temp)
}
out |> 
  ggplot(aes(y = r, fill = winnerparty, x = symbol)) +
  geom_col() +
  geom_text(aes(label = ifelse(r > 0, scales::percent(r, accuracy = 0.1), NA_character_)), 
            size = 4, nudge_y = 0.11) +
  geom_text(aes(label = ifelse(r <= 0, scales::percent(r, accuracy = 0.1), NA_character_)), 
            size = 4, nudge_y = -0.11) +
  geom_hline(yintercept = 0, linewidth = 0.2) +
  scale_fill_manual(values = c("blue", "red")) +
  scale_y_continuous(labels = scales::percent) +
  facet_wrap(~paste(electionyear, winner), ncol = 1, scales = "fixed") +
  labs(title = "Sector ETFs: US Presidential Elections",
       subtitle = "Performance 6 months after the election",
       x = "Sector ETF", y = "Return") +
  theme(legend.position = "none")

Market during presidencies

# presidents |> 
#   saveRDS("data/presidents.RDS")
# 
# spx_extended |> 
#   saveRDS("data/spx_extended.RDS")

presidents <- readRDS("data/presidents.RDS")
spx_extended <- readRDS("data/spx_extended.RDS")
df <- spx_extended %>% 
  full_join(presidents %>% 
              select(no_a, name, date = term_start, start = term_start, end = term_end, party = party_b_15_2),
            by = "date") %>% 
  arrange(date) %>% 
  mutate_if(is.character, na.locf0) %>% 
  mutate_if(is.Date, na.locf0) %>% 
  filter(!is.na(SPX)) %>% 
  mutate(p = cumprod(1+SPX)*100) %>% 
  ungroup()

df_mid <- df %>% 
  group_by(name) %>% 
  filter(row_number() == round(n()/2))

df_m <- spx_extended %>% 
  full_join(presidents %>% 
              select(name, date = term_start, start = term_start, end = term_end, party = party_b_15_2),
            by = "date") %>% 
  arrange(date) %>% 
  mutate_if(is.character, na.locf0) %>% 
  mutate_if(is.Date, na.locf0) %>% 
  filter(!is.na(SPX)) %>% 
  mutate(p = cumprod(1+SPX)*100) %>% 
  group_by(w = floor_date(date, "months")) %>% 
  filter(date == max(date)) %>% 
  ungroup()

df_m_mid <- df %>% 
  group_by(name) %>%
  mutate(r = last(p)/first(p)-1) |> 
  group_by(name) %>% 
  filter(row_number() == round(n()/2))
percent_plus_minus <- function(x, accuracy = 0.1) {
  if (x > 0) {
    paste0("+", percent(x, accuracy = accuracy))
  } else {
    percent(x, accuracy = accuracy)
  }
}
percent_plus_minus <- Vectorize(percent_plus_minus)


p <- df_m %>% 
  ggplot(aes(x = date, y = p)) +
  geom_line(aes(color = party, group = 1)) +
  geom_text_repel(data = df_m_mid, aes(label = paste0(name, "\n", percent_plus_minus(r, accuracy = 0.1))), 
                                       size = 2.5, nudge_y = 0.5, segment.alpha = 0.4) +
  # geom_text_repel(data = df_m_mid, aes(label = percent_plus_minus(r, accuracy = 0.1)), size = 2.5, nudge_y = 0.1, segment.alpha = 0.4) +
  scale_y_log10(labels = number) +
  scale_color_manual(values = c("blue","red")) +
  scale_x_date(date_breaks = "5 years", date_labels = "%Y", expand = c(0,0)) +
  labs(x = NULL, y = "S&P 500 (TR, 1928=100)", color = NULL, fill = NULL) +
  theme_minimal() +
  theme(legend.position = "top")

p

Same but with election dates

# library(elections)
# data(eldat)
# eldat |> saveRDS("data/eldat.RDS")
eldat <- readRDS("data/eldat.RDS")

election_dates <- eldat |> 
  as_tibble() |> 
  # filter(electionyear > 1995) |> 
  bind_rows(tibble(electionyear = 2020, presel.Date = as.Date("2020-11-03"),
                   winner = "Joe Biden", winnerparty = "Dem.")) |> 
  group_by(winner) |> 
  slice_head(n = 1)

election_dates <- election_dates |> 
  mutate(winner = case_when(
    winner == "Dwight Eisenhower" ~ "Dwight D. Eisenhower",
    winner == "Franklin Roosevelt" ~ "Franklin D. Roosevelt",
    winner == "Harry Truman" ~ "Harry S. Truman",
    winner == "John Kennedy" ~ "John F. Kennedy",
    winner == "Lyndon Johnson" ~ "Lyndon B. Johnson",
    winner == "Warren Harding" ~ "Warren G. Harding",
    TRUE ~ winner
  )) |> 
  arrange(presel.Date) |> 
  mutate(nextelect = lead(presel.Date)-1)

df <- spx_extended %>% 
  full_join(presidents %>% 
              left_join(election_dates, by = c("name" = "winner")) %>%
              select(no_a, name, date = presel.Date, start = presel.Date, end = nextelect, party = party_b_15_2),
            by = "date") %>% 
  arrange(date) %>% 
  mutate_if(is.character, na.locf0) %>% 
  mutate_if(is.Date, na.locf0) %>% 
  filter(!is.na(SPX)) %>% 
  mutate(p = cumprod(1+SPX)*100) %>% 
  ungroup()

df_mid <- df %>% 
  group_by(name) %>% 
  filter(row_number() == round(n()/2))

df_m <- spx_extended %>% 
  full_join(presidents %>% 
              left_join(election_dates, by = c("name" = "winner")) %>%
              select(no_a, name, date = presel.Date, start = presel.Date, end = nextelect, party = party_b_15_2),
            by = "date") %>% 
  arrange(date) %>% 
  mutate_if(is.character, na.locf0) %>% 
  mutate_if(is.Date, na.locf0) %>% 
  filter(!is.na(SPX)) %>% 
  mutate(p = cumprod(1+SPX)*100) %>% 
  group_by(w = floor_date(date, "months")) %>% 
  filter(date == max(date)) %>% 
  ungroup()

df_m_mid <- df %>% 
  group_by(name) %>%
  mutate(r = last(p)/first(p)-1) |> 
  group_by(name) %>% 
  filter(row_number() == round(n()/2))
p <- df_m %>% 
  left_join(election_dates, by = c("name" = "winner")) %>%
  ggplot(aes(x = date, y = p)) +
  geom_line(aes(color = party, group = 1)) +
  geom_text_repel(data = df_m_mid, aes(label = paste0(name, "\n", percent_plus_minus(r, accuracy = 0.1))), 
                                       size = 2.5, nudge_y = 0.5, segment.alpha = 0.4) +
  annotate("text", x = as.Date("1950-01-01"), y = 150000, label = "By election dates", 
           color = "darkred", size = 5) +
  # geom_text_repel(data = df_m_mid, aes(label = percent_plus_minus(r, accuracy = 0.1)), size = 2.5, nudge_y = 0.1, segment.alpha = 0.4) +
  scale_y_log10(labels = number) +
  scale_color_manual(values = c("blue","red")) +
  scale_x_date(date_breaks = "5 years", date_labels = "%Y", expand = c(0,0)) +
  labs(x = NULL, y = "S&P 500 (TR, 1928=100)", color = NULL, fill = NULL) +
  theme_minimal() +
  theme(legend.position = "top")

p