3
$\begingroup$

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))
}
$\endgroup$
4
  • $\begingroup$ Could you tell us more about how you obtained the efficient frontier using fPortfolio? $\endgroup$
    – Bob Jansen
    Jan 1, 2017 at 17:49
  • $\begingroup$ @BobJansen, I'm using the default configuration in fPortfolio, i.e., only passing the returns data to it. $\endgroup$
    – Zeca
    Jan 1, 2017 at 19:55
  • $\begingroup$ My objective function is for the mean-variance optimal portfolio. The fPortfolio configuration I've setup is for the minimum variance portfolio which is a simplification of the previous objective function. $\endgroup$
    – Zeca
    Jan 1, 2017 at 23:50
  • $\begingroup$ Thanks for @AK88 for pointing out the issue in the calculation of the StdDev. Now my question is why using two different objective functions led to the same efficient frontier? $\endgroup$
    – Zeca
    Jan 5, 2017 at 6:05

2 Answers 2

1
$\begingroup$

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)))) 
$\endgroup$
8
  • $\begingroup$ Well, your comment is what I think as well but I just want to find a proper explanation. $\endgroup$
    – Zeca
    Jan 2, 2017 at 21:28
  • $\begingroup$ Proper explanation on why the formula has 1/2 term? Or on correctness of results? $\endgroup$
    – AK88
    Jan 3, 2017 at 0:09
  • $\begingroup$ My title question: why use cov and not cov x 2 as an argument? $\endgroup$
    – Zeca
    Jan 3, 2017 at 5:18
  • $\begingroup$ edited my answer ... $\endgroup$
    – AK88
    Jan 3, 2017 at 7:27
  • 1
    $\begingroup$ To create an efficient frontier, fPortfolio uses the same obj function min(w^T D w) but adds a new constraint into the problem which is a return target. I'm now using this method to create an efficient frontier. $\endgroup$
    – Zeca
    Jan 4, 2017 at 9:12
2
$\begingroup$

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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.