blacksiddis
blacksiddis

Reputation: 1

Quadprog for Portfolio Optimization with Constraints

Let me start by saying I am new to Stack Exchange sites, so apologies if this turns out to be a low quality question.

I am trying to run a mean-variance portfolio optimization using Solve.QP in R and have looked at several previous questions regarding this on Stack Overflow to figure out how to do this correctly but with no luck.

The constraints I want are as follows:

  1. Long/Short portfolio: weights may be negative
  2. Market neutral: Sum of weights = 0
  3. No leverage: Every weight is bound between -1 and 1 + sum of all positive weights = 1 and sum of all negative weights = -1

I am running this optimization with approx. 100 assets, so for demonstration purposes, I have reproduced the optimization part of the code with 5 assets (using fake data). Full code is found at the end of the post.

Let's say I have the following 5 expected returns for my 5 assets

> dvec
[1]  1.0791124  0.9088370  0.0992847 -0.2028962 -1.1632315

Two assets are expected to perform negatively, whilst 3 are expected to give a positive return.

Amat and bvec then looks like this

> cbind(amat, bvec)
                     bvec
 [1,]  1  1  1  1  1    0
 [2,]  1  1  1  0  0    1
 [3,]  0  0  0  1  1   -1
 [4,]  1  0  0  0  0   -1
 [5,]  0  1  0  0  0   -1
 [6,]  0  0  1  0  0   -1
 [7,]  0  0  0  1  0   -1
 [8,]  0  0  0  0  1   -1
 [9,] -1  0  0  0  0   -1
[10,]  0 -1  0  0  0   -1
[11,]  0  0 -1  0  0   -1
[12,]  0  0  0 -1  0   -1
[13,]  0  0  0  0 -1   -1

The optimization runs without throwing an error, but the leverage constraint is (not always) enforced

> sum(w_opt[w_opt>0])
[1] 1.22445
> sum(w_opt[w_opt<0])
[1] -1.22445

Where w_opt contains the optimized weights.

> w_opt
[1]  0.73304775  0.49140239 -0.22445014 -0.01629763 -0.98370237

I have set meq=3 to specify the three first constraints are equalities.

library(quadprog)

omega <- cov(data.frame(x=rnorm(200), y=rnorm(200), z=rnorm(200), p=rnorm(200), q=rnorm(200)))

N <- 5
maxw <- 1
minw <- -1
dvec <- rnorm(N)
dvec <- sort(dvec, decreasing=TRUE)
dmat <- omega
amat <- rbind(1, c(rep(1, length(dvec[dvec>0])),rep(0, length(dvec[dvec<0]))), c(rep(0,length(dvec[dvec>0])),rep(1, length(dvec[dvec<0]))), diag(N), -diag(N))
bvec <- c(0,1,-1, rep(minw,N), -rep(maxw, N))
meq <- 3

w_opt <- solve.QP(Dmat=dmat, dvec=dvec, Amat=t(amat), bvec=bvec, meq=meq)$solution

sum(w_opt[w_opt>0])
sum(w_opt[w_opt<0])

Upvotes: 0

Views: 292

Answers (0)

Related Questions