4

I’m trying to create the realized efficient frontier from a quarter period, with the daily closing prices of a hundred stocks, no short positions allowed.

The first step is to calculate the daily return for the period for each stock:

setwd("/Users/ClariceLoureiro/Desktop/COPPEAD/5th Term/Introducao ao Pacote estatistico em R/db") getwd() library(tseries) Quarter <- read.csv2("20153Q.csv",header=T,dec=".") assets <- Quarter n <- nrow(assets) returns <- (assets[2:n,])/(assets[1:n-1,])-1 

Then I used the portfolio.optim() function from the {tseries} to perform the quadratic programing and create the an optimum portfolio:

w2 <-portfolio.optim(as.matrix(returns),shorts=FALSE,riskless=FALSE) 

But, when I run this function the following message appears:

Error in solve.QP(Dmat, dvec, Amat, bvec = b0, meq = 2) : matrix D in quadratic function is not positive definite! 

When I run the same code for fewer stocks, It seems to work well:

# Choosing just 70 stocks out of 100 Quarter <- read.csv2("20153Q.csv",header=T,dec=".") assets <- Quarter[,1:70] #Calculating the returns n <- nrow(assets) returns <- (assets[2:n,])/(assets[1:n-1,])-1 #Portfolio optimization w2 <-portfolio.optim(as.matrix(returns),shorts=FALSE,riskless=FALSE) #Weights w2$pw [1] -3.644189e-19 2.390930e-18 1.156864e-01 -3.918512e-16 2.676315e-17 -3.136607e-16 [7] 3.158552e-16 3.901110e-16 -1.112018e-17 -1.927371e-16 1.264102e-19 9.040602e-17 [13] 4.881587e-02 2.291796e-17 -6.328846e-17 8.224983e-02 1.210207e-16 1.329818e-16 [19] 3.460248e-17 8.966350e-02 -4.929045e-17 1.689343e-17 -9.573418e-17 0.000000e+00 [25] -1.323861e-18 1.133006e-01 -1.896390e-17 -1.386383e-17 1.525087e-16 4.805648e-02 [31] -4.695605e-18 6.110056e-02 6.128005e-17 -1.042136e-17 9.100962e-03 1.846112e-17 [37] 5.128598e-17 -3.981178e-16 -4.379979e-16 1.936907e-17 4.694298e-02 2.676847e-18 [43] 8.752091e-18 4.121872e-02 2.970893e-17 6.871426e-03 3.612246e-17 4.217859e-17 [49] -4.834692e-18 3.071602e-17 -7.301697e-19 -1.309647e-17 2.034399e-02 4.689105e-03 [55] -6.014390e-19 6.389368e-02 7.511315e-02 -4.338530e-17 1.551683e-18 -6.838667e-20 [61] 1.445453e-18 4.783709e-17 4.803861e-17 1.866350e-02 -1.471388e-17 1.100957e-01 [67] 1.809216e-02 2.610136e-02 -2.751673e-17 1.393180e-18 # It must sum 1 sum(w2$pw) [1] 1 

Anybody knows why I’m facing this problem? Thank you very much!

7
  • Please provide a reproducible example Commented Mar 22, 2016 at 11:21
  • Have you tried running it with the second part of the data assets <- Quarter[,70:ncol(Quarter)] ? Maybe a data problem. Commented Mar 22, 2016 at 11:29
  • [1:n-1,] is not [1:(n-1),]! 1:n-1 is the same as 0:(n-1) because of operator precedence. Commented Mar 22, 2016 at 11:32
  • @jogo Just fix It, thank you! but the error was kept! Commented Mar 22, 2016 at 11:38
  • Not much help without seeing the data - can you share your 20153Q.csv somehow? Commented Mar 22, 2016 at 11:39

1 Answer 1

6

OK, had a look at the data, and it's OK. The problem is, as the error says, that the covariance matrix is not a positive definite. A quick test confirms that (BTW - I'm using packages matrixcalc and Matrix):

library(tseries) prices <- read.csv2("20153Q.csv",header=TRUE,dec=".") n <- nrow(prices) returns <- (prices[2:n,])/(prices[1:(n-1),])-1 portfolio.optim(as.matrix(returns), shorts=FALSE,riskless=FALSE) # cov(X) not a positive definitive # check matrixcalc::is.positive.definite(cov(returns)) 

gets

> matrixcalc::is.positive.definite(cov(returns)) [1] FALSE 

What you can do is adjust the covariance matrix to its nearest positive definite matrix by using Matrix::nearPD

returns.nearest.PD <- Matrix::nearPD(cov(returns))$mat returns.nearest.PD <- as.matrix(returns.nearest.PD) 

which will then allow you to using portfolio.optim by explicitly specifying the covmat:

(po <- portfolio.optim(as.matrix(returns), covmat = returns.nearest.PD, shorts=FALSE,riskless=FALSE)) 

which works without error:

> sum(po$pw) [1] 1 

and you can confirm that it has weights for each symbol:

> length(po$pw) [1] 99 

EDIT Just to be sure, the adjusted covariance matrix is very close to the original covariance matrix, the diffs are miniscule:

> # the matrices are really close > sum((abs(returns.nearest.PD - cov(returns)) > 0.000000001)==TRUE) [1] 0 > # the matrices are really close > sum((abs(returns.nearest.PD - cov(returns)) > 0.0000000001)==TRUE) [1] 74 
Sign up to request clarification or add additional context in comments.

1 Comment

thank you very much for your help! Really appreciated!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.