我有一个嘈杂的优化任务。我试图找到一个函数的参数(选择哪些资产及其权重),以使它们最小化函数结果(跟踪误差-投资组合和指数收益之间的差异)。财务条款对找到解决方案不是很关键。
当我使用mlrMBO
中的优化方法时,结果(y)总是与理论结果和直觉结果所期望的相差甚远。 mbo
的结果与函数中使用最优参数的结果甚至不同。
我尝试更改学习者,参数集的设置并重新编码该功能,但是它不起作用
这是一个最小的可重现示例(结果是相同的,问题仍然存在,所以我想它是可重现的)
max_stocks <- 10 # maximum number of assets to choose
# for the sake of reproducibility below is a provisional matrix of assets returns, each column is a different asset and stock index returns
quarter.pool <- matrix(rnorm(1830, 0, 0.01), nrow = 61, ncol = 300)
stock_index <- matrix(rnorm(61,0,0.02))
# function with 2 inputs of same length vectors and tracking error as output
obj_func <- function(stock_weights, which_stocks){
quarter.pool_ <- quarter.pool[,which_stocks] #choosing which assets to invest in
portfolio <- matrix(rep(0,nrow(quarter.pool_))) # empty index-tracking portfolio
for (i in 1:nrow(quarter.pool_)) {
portfolio[i] <- sum(quarter.pool_[i,]*stock_weights, na.rm = TRUE)}
tracking_error <- sqrt(sum(portfolio-stock_index)^2/length(portfolio-1))
return(tracking_error)}
obj_f <- makeSingleObjectiveFunction(name = "index_tracking",
fn = obj_func,
par.set = makeParamSet( makeNumericVectorParam("stock_weights", len = max_stocks, lower = 0, upper = 0.25),
makeIntegerVectorParam("which_stocks", len = max_stocks, lower = 1, upper = ncol(quarter.pool))),
noisy = TRUE,
vectorized = TRUE)
ctrl <- makeMBOControl(final.method = "best.true.y", propose.points = 1)
ctrl <- setMBOControlTermination(ctrl, iters = 20, target.fun.value = 0.0000001)
run <- mbo(fun = obj_f, control = ctrl)
obj_func(run$x$stock_weights, run$x$which_stocks) == run$y
# the result is different even tho function works as usual
无论我在哪里重复脚本,结果都相差很大。 但是主要问题是双重的:
- 它应该接近0,通常甚至不低于0.2。甚至不知道它是否可能。
mbo
中的“最优” y与将“最优”参数放入同一函数的结果不同。也许是因为y是预测值而不是真实值?虽然差异很大。
编辑[1] 显然,当我删除参数“ which_stocks”时,一切都很好,因此一定是因为它。还有什么办法吗?也许算法不能胜任这项艰巨的任务?
答案 0 :(得分:1)
请参阅我对设置的评论。从技术上讲,它通过将参数作为列表传递并将has.simple.signature = FALSE
添加到欺骗包装程序中来工作。
max_stocks <- 10 # maximum number of assets to choose
# for the sake of reproducibility below is a provisional matrix of assets returns, each column is a different asset and stock index returns
quarter.pool <- matrix(rnorm(1830, 0, 0.01), nrow = 61, ncol = 300)
stock_index <- matrix(rnorm(61,0,0.02))
# function with 2 inputs of same length vectors and tracking error as output
obj_func <- function(x){
stock_weights = x$stock_weights
which_stocks = x$which_stocks
quarter.pool_ <- quarter.pool[,which_stocks] #choosing which assets to invest in
portfolio <- matrix(rep(0,nrow(quarter.pool_))) # empty index-tracking portfolio
for (i in 1:nrow(quarter.pool_)) {
portfolio[i] <- sum(quarter.pool_[i,]*stock_weights, na.rm = TRUE)}
tracking_error <- sqrt(sum(portfolio-stock_index)^2/length(portfolio-1))
return(tracking_error)}
obj_f <- makeSingleObjectiveFunction(name = "index_tracking",
fn = obj_func,
par.set = makeParamSet( makeNumericVectorParam("stock_weights", len = max_stocks, lower = 0, upper = 0.25),
makeIntegerVectorParam("which_stocks", len = max_stocks, lower = 1, upper = ncol(quarter.pool))),
noisy = FALSE,
vectorized = FALSE,
has.simple.signature = FALSE
)
ctrl <- makeMBOControl(final.method = "best.true.y", propose.points = 1)
ctrl <- setMBOControlTermination(ctrl, iters = 10, target.fun.value = 0.0000001)
run <- mbo(fun = obj_f, control = ctrl)
obj_func(list(stock_weights = run$x$stock_weights, which_stocks = run$x$which_stocks)) == run$y
发生的事情是stock_weights和which_stocks被unlist()
组合成一个向量并传递给您的obj_func
,不幸的是,即使第二个参数(which_stocks
)也有效未定义,并且第一个向量太长。这应该提醒您,如果函数有些复杂,请务必在函数参数中添加一些可行性检查。您可以使用checkmate
包来实现。基本上,您没有优化真正的目标函数。