使用optim计算IRR

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

我想找到内部收益率(IRR),基本上是使用optim函数使我的NPV函数变为零的'速率'。

我目前的NPV功能代码(有效)是:

npv <- function(rate, cf){
    r_v <- rep (rate,length (cf))
    t_v <- as.numeric (seq(1:length (cf)))
    pv <- cf * exp (-t_v*r_v)
    sum (pv)
} 

我尝试使用以下optim函数:

InternalRateReturn <- optim(c(0,1), npv, cf = testcf2, gr = NULL, method = "L-BFGS-B", lower = -Inf, upper = Inf,control=list(), hessian = FALSE)

但它没有回复InternalRateReturn$par的正确答案,而不是使用下面的uniroot方法。

请问如何修改此代码(重申一下,我只想优化npv函数中的速率,使npv函数等于零)?

使用uniroot的IRR功能如下:

irr1 <- function(cf) {
    uniroot(npv, c(0, 1), cf=cf)$root
}
r finance irr
2个回答
2
投票

有一个非常酷的例子,使用optim来计算Matt Brigida的IRR

### IRR Function:  Takes a vector of payments and returns a list which includes the internal rate of return ($IRR) and possible word of warning ($beware) ----

irr <- function(x, period = 1, starting.value = .1){

### This should detect the number of sign changes.  Should correctly not warn if there are many negative cash flows (so long as there is only 1 change in sign).

    irr.func <- function(r){ ( sum(x / (1 + r)^{0:(length(x)-1)}) )^2 }
    result <- optim(par = starting.value, fn = irr.func, method = "Brent", lower = -1000000, upper = 1000000)

    ## detecting number of sign changes
    x.ge.0 <- 1 * (x >= 0)
    changes <- diff(x.ge.0)
    changes <- changes * changes
    num.changes <- sum(changes)

    if( num.changes > 1) {

        statement <- "Your cash flows change more than once -- so you may have multiple IRRs. This function will only return the first IRR it finds. To find the others, you can try different starting values.  However, note the IRR does not make sense if the signs change more than once (try Modified IRR or NPV)."
        value <- period * result$par
        return(list(beware = statement, IRR = value))

    } else {

        return(list(IRR = period * result$par))

    }
}

对于更现实的修正IRR,Matt也有一个非常有用的功能(它不会对再投资率做出不合理的假设)

### Modified IRR (MIRR) Function:  Takes a vector of payments and returns the MIRR by ----

mirr <- function(x, period = 1, starting.value = .1, discount.rate = 0.1, investment.rate = 0.05){

    ## move cash flows
    ## negative
    cf.neg <- (x < 0) * x
    ## discounted
    pv.cf.neg <- cf.neg / (1 + discount.rate)^{0:(length(x)-1)}
    pv <- sum(pv.cf.neg)

    ## positive
    cf.pos <- (x > 0) * x
    fv.cf.pos <- cf.pos * (1 + investment.rate)^{0:(length(x)-1)}
    fv <- sum(fv.cf.pos)

    mirr.per.period <- ( fv / abs(pv) )^{1 / (length(x))} - 1

    return( period * mirr.per.period )
} 

0
投票

如果你只需要计算IRR或NPV(或MIRR),并且由于不清楚为什么你绝对需要使用optim,你可以简单地考虑包financialFinCal而不是破解你自己的函数。像这样:

> require(financial)
> cf(c(-123400, 36200, 54800, 48100), i = 2.5)

Cash Flow Model

Flows:
      1       2       3       4 
-123400   36200   54800   48100 

 IRR%: 5.96 
 NPV Extremes at I%:  

   I%     NPV     NFV     NUS
1 2.5 8742.13 9414.32 3060.95

> require(FinCal)
> npv(c(-123400, 36200, 54800, 48100), r = 0.025)
[1] 8742.134
> irr(c(-123400, 36200, 54800, 48100))
[1] 0.05959787
© www.soinside.com 2019 - 2024. All rights reserved.