Portfolio Optimization
Chapter 12: Graph-Based Portfolios

R code

Published

October 11, 2024

R code examples for Chapter 12 of the book:

Daniel P. Palomar (2024). Portfolio Optimization: Theory and Application. Cambridge University Press.

Loading packages

First load the packages used in the examples:

# basic finance
library(xts)                    # to manipulate time series of stock data
library(portfolioBacktest)      # to conduct backtests
library(pob)                    # book package with financial data
 
# plotting
library(ggplot2)                # for nice plots
library(ggdendro)               # to plot dendograms
library(reshape2)               # to reshape data
library(patchwork)              # for combining plots

# graphs
library(fingraph)              # to learn financial graphs

# optimization
library(CVXR)

Hierarchical clustering

Dendograms

Plots of dendrograms of S&P 500 stocks (with cut to produce four clusters):

Code
library(pob)
library(ggdendro)

# use data from package pob
data(SP500_2015to2020)
set.seed(42)
stock_prices <- tail(SP500_2015to2020$stocks[, c("MGM", "WYNN", "LVS", "CMS", "DUK", "BAC", "BK", "USB", "KMB", "PG", "FB", "AMZN", "MSFT", "GOOGL")], 200)
stock_prices <- stock_prices[, sample(ncol(stock_prices))]
X <- diff(log(stock_prices))[-1]
D <- sqrt(0.5*(1 - cor(X)))

p_single <- hclust(dist(D), method = "single") |>
  ggdendrogram(rotate = FALSE, size = 4, theme_dendro = TRUE) +
  geom_hline(yintercept = 0.66, color = "blue", linetype = "dashed") +
  theme(panel.border = element_blank(), 
        axis.text.y=element_blank()) +
  xlab(element_blank()) + ylab(element_blank()) + ggtitle("Single linkage")

p_complete <- hclust(dist(D), method = "complete") |>
  ggdendrogram(rotate = FALSE, size = 4, theme_dendro = TRUE) +
  geom_hline(yintercept = 0.72, color = "blue", linetype = "dashed") +
  theme(panel.border = element_blank(), 
        axis.text.y=element_blank()) +
  xlab(element_blank()) + ylab(element_blank()) + ggtitle("Complete linkage")

p_average <- hclust(dist(D), method = "average") |>
  ggdendrogram(rotate = FALSE, size = 4, theme_dendro = TRUE) +
  geom_hline(yintercept = 0.70, color = "blue", linetype = "dashed") +
  theme(panel.border = element_blank(), 
        axis.text.y=element_blank()) +
  xlab(element_blank()) + ylab(element_blank()) + ggtitle("Average linkage")

p_ward <- hclust(dist(D), method = "ward.D") |>
  ggdendrogram(rotate = FALSE, size = 4, theme_dendro = TRUE) +
  geom_hline(yintercept = 1.00, color = "blue", linetype = "dashed") +
  theme(panel.border = element_blank(), 
        axis.text.y=element_blank()) +
  xlab(element_blank()) + ylab(element_blank()) + ggtitle("Ward's method")

(p_single | p_complete) / (p_average | p_ward)