3

This is a simple function I use to calculate IRR. However, there are incidences when all cash flows are negative and return "Error in uniroot(npv, c(0, 1), cf = cf) : f() values at end points not of opposite sign." Is there any way I can put if statement so that when IRR can't be computed, R simply returns 0?

npv<-function(i,cf,t=seq(along=cf)) sum (cf/(1+i)^t)
irr <- function(cf) {uniroot(npv, c(0,1), cf=cf)$root }
irr(cf)
4

3 回答 3

4

You could use the all function:

irr <- function(cf) {
              if(all(cf < 0)) return(0)
              uniroot(npv, c(0,1), cf=cf)$root
       }
  • If the all function returns TRUE, the return function will return 0 and then exit the function.
  • If the all function returns FALSE, then the uniroot function will run as it did previously.
于 2016-06-08T16:32:24.327 回答
1

I should mention that even after the accepted answer your functions seem to contain a small error:

npv<-function(i,cf,t=seq(along=cf)) sum (cf/(1+i)^t)
irr <- function(cf) {
    if(all(cf < 0)) return(0)
    uniroot(npv, c(0,1), cf=cf)$root
}

Which considering this example:

> npv(c(-123400, 36200, 54800, 48100), i = 0.025)
[1] 8528.911

The problem is that the defaults for t=seq(along=cf) will make you discount the cash flows by 1:4. Since the initial cash outflow of -123400 is usually considered a PV, you end up out of sync for the discounting.

This should fix things:

npv<-function(i,cf,t=seq(along=cf)-1) sum (cf/(1+i)^t)

Giving you this:

> npv(c(-123400, 36200, 54800, 48100), i = 0.025)
[1] 8742.134

But generally I would use financial or FinCal for computing IRR or NPV (or MIRR):

> 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
于 2017-02-07T09:43:24.197 回答
0

IRR may fail in may more instances than just when all cash flows are zero. To cater for every one of those scenarios you may want to tryCatchthe error, instead.

npv<-function(i,cf,t=seq(along=cf)) sum (cf/(1+i)^t)
irr <- function(cf) {tryCatch(uniroot(npv, c(0,1), cf=cf)$root,
         error=function(e) return(NA))
        }

irr(cf)
于 2017-12-22T01:55:54.780 回答