R中的非线性优化Solnl函数错误:'长度为零的参数'

问题描述 投票:0回答:1

我正在尝试在R中实现CVaR投资组合优化。基本上是尝试复制本文中使用的Matlab方法:

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

为此,我需要在非线性约束下执行非线性优化。

我曾尝试使用nloptr包,但发现了超出我的矩阵的梯度的导数计算。

相反,我选择了NlcOptim软件包,该软件包以与本文中使用的Matlab函数相同的方式来表示约束。


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)
# **********************************************

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

我收到以下错误:

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

我已经阅读了程序包的源代码,并试图找出导致此错误的原因,但仍然不知所措。

r nonlinear-optimization
1个回答
0
投票

[检查源代码和输入数据,当以下代码被调用nLineareq = nrow(Aeq);时,我认为错误始于NlcOptim的第319行:通过以您定义的nrow(Aeq)方式调用Aeq,将导致NULL几行后,对表达式if (eq > 0 & ineq > 0)求值导致错误。关于错误,您可以在这里R - argument is of length zero in if statement

中找到解释。

快速解决方法是使用]更改Aeq上的形状>

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

但是通过更改,当我尝试运行代码时,我得到了另一个错误

Error: objetc 'lambda' not found

我不确定r的实现是否需要不同的初始条件或该方法是否收敛,因为在本文中,用于优化的方法是内部点而不是NlcOptim中实现的SQP。希望对您有所帮助

© www.soinside.com 2019 - 2024. All rights reserved.