library(xts)
library(quantmod)
library(PerformanceAnalytics)
library(portfolioBacktest)
library(CVXR)
library(DT)Backtesting Risk-Based Portfolios
Overview
The project consists of empirically testing the performance of selected portfolio risk based investment strategies.
Tasks
Download monthly market data for S&P500 listed stocks from 01-01-2010 to 31-12-2022.
Generate 100 random resamples of 20 S&P500 listed stocks and 3 consecutive data.
Empirically investigate the performance of the following traditional and risk-based portfolios.
- Global Minimum-Variance Portfolio with no short-selling
- Inverse Volatility Portfolio
- Risk parity portfolio
- Most diversified portfolio
- Maximum decorrelation portfolio
- Hierarchical Risk Parity Portfolio
- Markowitz's mean-variance portfolio (MVP) with no short-selling
Critically discuss the results considering alternative risk-adjusted performance metrics (e.g., returns, volatility, Sharpe ratio, Sterling ratio, drawdown).
Extra Points: Use the same data set to investigate the performance of portfolio management strategies using alternative risk measures, e.g., downside risk, value-at-risk (VaR),Conditional VaR (CVaR) or expected shortfall (ES).
Loading Essential Libraries
Loading Data
startDate <- "2010-01-01"
endDate <- "2022-12-31"
data(SP500_symbols)
sp500 <- stockDataDownload(stock_symbols = SP500_symbols, from=startDate,to=endDate, periodicity="monthly")Loading stock data from local file /Users/vivekraj/Coding/R/Asset Pricing & Portfolio Management/stockdata_from_2010-01-01_to_2022-12-31_(065fe3c9e1991cd1ec13c8d1c18d3e2c).RData
Generate Random Re-samples
# 100 random resamples of 20 S&P500 listed stocks and 3 consecutive data.
set.seed(100)
dataset_list <- financialDataResample(sp500, # dataset
N_sample = 20, # Desired number of financial instruments in each resample
T_sample = 12*3, # Desired length of each resample (consecutive samples with a random initial time)
num_datasets = 100) # Number of resampled datasets100 datasets resampled (with N = 20 instruments and length T = 36) from the original data between 2010-01-01 and 2022-12-01.
head(dataset_list$`dataset 1`$adjusted, 3) RHI CMA HOLX UAL ABMD NOC PNR CHD
2016-02-01 33.57555 25.51389 34.63 57.26 80.01 169.9190 28.01455 40.87451
2016-03-01 39.92841 28.60306 34.50 59.86 94.81 175.6796 31.86062 41.68137
2016-04-01 32.83937 33.72963 33.59 45.81 97.14 183.1010 34.10365 41.91650
FTI ADBE IT NTAP TJX NI ETN MTD
2016-02-01 17.01593 85.15 82.40 20.15832 33.17339 16.80483 46.49743 314.91
2016-03-01 18.97904 93.80 89.35 22.14656 35.18468 18.56609 51.29395 344.76
2016-04-01 21.15026 94.22 87.17 19.18448 34.04853 17.89626 52.39142 357.95
LIN PAYX HRB APTV
2016-02-01 87.85804 41.05777 23.91893 53.21378
2016-03-01 98.78529 43.15101 19.21953 60.16710
2016-04-01 102.11877 41.64100 14.82948 59.05230
Defining the Portfolios
1. Global Minimum-Variance Portfolio with no short-selling
# Global Minimum-Variance Portfolio with no short-selling
gmvp_portfolio_fn <- function(dataset,...) {
X <- diff(log(dataset$adjusted))[-1] # computed the log-returns
sigma <- cov(X) # computed the covariance matrix
w <- solve(sigma,rep(1, nrow(sigma)))
w <- abs(w)/sum(abs(w)) # normalize the weights so that they sum up to 1
return(w)
}2. Inverse Volatility Portfolio
inv_vol_portfolio_fn <- function(dataset, ...) {
X <- diff(log(dataset$adjusted))[-1] # computed the log-returns
volatility <- sd(X)
w <- 1/volatility
w <- abs(w)/sum(abs(w))
return(w)
}3. Risk Parity Portfolio
risk_parity_portfolio_fn <- function(dataset, ...) {
X <- diff(log(dataset$adjusted))[-1] # computed the log-returns
sigma <- cov(X) # computed the covariance matrix
risk_contribution <- sqrt(diag(sigma) %*% X)
w <- 1/risk_contribution
w <- abs(w)/sum(abs(w))
return(w)
}4. Most Diversified Portfolio
most_diverse_portfolio_fn <- function(dataset, ...) {
X <- diff(log(dataset$adjusted))[-1] # computed the log-returns
# Calculate the correlation matrix
corr_mat <- cor(X)
# Calculate the inverse correlation matrix
inv_corr_mat <- solve(corr_mat)
w <- inv_corr_mat %*% rep(1, ncol(X))
w <- abs(w)/sum(abs(w))
return(w)
}5. Maximum Decorrelation Portfolio
max_deco_portfolio_fn <- function(dataset, ...) {
}