Minimize portfolio variance, which should be reasonably similar to the benchmark portfolio

I am doing portfolio optimization and I would like to expand the discussion here with the following:

I have a vector of weights w_bench

that is used as a reference. I would like to optimize a portfolio weight vector w_pf

that satisfies

sum(pmin(w_bench, w_pf)) > 0.7

      

pmin

there is a pairwise minimum. This makes the optimized portfolio weights w_pf

look like the weights w_bench

, and the right size (0.7 in this case) determines how much they should fit. As this value gets larger, we require the portfolios to be more similar.

At first I thought I could easily do this with a package fPortfolio

(still trying). But there are still no cubes. I also think that solving this with help quadprog

would be much more intuitive, but I don't know how to incorporate this functionality into the process.

Excel implementation:

Covariance matrix:

0.003015254   -0.000235924  0.000242836
-0.000235924  0.002910845   0.000411308
0.000242836   0.000411308   0.002027183

      

Weight:

    w_pf    w_bench min
V1   0.32    0.40    0.32 
V2   0.31    0.50    0.31 
V3   0.38    0.10    0.10 
Ss   1.00    1.00    0.72 

      

Collapse value ( =MMULT(TRANSPOSE(H8:H10),MMULT(H3:J5,H8:H10))

) with constraints Ss(w_pf) = 1

andSs(min) > 0.7

+3


source to share


1 answer


As you noticed, the tricky constraint is that sum(pmin(w_bench, w_pf)) > 0.7

(in fact, it is very difficult to have strict inequality, so I will do >=

instead >

, you, solve with help >= 0.7+epsilon

for a small epsilon). To approach this, we will create a new variable y_i

for each item i

in our portfolio, and we will add constraints y_i <= wpf_i

(aka wpf_i - y_i >= 0

) and y_i <= wbench_i

(aka -y_i >= -wbench_i

) where wpf_i

is the share i

in our selected portfolio (decision variable) and wbench_i

is the share i

in the control portfolio (input data). This limits y_i

no more than the minimum of these two values. Finally, we will add a constraint \sum_i y_i >= 0.7

requiring these minimum values ​​to be at least 0.7.

All that remains is to implement it in the package quadprog

. Setting with problem data:

cov.mat <- rbind(c(0.003015254, -0.000235924, 0.000242836), c(-0.000235924, 0.002910845, 0.000411308), c(0.000242836, 0.000411308, 0.002027183))
w.bench <- c(.4, .5, .1)
n <- length(w.bench)

      

As we add new variables, we will place the covariance matrix (which will be placed in the optimization target) with 0 in the rows and columns corresponding to these new variables. We can do this with:

(cov.mat.exp <- cbind(rbind(cov.mat, matrix(0, n, n)), matrix(0, 2*n, n)))
#              [,1]         [,2]        [,3] [,4] [,5] [,6]
# [1,]  0.003015254 -0.000235924 0.000242836    0    0    0
# [2,] -0.000235924  0.002910845 0.000411308    0    0    0
# [3,]  0.000242836  0.000411308 0.002027183    0    0    0
# [4,]  0.000000000  0.000000000 0.000000000    0    0    0
# [5,]  0.000000000  0.000000000 0.000000000    0    0    0
# [6,]  0.000000000  0.000000000 0.000000000    0    0    0

      

Now we want to create a constraint matrix for all of our constraints:

(consts <- rbind(rep(c(1, 0), c(n, n)),
                 rep(c(0, 1), c(n, n)),
                 cbind(matrix(0, n, n), -diag(n)),
                 cbind(diag(n), -diag(n))))
#      [,1] [,2] [,3] [,4] [,5] [,6]
# [1,]    1    1    1    0    0    0
# [2,]    0    0    0    1    1    1
# [3,]    0    0    0   -1    0    0
# [4,]    0    0    0    0   -1    0
# [5,]    0    0    0    0    0   -1
# [6,]    1    0    0   -1    0    0
# [7,]    0    1    0    0   -1    0
# [8,]    0    0    1    0    0   -1
(rhs <- c(1, 0.7, -w.bench, rep(0, n)))
# [1]  1.0  0.7 -0.4 -0.5 -0.1  0.0  0.0  0.0

      



The first line will sum up the portfolio weights to 1, the next will be enforced \sum_i y_i >= 0.7

, the next three will be constraints -y_i >= -wbench_i

, and the last three will be constraints ypf_i-y_i >= 0

.

All that's left is to put them in the format expected by the function solve.QP

:

library(quadprog)
mod <- solve.QP(cov.mat.exp, rep(0, 2*n), t(consts), rhs, 1)
# Error in solve.QP(cov.mat.exp, rep(0, 2 * n), t(consts), rhs, 1) : 
#   matrix D in quadratic function is not positive definite!

      

Since we added a covariance matrix with an additional 0 for our new variables, it is positive semidefinite but not positive definite. Let's add a tiny positive constant to the main diagonal and try again:
library(quadprog)
mod <- solve.QP(cov.mat.exp + 1e-8*diag(2*n), rep(0, 2*n), t(consts), rhs, 1)
(w.pf <- head(mod$solution, n))
# [1] 0.3153442 0.3055084 0.3791474
(y <- tail(mod$solution, n))
# [1] 0.3 0.3 0.1
(opt.variance <- as.vector(t(w.pf) %*% cov.mat %*% w.pf))
# [1] 0.0009708365

      

We see that this is not a particularly interesting case, because the constraint that we worked with so much was not required. Let's increase the right side from 0.7 to 0.9 to see the constraint in action:

(rhs <- c(1, 0.9, -w.bench, rep(0, n)))
# [1]  1.0  0.9 -0.4 -0.5 -0.1  0.0  0.0  0.0
mod <- solve.QP(cov.mat.exp + 1e-8*diag(2*n), rep(0, 2*n), t(consts), rhs, 1)
(w.pf <- head(mod$solution, n))
# [1] 0.3987388 0.4012612 0.2000000
(y <- tail(mod$solution, n))
# [1] 0.3987388 0.4012612 0.1000000
(opt.variance <- as.vector(t(w.pf) %*% cov.mat %*% w.pf))
# [1] 0.00105842

      

In this case, the restriction was mandatory; the minimum value accepted y_1

and y_2

is taken from our new portfolio, and the minimum value accepted y_3

from the reference portfolio. We see that the variance of the optimal portfolio had a relative increase of 9.0% due to the constraint.

+2


source







All Articles