R中的序贯二次规划,以找到同等加权风险贡献组合的最优权重

时间:2018-03-18 16:35:10

标签: r finance portfolio quantitative-finance

问题简介

我正在尝试在R中写下代码,以获得同等加权贡献(ERC)投资组合的权重。正如你们中的一些人所知,投资组合的构建是由Maillard, Roncalli and Teiletche提出的。

跳过技术细节,为了找到ERC组合的最佳权重,需要解决以下序列二次规划问题:

enter image description here

使用:

enter image description here enter image description here

假设我们正在分析 N 资产。在上面的公式中,我们得到 x 是投资组合权重的(N×1)向量,Σ是资产收益的(N×N)方差 - 协方差矩阵。

到目前为止我做了什么

使用解决SQP问题的包slsqp的函数nloptr,我想解决上面的最小化问题。这是我的代码。首先,要最小化的目标函数:

ObjFuncERC <- function (x, Sigma) {
sum <- 0
R <- Sigma %*% x
    for (i in 1:N) {
        for (j in 1:N) {
            sum <- sum + (x[i]*R[i] - x[j]*R[j])^2
        }
    }
}

其次,起点(我们从同等加权的投资组合开始):

x0 <- matrix(1/N, nrow = N, ncol = 1)

然后,等式约束(权重必须总和为1,即:权重之和减去一等于零):

heqERC <- function (x) {
    h <- numeric(1)
    h[1] <- (t(matrix(1, nrow = N, ncol = 1)) %*% x) - 1
    return(h)
}

最后,下限和上限约束(权重不能超过1且不能低于零):

lowerERC <- matrix(0, nrow = N, ncol = 1)
upperERC <- matrix(1, nrow = N, ncol = 1)

因此,应该输出最佳权重的函数是:

slsqp(x0 = x0, fn = ObjFuncERC, Sigma = Sigma, lower = lowerERC, upper = upperERC, heq = heqERC)

不幸的是,我不知道如何与你分享我的方差 - 协方差矩阵(它取名为Sigma并且是一个(29 x 29)矩阵,因此N = 29)所以为了重现我的结果,你仍然可以模拟之一。

输出错误

运行上面的代码会产生以下错误:

Error in nl.grad(x, fn) : 
Function 'f' must be a univariate function of 2 variables.

我不知道该怎么做。也许,我误解了必须记下的内容,以便函数slsqp能够理解该怎么做。 有人可以帮助我了解如何解决问题并获得我想要的结果吗?

UPDATE ONE :正如@jogo在评论中指出的那样,我已经更新了代码,但它仍然会产生错误。现在更新了上面的代码和错误。

更新2 :根据@jaySf的要求,以下是允许您重现错误的完整代码。

## ERC Portfolio Test
# Preliminary Operations
rm(list=ls())
require(quantmod)
require(nloptr)

# Load Stock Data in R through Yahoo! Finance
stockData <- new.env()
start <- as.Date('2014-12-31')
end <- as.Date('2017-12-31')
tickers <-c('AAPL','AXP','BA','CAT','CSCO','CVX','DIS','GE','GS','HD','IBM','INTC','JNJ','JPM','KO','MCD','MMM','MRK','MSFT','NKE','PFE','PG','TRV','UNH','UTX','V','VZ','WMT','XOM')
getSymbols.yahoo(tickers, env = stockData, from = start, to = end, periodicity = 'monthly')

# Create a matrix containing the price of all assets
prices <- do.call(cbind,eapply(stockData, Op))
prices <- prices[-1, order(colnames(prices))]
colnames(prices) <- tickers

# Compute Returns
returns <- diff(prices)/lag(prices)[-1,]

# Compute variance-covariance matrix 
Sigma <- var(returns)
N <- 29

# Set up the minimization problem
ObjFuncERC <- function (x, Sigma) {
sum <- 0
R <- Sigma %*% x
    for (i in 1:N) {
        for (j in 1:N) {
            sum <- sum + (x[i]*R[i] - x[j]*R[j])^2
        }
    }
}


x0 <- matrix(1/N, nrow = N, ncol = 1)


heqERC <- function (x) {
    h <- numeric(1)
    h[1] <- t(matrix(1, nrow = N, ncol = 1)) %*% x - 1
}

lowerERC <- matrix(0, nrow = N, ncol = 1)
upperERC <- matrix(1, nrow = N, ncol = 1)

slsqp(x0 = x0, fn = ObjFuncERC, Sigma = Sigma, lower = lowerERC, upper = upperERC, heq = heqERC)

1 个答案:

答案 0 :(得分:2)

我在您的代码中发现了几个错误。例如,ObjFuncERC没有返回任何值。您应该改用以下内容:

# Set up the minimization problem
ObjFuncERC <- function (x, Sigma) {
  sum <- 0
  R <- Sigma %*% x
  for (i in 1:N) {
    for (j in 1:N) {
      sum <- sum + (x[i]*R[i] - x[j]*R[j])^2
    }
  }
  sum
}

heqERC也未返回任何内容,我还对您的函数进行了一些更改

heqERC <- function (x) {
    sum(x) - 1
}

我进行了这些更改,并尝试了slsqp而没有lowerupper的情况,并且该方法有效。还有,要考虑的另一件事是您将lowerERCupperERC设置为矩阵。请改用以下内容:

lowerERC <- rep(0,N)
upperERC <- rep(1,N) 

希望这会有所帮助。