How to compute the tangency portfolio

Author

Enrico Schumann

Keywords

portfolio optimisation

Review Status

draft

Introduction

The tangency portfolio is the portfolio that maximises the Sharpe ratio, ie, it is obtained from

(1)
\begin{split} \max_{w} \frac{\mu'w-r_f}{\sqrt{w' \Sigma w}}\\ w'\iota = 1 \end{split}

where $w$ is the vector of portfolio weights, $\Sigma$ is the variance-covariance matrix of the assets, and $\iota$ is an appropriately-sized vector of ones. The vector $\mu$ holds the assets' means, $$r_f$$ is the riskfree rate (assumed to be a constant). There are no further constraints on the problem, in particular, short sales are allowed here.

The optimisation makes sense only if there exists at least ones portfolio for which $\mu'w$ is larger than $r_f$; otherwise, excess return is negative and no one would want to hold risky assets.

Using a QP solver

R

We use the quadprog package for R (see the references below).

require(quadprog)

# create artifical data
nO     <- 100     # number of observations
nA     <- 10      # number of assets
mData  <- array(rnorm(nO * nA, mean = 0.001, sd = 0.01), dim = c(nO, nA))
rf     <- 0.0001     # riskfree rate (2.5% pa)
mu     <- apply(mData, 2, mean)    # means
mu2    <- mu - rf                  # excess means

# qp
aMat  <- as.matrix(mu2)
bVec  <- 1
zeros <- array(0, dim = c(nA,1))
solQP <- solve.QP(cov(mData), zeros, aMat, bVec, meq = 1)

# rescale variables to obtain weights
w <- as.matrix(solQP$solution/sum(solQP$solution))

# compute sharpe ratio
SR <- t(w) %*% mu2 / sqrt(t(w) %*% cov(mData) %*% w)

A regression representation

Britten-Jones [1] showed that the same results can be obtained by running the following regression

(2)
\begin{align} 1 = Xw + \varepsilon\,. \end{align}

Here $1$ is a vector of ones, $X$ holds in its columns the excess returns of the assets (each row is one observation), and $\varepsilon$ holds the remaining errors.

The obtained regression weights need to be rescaled, ie,

(3)
\begin{align} w_i = \frac{w_i}{\sum w} \quad \text{for all $i$}\,. \end{align}

R

# (...continued)

##
# regression

# compute excess returns
X     <- mData - rf
ones     <- array(1, dim = c(100,1))

# run regression
solR     <- lm(ones~-1 + X)

# rescale 
w2 <- coef(solR)
w2 <- w2/sum(w2)

Solving a system of linear equations

The weights can also be found by solving a system of linear equations.

R

# (...continued)

# solve
w3 <- solve(cov(mData),mu2)

# rescale
w3 <- w3/sum(w3)

All three methods should give the same results:

# (...continued)

#qp
as.vector(w)

# regression
as.vector(w2)

# linear equations
as.vector(w3)

# check
all.equal(as.vector(w),as.vector(w2))
all.equal(as.vector(w),as.vector(w3))
all.equal(as.vector(w2),as.vector(w3))

Internal Links

Concepts
Tutorials
How to compute the global minimum-variance portfolio
Tips
Related Articles

External links

References
1. Britten-Jones, M. (1999). The Sampling Error in Estimates of Mean-Variance Efficient Portfolio Weights. Journal of Finance 64, 655-671.
2. Gilli, M., D. Maringer and E. Schumann. (2011). Numerical Methods and Optimization in Finance. Elsevier.
3. R Development Core Team (2008). R: A Language and Environment for Statistical Computing. R Foundation for Statistical Computing. http://www.R-project.org.
4. Turlach, B.A. [S original] and A. Weingessel [R port] (2007). quadprog: Functions to solve Quadratic Programming Problems. R package version 1.4-11. available from CRAN.
Weblinks

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License