Hi.
I have been struggling with the implantation of tangency portfolio in R for a while now, and was hoping some of you might know the answer
This is the way my professor solved the problem, which works fine:
source("performance.r")
source("markowitz.r")
library("quadprog")
#*********************************************
# Importing the data and selecting the time window
#*********************************************
# read data
data = read.table("marketdata.txt", header=TRUE)
# construct the time series object
data <- ts(data[,2:ncol(data)], start=c(1926,1), frequency = 12)
''
# find the time index of portfolio start
year.start <- 2000
ind.start <- which(time(data) == year.start)
# you can index the columns in a ts-object by names!
r.stocks <- as.numeric(data[,"STOCKS"])
r.bonds <- as.numeric(data[,"BONDS"])
r.tbill <- as.numeric(data[,"TBILLS"])
nobs <- length(r.stocks)
#*********************************************
# Portfolio management part of the program
#*********************************************
lookback.period = 3*12 # length of lookback period in a number of months
n <- nobs - ind.start + 1 # number of monthly portfolio returns
r.tanportfolio = rep(0,n)
assets <- cbind(r.stocks, r.bonds)
for (i in 1:n) {
# find the indices of the lookback period
period.end <- ind.start + i - 2
period.start <- period.end - lookback.period + 1
if (period.start < 1) period.start <- 1 # index cannot be less than 1
# estimate the covariance matrix and mean returns
covmat <- cov(assets[period.start:period.end,])
er <- apply(assets[period.start:period.end,], 2, mean)
# get the risk-free rate of return
rf <- r.tbill[period.end+1]
Rf = rf
w.tanportfolio = tanportfolio(er, covmat, Rf , shorts=FALSE)
r.tanportfolio[i] = sum(w.tanportfolio*assets[period.end+1])
}
The problems occur when I am trying to replicate the method with another dataset:
source("performance.r")
source("markowitz.r")
source("functions.r")
source("ols.r")
library("quadprog")
data = read.csv("Portfolios_Formed_on_BE-ME.csv", header = TRUE)
data = ts((data[,11:20]/100), start=c(1926,7), frequency = 12)
asset.names = colnames(data)
factors = read.table(file="F-F_Research_Data_Factors.txt", header=TRUE)
factors = ts((factors[,2:ncol(factors)]/100), start=c(1926,7), frequency = 12)
year.start = 1964
ind.start = which(time(data) == year.start)
assets = as.matrix(data) #transform ts to a matrix
assets1 = as.numeric(assets[,1])
assets2 = as.numeric(assets[,2])
assets3 = as.numeric(assets[,3])
assets4 = as.numeric(assets[,4])
assets5 = as.numeric(assets[,5])
assets6 = as.numeric(assets[,6])
assets7 = as.numeric(assets[,7])
assets8 = as.numeric(assets[,8])
assets9 = as.numeric(assets[,9])
assets10 = as.numeric(assets[,10])
risk.free <- as.numeric(factors[,"RF"])
assets = cbind(assets1, assets2, assets3, assets4, assets5, assets6, assets7,
assets8, assets9, assets10)
nobs = length(assets1)
nAssets = ncol(assets)
lookback.period = 5*12 # length of lookback period in a number of months
n = nobs - ind.start + 1 # number of monthly portfolio returns
r.tanportfolio = rep(0,n)
for (i in 1:n) {
# find the indices of the lookback period
period.end <- ind.start + i - 2
period.start <- period.end - lookback.period + 1
if (period.start < 1) period.start <- 1 # index cannot be less than 1
# estimate the covariance matrix and mean returns
covmat <- cov(assets[period.start:period.end,])
er <- apply(assets[period.start:period.end,], 2, mean)
# get the risk-free rate of return
Rf <- risk.free[period.end+1]
w.tanportfolio = tanportfolio(er, covmat, Rf , shorts=FALSE)
r.tanportfolio[i] = sum(w.tanportfolio*assets[period.end+1])
}
The error message is as follows: Error in tanportfolio(er, covmat, Rf, shorts = FALSE) :
Risk-free rate greater than mean return on global minimum variance portfolio.
However, when i calculate the values this is not the case..
Here is the code for the tanportfolio:
tanportfolio <- function(er, covmat, Rf, shorts=TRUE) {
# computes the tangency portfolio
#
# inputs:
# er N x 1 vector of expected returns
# covmat N x N covariance matrix of returns
# r scalar, risk-free rate return
#
# output is a vector of portfolio weights
#
# check for valid inputs
#
er <- as.vector(er)
covmat <- as.matrix(covmat)
if (!is.numeric(Rf) || length(Rf) !=1)
stop("Risk-free rate is not a scalar")
if(length(er) != nrow(covmat))
stop("Mismatch in number of rows")
if(any(diag(chol(covmat)) <= 0))
stop("Covariance matrix is not positive definite")
#
# compute global minimum variance portfolio
#
w <- gmvportfolio(covmat, shorts=shorts)
if(w %*% er < Rf)
stop("Risk-free rate greater than mean return on global minimum variance portfolio")
#
# compute the weights of the tangency portfolio
#
if(shorts==TRUE){
# closed-form solutions when short sales are allowed
ones <- rep(1, nrow(covmat)) # vector of ones
covmat.inv <- solve(covmat) # inverse of covariance matrix
w <- (covmat.inv %*% (er-Rf))/as.numeric(ones %*% covmat.inv %*% (er-Rf))
w <- as.vector(w)
} else if(shorts==FALSE){
# numerical solution with no short sales
n = nrow(covmat)
Dmat <- covmat
dvec <- rep.int(0, n)
Amat <- cbind(er-Rf, diag(1,n))
bvec <- c(1, rep(0,n))
result <- solve.QP(Dmat=Dmat,dvec=dvec,Amat=Amat,bvec=bvec,meq=1)
w <- round(result$solution/sum(result$solution), 6)
} else {
stop("shorts needs to be logical. For no-shorts, shorts=FALSE.")
}
return(w)
}
Big thanks to anyone able to help!