Skip to content
All library documents

Scaling the Covariance Matrix in Quadratic Portfolio Optimization

Article Quant Q&A · Author: Zeca

Summary

The document examines whether the covariance matrix supplied to R’s quadratic programming solver should be doubled when constructing a mean-variance efficient frontier. The question arises because the solver’s objective includes a one-half factor on its quadratic term, while portfolio variance is commonly written without that factor. The discussion compares results from the solver with those from a portfolio optimization package and notes that different scaling can make reported variances differ even when returns match.

The answers offer mixed guidance on the factor of two. One says scaling the covariance matrix by a positive constant does not change the minimizing weights in the illustrated constrained problem, though it affects the objective scale; another distinguishes the optimizer’s weights from the multiplier values and argues for doubling under a particular objective convention. The practical lesson is to keep the solver objective, linear term, and reported risk calculation consistent. The examples are package-specific and do not settle every formulation or constraint setup.

Key ideas

  • Quadratic programming solvers may express the objective with a one-half factor on the quadratic term.
  • The covariance scaling must be interpreted alongside the precise mean-variance objective being optimized.
  • Multiplying the covariance matrix by a positive constant can leave minimizing portfolio weights unchanged in the described setup.
  • Reported variance is incorrect if it is calculated from a scaled matrix as though that matrix were the original covariance.
  • Solver conventions and constraints can affect how the scaling question should be resolved.

Tags

Full text
# Dmat argument in solve.QP R function: Cov or 2*Cov?


# Dmat argument in solve.QP R function: Cov or 2*Cov?












Background

My final objective is to find a portfolio located on the efficient frontier from a choice of 100 stocks from a stock index (eg. S&P500).

This efficient portfolio will be such that its variance is the same as the stock index variance. Wrapping it up, maximizing return for a given target risk.

Problem

I first learned how to use the PortfolioAnalytics package but I got an error from the function create.efficientFrontier whenever I passed the argument type="mean-StdDev" to the function.

Without a solution for the problem above, I decided to use the fPortfolio package. I got an efficient frontier but I can't get a matrix with the weights, returns and variance together so I can do a binary search on the variance column and then select the corresponding weights (maybe there is a way but I'm new to R).

Without a solution for the problem above, I decided to go straight to the solve.QP solution. I finally was able to do what I wanted in the first place.

Once I got an efficient frontier, I decided to compare it with the one I got from fPortfolio. For my surprise, the variance results differ significantly while returns are the same. Once I troubleshot, I found out that the difference was due to the Dmat argument, ie, the covariance matrix.

I'm passing Dmat <- Cov * 2 to the solve.QP function but if I instead use Dmat <- Cov then I get the same results from fPortfolio. Nothing changed, same dataset, same constraints. Obviously, the variance of the portfolios from solve.QP is twice the variance of those from fPortfolio.

I'm using the most basic default configuration in fPortfolio, i.e., only passing the returns dataset to it.

```
MV Portfolio Frontier 
 Estimator:         covEstimator 
 Solver:            solveRquadprog 
 Optimize:          minRisk 
 Constraints:       LongOnly
```

Question

I have come across some codes in the web multiplying the covariance matrix by 2 and passing this as Dmat. Yet, some other codes simply pass the covariance matrix as Dmat to the solve.QP function (i.e, without multiplying it by 2).

- Which approach is correct?

From my investigation of quadratic programming and the solve.QP function, I believe the covariance matrix must be multiplied by 2.

> The solve.QP routine implements the dual method of Goldfarb and Idnani (1982, 1983) for solving quadratic programming problems of the form min(-d^T b + 1/2 b^T D b) with the constraints A^T b >= b_0. The mean-variance optimization (efficient frontier) is a quadratic programming problem of the form min(w^T D w - q R^T w) with the constraints A^T w >= w_0. Therefore, when translating the MV objective function to the equivalent form used by solve.QP, the covariance matrix must be multiplied by 2.

