'Non-linear Optimization solnl function error in R: 'Argument of length zero'

I am trying to implement CVaR portfolio optimisation in R. Basically trying to replicate the Matlab approach used in this paper:

https://ethz.ch/content/dam/ethz/special-interest/mtec/chair-of-entrepreneurial-risks-dam/documents/dissertation/master%20thesis/Thesis_Matthias_Kull_2014.pdf

To do this I need to perform nonlinear optimisation with nonlinear constraints.

I have tried to use the nloptr package, but found the derivative calculation for the gradient of matrices beyond me.

Instead I have opted for the NlcOptim package which formulates the constraints in the same way as the Matlab function used in the paper.


library(NlcOptim)

# ====================================================================
# Just generate arbitrary returns data and bootstrap -----------------

asset_returns <- rbind(c(0.1, 0.05, 0.05, 0.01, 0.06),
                       c(0.05, 0.05, 0.06, -0.01, 0.09),
                       c(0.025, 0.05, 0.07, 0.02, -0.1),
                       c(0.01, 0.05, 0.08, -0.02, -0.01),
                       c(0.01, 0.05, 0.08, 0.00, 0.2),
                       c(0.005, 0.05, 0.09, 0.005, -0.15),
                       c(0.01, 0.05, 0.08, 0.01, -0.01),
                       c(0.012, 0.05, 0.00, -0.01, -0.01),
                       c(0.015, 0.05, 0.00, 0.03, 0.05),
                       c(0.02, 0.05, -0.01, 0.04, 0.03))
  # Returns for 5 assets over 10 trading periods

nAssets <- ncol(asset_returns)
nReturns <- nrow(asset_returns)
nPeriods <- 4
nSims <- 10

# BOOTSTRAP ---------------------------------------------------------
sim_period_returns <- matrix(nrow = nSims, ncol = nAssets)
for (k in 1:nSims) {# run nSims simulations
  sim_returns <- matrix(nrow = nPeriods, ncol = nAssets)

  sample_order <- sample(nReturns, nPeriods)
  for (i in 1:nPeriods) {
    sim_returns[i,] <- asset_returns[sample_order[i],]  
  }

  sim_prices <- rbind(rep(1, nAssets), 1 + sim_returns)

  for (j in 1:nAssets) {
    sim_period_returns[k, j] <- prod(sim_prices[, j]) - 1 
  }

}
# ------------------------------------------------------------------------
# ========================================================================

# The important stuff ====================================================

returns <- sim_period_returns
alpha <- 0.95
CVaR_limit <- 0.025
UB <- 0.75
LB <- 0.05

# Inequality constraints  
A <- rbind(c(rep(0, nAssets), 1, 1/((1-alpha)*nSims) * rep(1, nSims)),
             cbind(- returns, -1, diag(nSims)))

b <- as.matrix(c(-CVaR_limit, rep(0, nSims)), nrow = nSims, ncol = 1)  

# Equality constraints  
Aeq <- c(rep(1, nAssets), 0, rep(0, nSims))
beq <- 1

# Upper and lower bounds  
UB <- c(rep(UB, nAssets), Inf, rep(Inf, nSims))
LB <- c(rep(LB, nAssets), 0, rep(0, nSims))

# Initial portfolio weights  
w0 <- rep(1/nAssets, nAssets)
VaR0 <- quantile(returns %*% w0, alpha, names = F)
w0 <- c(w0, VaR0, rep(0, nSims))

objective_function <- function(x) {
    # objective function to minimise
    return (-colMeans(returns) %*% x[1:nAssets])

}

# **********************************************
# The solnl function giving the error based on the above inputs 
  solnl(X = w0, 
        objfun = objective_function, 
        A = A,
        B = b,
        Aeq = Aeq,
        Beq = beq, 
        lb = LB, 
        ub = UB)
# **********************************************

# =================================================================== 

I am receiving the following error:

Error in if (eq > 0 & ineq > 0) { : argument is of length zero

I have read the package source code and tried to figure out what is causing this error, but am still at a loss.



Solution 1:[1]

Checking the source code and input data, I think that the error starts at line 319 on NlcOptim when the following code is called nLineareq = nrow(Aeq);By calling nrow(Aeq) in the way that you have defined Aeq it will result in NULL a few lines later the expression if (eq > 0 & ineq > 0) is evaluated resulting in the error. Regarding the error you can find an explanation in here Argument is of length zero in if statement

A quick fix could be to change the shape on Aeq by using

Aeq <- t(array(c(rep(1, nAssets), 0, rep(0, nSims))))

However by changing that I get a different error when i try to run the code

Error: object 'lambda' not found

I'm not sure if the R implementation needs a different initial conditions or the method is not converging, since in the paper, the method used for the optimization was interior-point rather than SQP as implemented in NlcOptim.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 user438383