Ошибка в квадратичном программировании в R с использованием функции Portugal.optim

Я пытаюсь создать реализованную эффективную границу с квартальным периодом, с ежедневными ценами закрытия сотни акций, без коротких позиций.

Первым шагом является расчет ежедневной доходности за период для каждой акции:

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

Затем я использовал функцию portro.optim() из {tseries} для выполнения квадратичного программирования и создания оптимального портфеля:

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

Но когда я запускаю эту функцию, появляется следующее сообщение:

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

Когда я запускаю тот же код для меньшего количества акций, кажется, что он работает хорошо:

# 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

Кто-нибудь знает, почему я столкнулся с этой проблемой? Большое спасибо!


person Clarice Loureiro    schedule 22.03.2016    source источник
comment
Пожалуйста, приведите воспроизводимый пример   -  person adaien    schedule 22.03.2016
comment
Вы пытались запустить его со второй частью данных assets <- Quarter[,70:ncol(Quarter)]? Возможно проблема с данными.   -  person rbm    schedule 22.03.2016
comment
[1:n-1,] не [1:(n-1),]! 1:n-1 совпадает с 0:(n-1) из-за приоритета оператора.   -  person jogo    schedule 22.03.2016
comment
@jogo Просто исправь это, спасибо! но ошибка сохранилась!   -  person Clarice Loureiro    schedule 22.03.2016
comment
Без просмотра данных мало что поможет. Можете ли вы как-нибудь поделиться своим 20153Q.csv?   -  person rbm    schedule 22.03.2016
comment
@rbm, точно! Ссылка на данные   -  person Clarice Loureiro    schedule 22.03.2016
comment
@adiana Ссылка на данные   -  person Clarice Loureiro    schedule 22.03.2016


Ответы (1)


Хорошо, посмотрел данные, все в порядке. Проблема в том, как говорит ошибка, что ковариационная матрица не является положительно определенной. Быстрый тест подтверждает, что (кстати, я использую пакеты matrixcalc и 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))

получает

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

Что вы можете сделать, так это настроить ковариационную матрицу до ближайшей положительно определенной матрицы, используя Matrix::nearPD

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

что затем позволит вам использовать portfolio.optim, явно указав covmat:

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

который работает без ошибок:

> sum(po$pw)
[1] 1

и вы можете подтвердить, что он имеет веса для каждого символа:

> length(po$pw)
[1] 99   

РЕДАКТИРОВАТЬ Чтобы быть уверенным, скорректированная ковариационная матрица очень близка к исходной ковариационной матрице, различия минимальны:

> # 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
person rbm    schedule 22.03.2016
comment
Большое спасибо за Вашу помощь! Очень ценю! - person Clarice Loureiro; 22.03.2016