However, this would imply that the code from fPortfolio is incorrect.

- Has anybody noticed this behavior of fPortfolio before?

I guess I'm missing something very basic in here!

Code

```
eff.frontier <- function (ret, max.allocation=NULL, rf=0, risk.limit=.5, risk.increment=.005)
{          
  Dmat <- 2 * cov(ret)      
  n <- ncol(Dmat)      
  Amat <- cbind(1, diag(n))
  bvec <- c(1, rep(0, n))
  meq <- 1

  if(!is.null(max.allocation)){
    Amat <- cbind(Amat, -diag(n))
    bvec <- c(bvec, rep(-max.allocation, n))
  }

  nLoops <- risk.limit / risk.increment + 1
  iLoop <- 1

  eff <- matrix(.0, nrow=nLoops, ncol=n+3)
  colnames(eff) <- c(colnames(returns), "Return", "StdDev", "SharpeRatio")

  for (i in seq(from=0, to=risk.limit, by=risk.increment))
    {
    dvec <- colMeans(ret) * i
    sol <- solve.QP(Dmat=Dmat, dvec=dvec, Amat=Amat, bvec=bvec, meq=meq)
    eff[iLoop,"StdDev"] <- sqrt(sum(sol$solution %*% colSums((Dmat * sol$solution))))
    eff[iLoop,"Return"] <- as.numeric(sol$solution %*% colMeans(ret))
	eff[iLoop,"SharpeRatio"] <- (eff[iLoop,"Return"]-rf) / eff[iLoop,"StdDev"]
	eff[iLoop,1:n] <- sol$solution
    iLoop <- iLoop+1
    }
    return(as.data.frame(eff))
}
```

## Answer by AK88 (score 1, accepted)

https://quant.stackexchange.com/a/31753

The results that you are getting from fPortfolio package are correct. And if you do not multiply your covariance matrix by 2 you will get the same result from quadprog package. So, either use fPortfolio or quadprog without 2.

"1/2" in that formula that you sited might be referring to some specific problem. However, I have also seen this multiplication by 2 approach in portfolio optimization studies. For example, Eric Zivot used this method in his materials. I do not think that this is correct. To be sure, I advise you to go through a simple example using Excel, manually completing all the step required.

EDIT:

Looked into this problem little further and tried the following code:

```
library(fPortfolio)
library(quadprog)
ret = 100 * LPP2005.RET[,1:6]
Dmat1 <- cov(ret)     
Dmat2 = 2 * cov(ret)
Dmat3 = 10 * cov(ret)
n <- ncol(Dmat)      
dvec = rep(0, n)
Amat <- cbind(rep(1, n), diag(n))
bvec <- c(1, rep(0, n))
meq <- 1
## Dmat
## n
## dvec
## Amat
## bvec
qp.out1 = solve.QP(Dmat, dvec, Amat, bvec, meq, FALSE)
qp.out2 = solve.QP(Dmat, dvec, Amat, bvec, meq, FALSE)
qp.out3 = solve.QP(Dmat, dvec, Amat, bvec, meq, FALSE)
qp.out1$solution
qp.out2$solution
qp.out3$solution
```

I got the same weights for all `Dmats`. So it looks like in getting weights multiplying your covariance matrix by a constant doesn't change the optimization result. However, when you are building your `eff.frontier` you are still passing those n times multiplied covariance matrix to get your standard deviations:

```
eff[iLoop,"StdDev"] <- sqrt(sum(sol$solution %*% colSums((Dmat * sol$solution))))
```

I think the solution is:

```
eff[iLoop,"StdDev"] <- sqrt(sum(sol$solution %*% colSums((cov(ret) * sol$solution))))
```

## Answer by Manuel Guerra (score 2)

https://quant.stackexchange.com/a/33751

Both approach gives same results for stocks weights but different results for lamda values

Correct approach is multiplying the covariance matrix by 2 but you only need stocks weights so its the same

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.