问题
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)
回答1:
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, thereturn
function will return 0 and then exit the function. - If the
all
function returns FALSE, then theuniroot
function will run as it did previously.
回答2:
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
回答3:
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 tryCatch
the 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)
来源:https://stackoverflow.com/questions/37707952/how-can-i-incorporate-if-statement-when-calculating-irr-in-r