11

Are there any R packages available that have some form of function that can calculate IRR based on uneven payments on specific dates for a lump sum distribution.

Example:

df <- data.frame(date = c(as.Date("2010-1-24"), as.Date("2011-5-6"), as.Date("2012-3-24")), pmts=c(-2000,-1000,-800))
today <- as.Date("2012-7-25")
lumpsum <- 4580

I'm looking for an easy way to calculate the rate of return of $4580 received today in exchange for the payment schedule defined above.

Thanks in advance, --JT

JimmyT
  • 1,099
  • 4
  • 10
  • 15
  • 1
    [here](http://www.portfolioprobe.com/2012/01/19/how-to-search-the-r-sig-finance-archives/) is a good article about how to search for answers to questions like these. – GSee Jul 25 '12 at 23:55
  • 1
    Also, IRR is not complicated and it will likely be easier to just write it yourself. Any package you find for this will be designed for much more complicated scenarios. – Ari B. Friedman Jul 26 '12 at 03:18

3 Answers3

10

As already noted in the comments it would be easier to write something simple:

NPV<-function(paym,pdates,IRR){
   ptimes<-as.Date(pdates)-min(as.Date(pdates))
   ptimes<-as.numeric(ptimes,units="days")/365.25
   NPV<-sum(paym*(1+IRR)^{-ptimes})
   NPV
}

nlm(function(p){NPV(c(lumpsum,df$pmts),c(today,df$date),p)^2},p=0.1)

gives a IRR of 11.26%

EDIT:

after a quick scout around the lifecontingencies package has a present value function if you want to use that instead.

library(lifecontingencies)
capitals<-c(lumpsum,df$pmts)
times<-c(today,df$date)
times<-as.Date(times)-min(as.Date(times))
times<-as.numeric(times,units="days")/365.25
presentValue(cashFlows=capitals, timeIds=times,interestRates=0.03)
nlm(function(p){presentValue(capitals,times,p)^2},p=0.1)
shhhhimhuntingrabbits
  • 7,397
  • 2
  • 23
  • 23
7

utilising "stats" package uniroot function IRR can be coded as below:

   cf <- c(-10000, 1300, -1200, 12000) 
   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] 0.0686
   irrinpercent<- irr(cf)*100
   [1] 6.86
pmr
  • 998
  • 2
  • 13
  • 27
  • 1
    I believe this function contains a small error (`t=seq(along=cf)`), as it will discount the first CF instead of considering it as a PV (should be `t=seq(along=cf)-1`). In any case, I'm not sure this actually answers the question, and for IRR computations I'd suggest instead packages `financial` or `FinCal`. See [this](http://stackoverflow.com/questions/37707952/how-can-i-incorporate-if-statement-when-calculating-irr-in-r/42086453#42086453) answer to a different question. – landroni Feb 07 '17 at 09:54
  • @landroni, this behaviour is actually standard, ref. Excel formula NPV(). See solution and explanation to similar question here https://stackoverflow.com/a/47933761/5440712 – dmi3kno Dec 21 '17 at 22:52
  • @pmr thank you for your `irr` solution. I found it very helpful! – dmi3kno Dec 21 '17 at 22:52
  • 1
    Then NPV() in Excel is wrong. The investment happens -- by convention -- at the beginning of the first period, not at the end. So it is a PV. – landroni Dec 22 '17 at 05:41
1

pmr started with a great answer in his code sample. Thanks!

The problem I have with that code, however, is that the question (and my need as well) is to calculate the IRR when the cash flows have arbitrary times. pmr's code needs to be modified to have the irr function take the time vector t as an arg just like his npv function does.

To make this explicit, my adaptation of that code is:

# Returns the Internal Rate of Return.
# See: https://www.investopedia.com/terms/i/irr.asp
irr = function(t, cf) {
    uniroot(f = npv, interval = c(0, 1), t = t, cf = cf)$root
}

# Returns the Net Present Value.
# See: https://www.investopedia.com/terms/n/npv.asp
npv = function(t, cf, i) {
    sum( cf / (1 + i)^t )
}

Note that I changed the arg order (e.g. t first). Also, there is no default value for t, but if you want an even sequence, I think that landroni's comment is correct: your initial capital invested is at time = 0, not 1, as is clear in that investopedia link above the irr function.

Below is an example of how to use those functions that I faced. I was offered an opportunity to invest in an ATM network. These feature high annual returns (paid out monthly), but also are a rapidly depreciating asset (maybe 2% of your principal comes out at a final liquidation).

Execute the following code after first defining the functions above.

# parameters:
numYears = 7
capitalInvest = 52000
retAnnual = 0.245
capitalLiquidation = 700

# convert yearly values to mpnthly:
numMonths = numYears * 12
retMonthly = retAnnual / 12    # assumes no compounding

# initialize the time to 0 and the cash flow to capital SPENT (so negative):
t = 0
cf = -capitalInvest

# add monthly returns:
for (m in 1:numMonths) {
    t = c(t, m / 12)    # divide the time by 12 to have units of year
    cf = c(cf, retMonthly * capitalInvest)
}

# add liquidation value also on the final year:
t = c(t, numMonths / 12)    # divide the time by 12 to have units of year
cf = c(cf, capitalLiquidation)

# calculate the IRR:
irr(t, cf)

That code returned a value of 0.1852015 ~= 18.5% which agrees fairly closely with the value that the operator quoted me of 18.6%.

HaroldFinch
  • 762
  • 1
  • 6
  • 17