# Computing the minimum-variance portfolio

*This tutorial appeared originally on the COMISEF Wiki.*

## 1 The problem

The global minimum-variance (MV) portfolio is the leftmost point of the meanâ€“variance efficient frontier. It is found by choosing portfolio weights that minimise overall variance subject only to the constraint that the sum of the weights \(w\) is one. Formally,

\begin{equation} \min_{w}\ \ w' \Sigma w\\ w'\iota = 1 \end{equation}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. We do not put any further constraints on the problem; short sales, in particular, are allowed here.

As an example dataset, we create artificial returns with mean zero
(the default with `rnorm`

) and volatility 5%. (This order of magnitude
would be reasonable for monthly equity returns.) These returns are
stored in a matrix `mData`

.

nO <- 100L ## number of observations nA <- 10L ## number of assets mData <- array(rnorm(nO * nA, sd = 0.05), dim = c(nO, nA))

## 2 A quadratic-programming solution

We first use the `solve.QP`

function of package `quadprog`

(see the
references below), so we load/attach the package.

library("quadprog")

The aim will be to minimise `w %*% cov(mData) %*% w`

, subject to the
constraint that `sum(w)`

equals one.

aMat <- array(1, dim = c(1,nA)) bVec <- 1 zeros <- array(0, dim = c(nA,1)) solQP <- solve.QP(cov(mData), zeros, t(aMat), bVec, meq = 1) solQP$solution

[1] 0.07853404 0.12853164 0.14526751 0.09211099 0.11893845 [6] 0.15176486 0.12447023 0.02945822 0.06584904 0.06507502

The `quadprod`

package will minimise \(\frac{1}{2} w' \Sigma w\), i.e.
one-half of the portfolio variance (see `?solve.QP`

). Hence the
returned minimum-value will be one-half of the portfolio's
variance. Check:

all.equal(drop(var(mData %*% solQP$solution)), ## the solution, evaluated at the data 2*solQP$value) ## the solution's objective fun value times 2

[1] TRUE

This computation is also included as function `minvar`

in the NMOF
package.

require("NMOF") minvar(cov(mData), wmin = -Inf, wmax = Inf)

[1] 0.07853404 0.12853164 0.14526751 0.09211099 0.11893845 [6] 0.15176486 0.12447023 0.02945822 0.06584904 0.06507502 attr(,"variance") [1] 0.0002269999

Note that NMOF's minvar also returns the portfolio variance.

```
drop(var(mData %*% solQP$solution))
```

[1] 0.0002269999

## 3 A regression solution

The problem can also be solved as a linear regression; see Kempf and Memmel (2006). The authors show that regressing the negative excess returns of \(r_{\mathrm{n_A}} - 1\) assets on the returns of the remaining asset results in coefficients that equal the \(r_{\mathrm{n_A}} - 1\) respective portfolio weights; the remaining asset's weight is determined by the budget constraint. (Excess return here means with respect to the remaining asset.)

We run the regression

\begin{equation} r_{\mathrm{n_A}} = \alpha + w_1 (r_{\mathrm{n_A}} - r_1) + w_2 (r_{\mathrm{n_A}} - r_2) + \cdots + w_{\mathrm{n_A}-1}(r_{\mathrm{n_A}}-r_{\mathrm{n_A}-1}) + \epsilon\,, \end{equation}
in which \(r_i\) are the returns of the *i*-th asset, and \(\epsilon\) are
the errors.

From this equation, we directly obtain the weights \(w_1\) to \(w_{\mathrm{n_A}-1}\). Since the weights need to sum to unity, we have

\begin{equation} w_{\mathrm{n_A}} = 1 - \sum_{i=1}^{\mathrm{n_A}-1} w_i\,. \end{equation}Furthermore, the resulting portfolio's mean return will equal \(\alpha\) (the constant in the regression), and the portfolio's variance will equal the variance of the residuals.

## choose 1st asset as regressand y <- mData[ , 1L] ## compute minus excess returns X <- mData[ , 1L] - mData[ , 2:nA] ## run regression solR <- lm(y ~ X)

The results should be the same as the results from `quadprog`

:

cat("weights from qp\n") as.vector(solQP$solution) cat("\nweights from regression\n") as.vector(c(1 - sum(coef(solR)[-1L]), coef(solR)[-1L])) cat("\ncheck: variance of portfolio same as variance of residuals?\n") all.equal(as.numeric(var(mData %*% solQP$solution)), var(solR$residuals))

weights from qp [1] 0.07853404 0.12853164 0.14526751 0.09211099 0.11893845 [6] 0.15176486 0.12447023 0.02945822 0.06584904 0.06507502 weights from regression [1] 0.07853404 0.12853164 0.14526751 0.09211099 0.11893845 [6] 0.15176486 0.12447023 0.02945822 0.06584904 0.06507502 check: variance of portfolio same as variance of residuals? [1] TRUE

## 4 Solving a system of linear equations

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

x <- solve(cov(mData), numeric(nA) + 1) x <- x / sum(x) ## rescale so that sum(w) is 1 x

[1] 0.07853404 0.12853164 0.14526751 0.09211099 0.11893845 [6] 0.15176486 0.12447023 0.02945822 0.06584904 0.06507502

## 5 References

- Gilli, M., Maringer, D., Schumann, E. (2011) . Numerical Methods and Optimization in Finance. Elsevier/Academic Press. http://nmof.net
- Kempf, A. and C. Memmel (2006). Estimating the Global Minimum Variance Portfolio. Schmalenbach Business Review 58, 332-348.
- R Development Core Team (2008). R: A Language and Environment for Statistical Computing. R Foundation for Statistical Computing. http://www.r-project.org.
- 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.