# Problem with calculating tangency portfolio

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")

#*********************************************
# Importing the data and selecting the time window
#*********************************************

# 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")

data = ts((data[,11:20]/100), start=c(1926,7), frequency = 12)

asset.names = colnames(data)

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! Hi, and welcome!

Preliminarily, while the code blocks are helpful, they aren't quite a reproducible example, called a reprex, which is always helpful in attracting more and better answers.

In this case, however, it seems pretty clear that differences with the `FALSE` condition in `tanportfolio()` vs. w.tanportfolio <- tanportfolio(er, covmat, Rf , shorts=FALSE) is due to some difference in the datasets passed to the `er` argument, but I have no way of testing that.

2 Likes

Thank you for answering! Which one is `er`? If it's constructed from two or more of the files, can you post a `reprex` with the code, assuming the data linked to is in the working directory?