Skip to content

Instantly share code, notes, and snippets.

@Rots
Last active August 29, 2015 14:06
Show Gist options
  • Save Rots/7a5a0a7ff86804a91e34 to your computer and use it in GitHub Desktop.
Save Rots/7a5a0a7ff86804a91e34 to your computer and use it in GitHub Desktop.
#~ Title: XIRR Excel function simulation
#~
#~ Reference 1: XIRR manual - http://office.microsoft.com/en-gb/excel-help/xirr-HP005209341.aspx
#~ Reference 2: How to calculate IRR manually - http://www.s-anand.net/Calculating_IRR_manually.html
#~
#~ Step 1: enter zeroes (0) against dates that do not have any cash outflow or inflows.
#~ Step 1bis: calculate IRR for these cash flow values using normal IRR function.
#~ Step 1tris: or using an iteractive approach as bisection method to find the NPV zeroes.
#~ Step 2: multiply this value of IRR by 365 to get annual IRR (since, these are daily cash flows).
#~ Step 3: refine using the formula =( 1+ R / 365) ^ 365 - 1), where R is the the value obtained in Step2.
#~
#
sppv <- function (i, n) {
return((1 + i/100)^(-n))
}
# Net Present Value
npv <- function(x, i) {
npv = c()
for (k in 1:length(i)) {
pvs = x * sppv(i[k], 1:length(x))
npv = c(npv, sum(pvs))
}
return(npv)
}
# Internal rate of return for non-periodic cash flow
# Input: cashflow - vector of numeric
# dates - vector of dates
# Output: irr - internal rate of return - range 0,1
#
xirr <- function (cashflow, dates) {
if (length(cashflow) != length(dates)) {
stop("length(cashflow) != length(dates)")
}
cashflow_adj <- c(cashflow[1])
i=1
while (i<length(cashflow)) {
if(dates[i+1]==dates[i]){
cashflow_adj[length(cashflow_adj)]=cashflow_adj[length(cashflow_adj)]+cashflow[i+1]
}
else{
interval <- as.integer(dates[i+1] - dates[i])
cashflow_adj <- c(cashflow_adj, rep(0, interval-1), cashflow[i+1])
}
i=i+1
}
# Bisection method finding the rate to zero npv
left = -10
right = 10
epsilon = 1e-8
while (abs(right-left) > 2*epsilon) {
midpoint = (right+left)/2
if (npv(cashflow_adj, left) * npv(cashflow_adj, midpoint) > 0) {
left = midpoint
} else {
right = midpoint
}
}
# Irr for daily cashflow (not in percentage format)
irr = (right+left) / 2 / 100
# Irr for daily cashflow multiplied by 365 to get yearly return
irr <- irr * 365
# Annualized yield (return) reflecting compounding effect of daily returns
irr <- (1 + irr / 365) ^ 365 - 1
irr
}
#~ npv(rep(8792,12), 666.31/12) # 15755.01 - 100000 - 10.0088%
# the correct IRR is 10.06% - source: matlab example
mycashflow <- c(-10000,2500, 2000, 3000,4000)
mydates <- as.Date(c("12-01-87", "14-02-88", "03-03-88", "14-06-88", "01-12-88"),"%d-%m-%y")
xirr(mycashflow, mydates)
# the correct IRR is 37.34% - source: microsoft example
mycashflow <- c(-10000,2750,4250,3250,2750)
mydates <- as.Date(c("1-01-08","1-03-08","30-10-08","15-02-09","1-04-09"),"%d-%m-%y")
xirr(mycashflow, mydates)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment