1
votes

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
1
these slides enricoschumann.net/files/slides_rimini_2016_qp.pdf show how to use package quadprog for mean-variance optimisation. The referenced code is at enricoschumann.net/files/mv.REnrico Schumann
I appreciate the materials but I already have slides and similar codes. I was just looking for some code to my problem so that I can move on to other parts I need to complete. Like very explicit definitions of my variables. The equal to or less than 10% is what's tripping me up and how to define that in the Amat properly.eruiz
Is that intentional that you skip all even i?Jan
@Jan can you explain. i is looking at TAU which is either an array of numbers from zero to 0.5 in increments of 0.001 or, as I have it written, different rows of a matrix with the same numbers. I am merely going row to row within the TAU matrix but am I inadvertently skipping all the evens???eruiz
The for loop takes care of the increment itself. The statement i <- i+1 is extra and not needed. However, I just tried it out and R completely ignores the extra i+1statement. So, it doesn' t do any harm and my suspicion was wrong. So, you are right that it works.Jan

1 Answers

2
votes

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, i.e. 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)