adaodante adaodante - 3 months ago 29
R Question

Error in solve.QP

So essentially I have two matrices containing the excess returns of stocks (R) and the expected excess return (ER).

R<-matrix(runif(47*78),ncol = 78)
ER<-matrix(runif(47*78),ncol = 78)


I then combine these removing the first row of R and adding the first row of ER to form a new matrix R1.

I then do this for R2 i.e. removing first two rows of and R and rbinding it with the first 2 rows of ER.

I do this until I have n-1 new matrices from R1 to R47.

I then find the Var-Cov matrix of each of the Return matrices using cov() i.e. Var-Cov1 to Var-Cov47.

n<-47
switch_matrices <- function(mat1, mat2, nrows){
rbind(mat1[(1+nrows):nrow(mat1),],mat2[1:nrows,])
}

l<-lapply(1:n-1, function(nrows) switch_matrices(R,ER, nrows))
list2env(setNames(l,paste0("R",seq_along(l))), envir = parent.frame())

b<-lapply(l, cov)
list2env(setNames(b,paste0("VarCov",seq_along(b))), envir = parent.frame())


I am now trying to find the asset allocation using quadprog. So for example:

D_mat <- 2*VarCov1
d_vec <- rep(0,78)
A_mat <- cbind(rep(1,78),diag(78))
b_vec <- c(1,d_vec)

library(quadprog)
output <- solve.QP(Dmat = D_mat, dvec = d_vec,Amat = A_mat, bvec = b_vec,meq =1)
# The asset allocation
(round(output$solution, 4))


For some reason when running solve.QP with any Var-Cov matrix found I get this error:

Error in solve.QP(Dmat = D_mat, dvec = d_vec, Amat = A_mat, bvec = b_vec, :
matrix D in quadratic function is not positive definite!


I'm wondering what I am doing wrong or even why this is not working.

Answer

The input matrix isn't positive definite, which is a necessary condition for the optimization algorithm.

Why your matrix isn't positive definite will have to do with your specific data (the real data, not the randomly generated example) and will be both a statistical and subject matter specific question.

However, from a programming perspective there is a workaround. We can use nearPD from the Matrix package to find the nearest positive definite matrix as a viable alternative:

# Data generated by code in the question using set.seed(123)
library(quadprog)
library(Matrix)
pd_D_mat <- nearPD(D_mat)

output <- solve.QP(Dmat = as.matrix(pd_D_mat$mat), 
                   dvec = d_vec,
                   Amat = A_mat, 
                   bvec = b_vec,
                   meq  = 1)

# The asset allocation
(round(output$solution, 4))
 [1] 0.0052 0.0000 0.0173 0.0739 0.0000 0.0248 0.0082 0.0180 0.0000 0.0217 0.0177 0.0000 0.0000 0.0053 0.0000 0.0173 0.0216 0.0000
[19] 0.0000 0.0049 0.0042 0.0546 0.0049 0.0088 0.0250 0.0272 0.0325 0.0298 0.0000 0.0160 0.0000 0.0064 0.0276 0.0145 0.0178 0.0000
[37] 0.0258 0.0000 0.0413 0.0000 0.0071 0.0000 0.0268 0.0095 0.0326 0.0112 0.0381 0.0172 0.0000 0.0179 0.0000 0.0292 0.0125 0.0000
[55] 0.0000 0.0000 0.0232 0.0058 0.0000 0.0000 0.0000 0.0143 0.0274 0.0160 0.0000 0.0287 0.0000 0.0000 0.0203 0.0226 0.0311 0.0345
[73] 0.0012 0.0004 0.0000 0.0000 0.0000 0.0000