【发布时间】:2018-08-27 06:23:50
【问题描述】:
问题介绍
我正在尝试在 R 中编写代码,以便获得等权贡献 (ERC) 投资组合的权重。你们有些人可能知道,投资组合的构建是由Maillard, Roncalli and Teiletche 提出的。
跳过技术细节,为了找到 ERC 投资组合的最佳权重,需要解决以下顺序二次规划问题:
与:
假设我们正在分析 N 个资产。在上述公式中,我们有 x 是一个 (N x 1) 投资组合权重向量,而 Σ 是 (N x N) 个资产收益方差-协方差矩阵。
到目前为止我做了什么
使用解决SQP问题的包nloptr的函数slsqp,我想解决上述最小化问题。这是我的代码。首先,要最小化的目标函数:
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
return(h)
}
最后是上下界约束(权重不能超过1也不能低于0):
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 理解该做什么。 有人可以帮助我了解如何解决问题并获得我想要的结果吗?
更新一:正如@jogo 在 cmets 中指出的那样,我已经更新了代码,但它仍然会产生错误。上面的代码和错误现已更新。
更新 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)
【问题讨论】:
-
根据文档rdocumentation.org/packages/nloptr/versions/1.0.4/topics/slsqp
fn=应该是一个函数 - 而不是对函数的调用。所以最终应该是:slsqp(x0 = x0, fn = ObjFuncERC, Sigma = Sigma, ...) -
@jogo 好点!我已经更新了代码,但现在它返回了
'f' must be a univariate function of 2 variables。在这一点上,我开始认为 slsqp 可能不是解决我的问题的正确功能,但我不知道应该使用什么。上面确实是一个顺序二次规划问题…… -
您的代码没有重现该问题。请在新的 R 会话中检查这一点并相应地添加其他信息(包、变量..)。谢谢。
-
如果
Sigma是常量,您可以定义一个函数来构造您的目标函数:defObj <- function(Sigma) function(x) ObjFuncERC(x, Sigma); myObj <- defOBJ(Sigma); slsqp(x0 = x0, fn = myOBJ, ...) -
您的目标函数似乎与
function (x, Sigma) { R <- Sigma %*% x; xR <- x*R; sum(outer(FUN='-', xR, xR)^2) }等价
标签: r finance portfolio quantitative-finance