We use the following assets:
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(ggcorrplot)
library(patchwork)
# stocks (free long term sources: K.French) ok
# real estate (free long term sources: ) ok
# bonds
# gold ok
# alternatives
# stocks K.French ----
library(frenchdata)
ff_3f <- download_french_data('Fama/French 3 Factors')
stocks <- ff_3f$subsets$data[[1]] |>
mutate(date = ymd(paste0(date, "01"))) |>
mutate_if(is.numeric, function(x) x/100) |>
transmute(date, RF, Mkt = `Mkt-RF` + RF)
# real estate (REIT) ----
library(readxl)
url <- "https://www.reit.com/sites/default/files/returns/MonthlyHistoricalReturns.xls"
# download as temp file then read it
temp <- tempfile(fileext = ".xls")
download.file(url, temp, mode = "wb")
reit <- read_excel(temp,
range = "A8:B1000",
sheet = "Index Data") |>
transmute(date = floor_date(as.Date(Date), "month"),
reit = Return/100) |>
drop_na()
# gold ----
# source: https://www.investing.com/currencies/xau-usd-historical-data
gold <- read_csv("data/128-ltcorrs/gold.csv") |>
transmute(date = mdy(Date), price = Price) |>
arrange(date) |>
mutate(gold = price/lag(price)-1) |>
select(date, gold) |>
drop_na()
# bonds ----
t20 <- tq_get("DGS20", get = "economic.data", from = as.Date("1960-01-01")) |>
mutate(price = price/100)
corporate <- tq_get("DAAA", get = "economic.data", from = as.Date("1960-01-01")) |>
mutate(price = price/100)
library(treasuryTR)
# t20 |>
corporate <- corporate |>
arrange(date) |>
transmute(date, r = total_return(price, 20)) |>
drop_na() |>
group_by(date = floor_date(date, "month")) |>
summarise(r = prod(1+r)-1) |>
ungroup()
t20 <- t20 |>
arrange(date) |>
transmute(date, r = total_return(price, 20)) |>
drop_na() |>
group_by(date = floor_date(date, "month")) |>
summarise(r = prod(1+r)-1) |>
ungroup()
assets_returns <- bind_rows(stocks |>
pivot_longer(-date, names_to = "asset", values_to = "r") |>
arrange(asset, date) |>
mutate(asset = recode(asset,
Mkt = "Stocks", RF = "T-Bills")),
reit |>
transmute(date, r = reit, asset = "REITs"),
gold |>
transmute(date, r = gold, asset = "Gold"),
corporate |>
transmute(date, r = r, asset = "Bonds"),
t20 |>
transmute(date, r = r, asset = "Treasuries"))
assets_returns |> saveRDS("data/128-ltcorrs/assets_returns.RDS")
assets_returns <- readRDS("data/128-ltcorrs/assets_returns.RDS")
date_minmax <- assets_returns |>
group_by(asset) |>
summarise(min = min(date), max = max(date))
The data spans from 1983-01-01 to 2024-10-01 for Bonds, from 1970-03-01 to 2024-10-01 for Gold, from 1972-01-01 to 2024-09-01 for REITs, from 1926-07-01 to 2024-08-01 for Stocks, and from 1926-07-01 to 2024-08-01 for T-Bills.
The following heatmaps show the correlations between the assets for each decade.
plots <- list()
for (decade in c("1980s", "1990s", "2000s", "2010s", "2020s")) {
plots[[decade]] <- assets_returns |>
filter(between(year(date), as.numeric(str_sub(decade, 1, 4)), as.numeric(str_sub(decade, 1, 4))+9)) |>
pivot_wider(names_from = asset, values_from = r) |>
drop_na() |>
select(-date) |>
cor() |>
ggcorrplot(type = "lower", outline.color = "white", colors = c("blue", "white", "darkgreen"),
lab = T) +
labs(title = decade)
}
plot_a_list <- function(master_list_with_plots, no_of_rows, no_of_cols) {
patchwork::wrap_plots(master_list_with_plots,
nrow = no_of_rows, ncol = no_of_cols)
}
plot_a_list(plots, 3, 2)
On first sight, it becomes clear that the correlations have increased. While we see some purple up to the 2010s, the 2020s show a lot of green. The past four years have seen a lot of positive correlations between the asset classes.
Bonds and Treasuries have consistently strong positive correlations across all decades, especially in the 1980s, 1990s, and 2020s (with correlations above 0.9).
The correlation between Stocks and Bonds varies over the decades. In the 1980s and 1990s, the correlation was low yet positive (0.45 in the 1980s, 0.24 in the 1990s), however the correlation turned negative in the 2000s (-0.04 but -0.15 for Treasuries) and 2010s (-0.3, -0.51 for Treasuries). More recently in the 2020s, the correlation has turned positive again (0.48, 0.24 for Treasuries). This shows that the relationship between Stocks and Bonds is not stable over time. Bonds are not always a good hedge against stock market downturns.
Gold had shown low correlations with the other asset classes, the highest positive correlation being with Treasuries in the 1980s (0.35). There’s no decade with strong negative correlation to the stock market (lowest was -0.11 also in the 1980s). More recently in the 2020s, the correlation with Stocks has turned positive for all asset classes (0.26 with Stocks, 0.41 with both Bonds and Treasuries).
REITs have shown low to moderate correlations with the other asset classes. The highest positive correlation was with Stocks which seems to have increased over time (up to 0.88 in the 2020s).
The following plots show the rolling 60-month correlations between the assets.
assets_returns_wide <- assets_returns |>
pivot_wider(names_from = asset, values_from = r)
# janitor::clean_names()
correlations <- tibble()
for (asset1 in names(assets_returns_wide[-1])) {
for (asset2 in names(assets_returns_wide[-1])) {
if (asset1 != asset2) {
correlations <- bind_rows(correlations,
assets_returns_wide |>
select(date, all_of(asset1), all_of(asset2)) |>
filter(!is.na(!!as.name(asset1)),
!is.na(!!as.name(asset2))) |>
transmute(
date,
cor60 = rollapply(
data = cbind(!!sym(asset1), !!sym(asset2)),
width = 60,
FUN = function(x) cor(x[, 1], x[, 2], use = "pairwise.complete.obs"),
by.column = FALSE,
align = "right",
fill = NA
),
asset1 = asset1,
asset2 = asset2) |>
drop_na())
}
}
}
correlations |>
filter(date >= as.Date("1980-01-01")) |>
ggplot(aes(x = date, y = cor60, color = cor60, group = 1)) +
geom_line() +
geom_hline(yintercept = 0, linetype = "dashed", color = "red", size = 0.1) +
facet_grid(asset1 ~ asset2, scales = "free") +
scale_x_date(date_breaks = "10 years", date_labels = "'%y") +
scale_y_continuous(limit = c(-1, 1)) +
# "blue", "white", "darkgreen"
scale_color_gradient2(low = "blue", mid = "gray", high = "darkgreen",
midpoint = 0) +
labs(title = "Rolling 60-month correlations",
y = "Correlation", color = NULL,
x = NULL) +
theme(legend.position = "bottom")
In the chat the follows we focus on the correlation of Stocks with the other asset classes.
correlations |>
filter(date >= as.Date("1960-01-01")) |>
filter(asset1 == "Stocks") |>
ggplot(aes(x = date, y = cor60, color = asset2)) +
geom_line() +
geom_hline(yintercept = 0, linetype = "dashed", color = "red", size = 0.1) +
scale_color_manual(values = c("REITs" = "red", "Gold" = "orange", "Bonds" = "blue", "Treasuries" = "purple",
"T-Bills" = "gray")) +
scale_y_continuous(limit = c(-1, 1)) +
scale_x_date(date_breaks = "10 years", date_labels = "%Y") +
labs(title = "Rolling 60-month correlations with Stocks",
y = "Correlation",
x = NULL, color = NULL)
The chart shows the spike in correlations over the past four years. While correlations had been higher for several asset classes versus Stocks, the sudden increase is notable. Previously, we have seen increases around the Financial Crisis.
In conclusion, the correlations between asset classes have increased over the past four years. This is especially true for Stocks and REITs, Stocks and Gold, and Stocks and Bonds. The relationship between Stocks and Bonds is not stable over time. Bonds are not always a good hedge against stock market downturns. Gold has shown low correlations with the other asset classes, but these have increased recently. REITs have shown low to moderate correlations with the other asset classes, but the correlation with Stocks has increased over time.