简体   繁体   中英

using quadprog for portfolio optimization

I have my input parameters mu (mean vector μ), Q (covariance matrix Q), and tau (risk tolerance τ) and I need to return the vector h (asset weights) that maximizes the following utility function U defined by:

U(h)= −1/2h^T*Q*h + τ*h^T*μ

subject to constraints:

0 ≤ h ≤ 0.1 for all h
and sum of all h is equal to 1: h^T*e = 1

TAU contains numbers from zero to 0.5 in steps of 0.001. How do I define the parameters: Dmat, dvec, Amat and bvec for this problem? I know the finance concepts but not how to program it correctly.

Thank you

This doesn't work as I still have negative weights indicative of short selling:(

frontieropti <- c(NULL)
i <- 1
for (i in 1:nrow(TAU)){
  solQP <- solve.QP(Dmat,TAU[i]*mu, Amat, bvec, meq = 1, factorized = F)
  sol <- c(i,solQP$value)
  frontieropti <- rbind(frontieropti,sol)
  i <- i +1
}
solQP <- solve.QP(Dmat, TAU[1]*mu, Amat, bvec, meq = 1, factorized = F)
solQP

Setting up Amat :

na <- 5  ## number of assets

I use only 5 assets and a maximum weight of 40% so that I can show the resulting matrices:

wmin <- 0
wmax <- 0.4
A <- rbind(1,-diag(na), diag(na))
bvec <- c(1, -rep(wmax, na), rep(wmin, na))
cbind(A, bvec)
##                      bvec
##  [1,]  1  1  1  1  1  1.0
##  [2,] -1  0  0  0  0 -0.4
##  [3,]  0 -1  0  0  0 -0.4
##  [4,]  0  0 -1  0  0 -0.4
##  [5,]  0  0  0 -1  0 -0.4
##  [6,]  0  0  0  0 -1 -0.4
##  [7,]  1  0  0  0  0  0.0
##  [8,]  0  1  0  0  0  0.0
##  [9,]  0  0  1  0  0  0.0
## [10,]  0  0  0  1  0  0.0
## [11,]  0  0  0  0  1  0.0

Note that the first row of Amat is for the budget constraint, so you need to set argument meq to 1. Also, solve.QP wants the transpose of Amat , ie t(Amat) .


So here would be a complete example:

library("quadprog")
library("NMOF")

I start by creating some random data for 30 assets.

na <- 30
R <- randomReturns(na = na, ns = 120, rho = 0.5, sd = 0.03)
mu <- colMeans(R)
V <- cov(R)


wmin <- 0
wmax <- 0.1
A <- rbind(1,-diag(na), diag(na))
b <- c(1, -rep(wmax, na), rep(wmin, na))

TAU <- seq(0, 0.5, by = 0.01) ## choose an appropriate stepsize

It is good practice to initialise data structures before the loop, and not "grow" them. (Even though it does not matter much in this example.)

results <- numeric(length(TAU))
weights <- array(NA, dim = c(na, length(TAU)))
for (i in seq_along(TAU)) {
    solQP <- solve.QP(Dmat = V,
                      dvec = TAU[i]*mu,
                      Amat = t(A),
                      bvec = b, meq = 1)

    ## an equivalent computation    
    ## NMOF::mvPortfolio(mu, V, wmax = 0.1, lambda = c(TAU[i], 0.5))

    results[i] <- solQP$value
    weights[, i] <- solQP$solution
}

Note that, because of round-off error, some results may be negative. So round the results to 8 decimal places, say.

weights <- round(weights, 8)
barplot(weights)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM