如何使用 R 的优化、优化函数等来查找提供特定返回值的函数输入?

德克棉

我试图找到一个函数输入值(标量),当与其他三个已知向量参数结合时,创建第四个向量,该向量恰好在特定向量元素(而不是之前)处减小为零。

第四个向量包含计算的投资组合余额,每个向量元素是一年。我希望投资组合余额恰好在投资者去世那年的投资组合余额中减少到零(该年份在已知向量参数之一中指定)。我想通过找到初始投资组合值来实现这一点,该值导致该向量元素在死亡年份和不久之后为零。

(注意:在 Excel 中,这可以使用 Goal Seek 工具通过更改初始投资组合值将特定投资组合平衡元素(年份)设置为零来完成。)

我已经尝试了 optim 和 optimize 但最后一次尝试了下面的脚本。优化的初始投资组合值始终等于约束最大值。

任何帮助将不胜感激。这两天一直在拔头发。

f1 <- function(init,spendV,returnV,stateV) {

  # create a vector that equals an initial portfolio value (init) and sets subsequent vector elements
  # equal to the previous portfolio balance minus an amount of spending and then applies a market return rate.
  # Portfolio balance can never fall below zero

  # When the state vector element = 4, the investor died in the previous period
  endState <- which (stateV == 4)
  portfoliobal <- rep(0,length(spendV))

  portfoliobal[1] <- (init - spendV[1]) * returnV[1]

  for (i in (2:length(spendV))) {
    portfoliobal[i] <- max(0,(portfoliobal[i-1] - spendV[i]) * returnV[i])
  }

  # the function returns the portfolio balance when the investor dies
  return(portfoliobal[endState])

}

# spending, market growth rates, and the period of death are given vectors
spendV <- c(97719.19,97737.92,102649.4,98669.15,78108.44,58105.49,51710.02,53267.12,
            39982.34,21070,22439.68,21375.4,15613.45,10826.54,9333.82,7808.239,
            8737.435,8382.001,7267.976,6534.688,5129.403,5026.947,4931.132,5468.401,
            5033.245,5195.273,5199.938,4854.684,5039.221,3757.753,1822.97,1202.24,
            1237.238,965.111,1051.235,906.4884,1110.66,1018.127,500.788,538.2703,
            584.5545,599.1832,575.2254,640.8828,604.0179,781.878,595.9795,625.5037,
            615.471,667.4227)

init <- 1000000 

returnV <- c(0.9347388,1.170053,1.204515,0.9572276,1.044682,0.9229759,1.110595,0.9299398,
             1.161509,1.053207,1.058104,0.8997761,1.000342,1.353597,1.031785,1.121795,0.8745584,
             1.05637,1.180234,0.9795393,0.9137375,0.772738,1.021843,0.9697467,1.055284,0.9182615,
             0.9662726,1.105152,1.099005,0.9195565,0.895424,0.9226368,1.196467,1.085768,0.9529325,
             1.485245,0.9124764,0.8978044,0.8021779,0.9064698,1.034353,0.9914232,0.742632,
             0.9308539,0.9683604,0.9325817,1.000051,1.145982,1.018012,1.127159)

stateV <- c(3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
            2,2,2,2,2,2,2,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)

cat("\n\nCritical vector element= ",which(stateV == 4))

# the critical vector element is the portfolio balance at death

# I experiment with different inital portfolio values and find that portfolio balance[34] approaches zero
# when initial portfolio balance is about 710,000
f1value <- f1(init=1000000,spendV,returnV,stateV)
cat ("\n\nf1value for critical vector element",which(stateV == 4)," when inital value = 1,000,000: ",f1value)

f1value <- f1(init=800000,spendV,returnV,stateV)
cat ("\n\nf1value for critical vector element",which(stateV == 4)," when inital value = 800,000: ",f1value)

f1value <- f1(init=710000,spendV,returnV,stateV)
cat ("\n\nf1value for critical vector element",which(stateV == 4)," when inital value = 710,000: ",f1value)

# I am trying to find the initial portfolio balance that leaves zero dollars in portfolio balance vector [34]
# ---- BUT not BEFORE portfolio balance [34]

# opt <- optimize(f1,c(0,10000000),spendV,returnV,stateV,maximum = FALSE)
丹尼

回答

optim()并且optimize()都寻求最小值(默认情况下)。你想要一个零。您正在寻找的功能是uniroot(). 做这个:

uniroot(f=f1, interval=c(1, 1e7), spendV=spendV, returnV=returnV, stateV=stateV)
#> $root
#> 703932.9

其他一些东西

为了好玩,这里用矢量化表示法重写了你的函数(我懒惰地省略了returnVspendVargs):

f2 <- function(init, end=34) {
    init*prod(returnV[1:end]) - sum(cumprod(returnV[end:1])*spendV[end:1])
}

uniroot(f2, c(1, 1e7))
#> $root
#> 703932.9

一般来说,如果您正在测试可能的解决方案,您可能会发现绘制一大堆解决方案更容易,而不是一次尝试一个并使用cat(). 以下是我可能的处理方式:

x <- seq(1, 2e6, by=100000)
y <- f2(x, 34)
plot(x, y, pch=20)
abline(v=0, h=0)

最后一个想法:在您的函数中f1which(stateV==4)如果用户输入,例如,该行可能会返回一个值向量stateV=c(1,4,4)我猜你想要第一次出现“4”,你可以用which(stateV==4)[1]来完成if(sum(stateV==4)>1) stop("Too many 4s!")

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章