У меня возникают трудности при попытке выполнить нелинейную ограниченную оптимизацию с использованием библиотеки nloptr.
Мне нужно минимизировать отрицательную логарифмическую функцию правдоподобия линейной комбинации связки в форме
Clayton_t_gumbel = weight1 * clayton_copula + weight2 * gumbel_copula + weight3 * t_copula
Эта проблема аналогична описанной в статье Бернарда Пфафику «Моделирование финансовых рисков и оптимизация портфеля» вR, глава 9: смеси копул, но с добавлением ограничения равенства весов копул. У меня проблема в том, что оптимизация не учитывает мое ограничение равенства (heq).
Код целевой функции выглядит следующим образом:
LLCG <- function(params,x, copC, copG, copt){ #log likelihood minimization
slot(copC, "parameters") <- params[1]
slot(copG, "parameters") <- params[2]
slot(copt, "parameters") <- params[3:4] #t copula uses two parameters
pi1 <- params[5] #weight parameters
pi2 <- params[6]
pi3 <- params[7]
#pi3 <- params[6]
opt <- log(pi1 * copula::dCopula(x, copC) + pi2 * copula::dCopula(x, copG)
+ pi3 * copula::dCopula(x, copt))
if(any(is.infinite(opt)))
{
opt[which(is.infinite(opt))]<-0
}
sum(opt)
}
Где params - это векторпараметры связок и веса линейных комбинаций (pi1, pi2, pi3).
. Мое ограничение равенства (сумма весов = 1):
heq <- function(params, x, copC, copG, copt){
constrain <- c(0*params[1]+ 0*params[2] + 0*params[3] +
0*params[4] + params[5] + params[6] + params[7] - 1)
return constrain
}
Где params [5: 7] - это веса, которые должны быть равны 1.
Поскольку я не знаю градиентмоей целевой функции, я подумал об использовании решателя NLOPT_GN_ISRES. Он свободен от производных и поддерживает ограничения равенства в дополнение к границам параметров.
Мой код оптимизации выглядит следующим образом:
## Initializing copula objects
copt <- copula::tCopula(param = 0.5, dim = 8)
copC <- copula::claytonCopula(2, dim = 8) # delta= 2
copG <- copula::gumbelCopula(2, dim = 8) # theta= 2
##parameters bounds: some of them are Infinite. The last three are weights between [0,1]
lower <- c(copC@param.lowbnd, 1.1, -0.9,2.1, 0,0,0)
upper <- c(copC@param.upbnd, copG@param.upbnd, 1,100, 1,1,1)
##obtaining ecdfs
v<-as.matrix(do.call(cbind, X[[i]]))
U<-v[,1:8]
## Creating copula objects initial guesses
par1 <- copula::fitCopula(copC, U, "itau",estimate.variance= T)@estimate #inversion of Kendall's tau
par2 <- copula::fitCopula(copG, U,"itau", estimate.variance= T)@estimate
par3 <- copula::fitCopula(copt, U,"mpl",estimate.variance= F)@estimate ###mpl
par4 <- 0.2 ##weight parameters
par5 <- 0.2
par6 <- 0.2
##optimization:
opts <- list("algorithm"="NLOPT_GN_ISRES",
"xtol_rel"=1.0e-4,
"maxeval"=100000,
"print_level" = 3,
"tol_constraints_eq" = 1.0e-6 )
opt <- nloptr::nloptr(x0 = c(par1, par2, par3, par4, par5,par6),
eval_f = LLCG, x = U,
copC = copC, copG = copG, copt=copt,
lb = lower, ub = upper,
eval_g_eq = heq,
opts = opts)
По неизвестной мне причине решатель, вероятнее всего, оценит хорошие параметры связок (из предыдущего опыта), но веса нетронуты. Если я начну с весов = 0,2 каждый, они получат одинаковое значение. Ниже приведен пример оценки параметров. Понятно, что ограничение равенства не выполняется, так как сумма весов = 0,6.
[1] 1.2850078 1.6963797 0.1292916 4.7089477 0.2000000 0.2000000 0.2000000
Я также с радостью принимаю различные решения для nlopters. Спасибо.