2

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 
6
  • 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.R Commented Jun 25, 2020 at 13:51
  • 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. Commented Jun 25, 2020 at 14:02
  • Is that intentional that you skip all even i? Commented Jun 25, 2020 at 19:15
  • @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??? Commented Jun 25, 2020 at 21:19
  • 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. Commented Jun 25, 2020 at 22:46

1 Answer 1

3

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) 
Sign up to request clarification or add additional context in comments.

9 Comments

thank you for your answer, I am following your thinking but have a couple followups. What would my dvec be then since I have risk tolerances tau included in the second term of the quadratic function τ*h^T*μ. I altered your code for my case (I have 30 assets and a max of 10%, no short sales). Also if A is Amat in your code you're saying that solve.QP only will take t(A) as an input? Thank you for helping, it doesn't help that this is such a large matrix. I appreciate you
I included above in my original question my loop for a solution but it still gives me negative weights indicative of short selling.
I have added to my answer.
This is all wonderful, I follow your logic and it seems to have worked. A quick followup however. Did you just include cbind(A, b) in your first response to show me both A and b in one output? I was under the impression that Amat is the matrix defining the constraints under which we want to minimize the quadratic function. So why is bvec not a part of Amat? I am trying to distinguish why the weight constraint is not a part of Amat as well?
Furthermore, is there a way to distinguish the optimum portfolio’s expected return and standard deviation of return. From your logic, results stores each solution from each iteration of the loop. So would the max value of this matrix of results just be the portfolio with the best possible return and therefore its corresponding weights? I am trying to store each portfolio return and standard deviation and then plot the efficient frontier. I am very new to theseoptimizations but I am so close to understanding. Thank you so much
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.