irr is a guessing algorithm similiar to binary searching for bugs in a program. For a project with a positive IRR, then two relatively prime factors could be used , one to increase the irr (multiple by factor > 1) if the npv is still positive and the other to decrease the irr when npv negative (divide by factor > 1), so that the tried values of the irr are unlikely to cycle, due to the lack of common factors in multiply and divide.
Below is a python algorithm for irr calculation, which also deals with going to a negative IRR when the guessing shows the irr is approaching zero.
# copyright GNU license, sjt,2014
r = 10.
sign = 1
npv = reduce( lambda x,(i,cf): x + cf / pow(1 + r/100, i ) , \
#for i,x in enumerate(cashflows):
# lr = pow((1 + r/100), i)
# y = x / lr
# print "lr", lr, "y", y
#print reduce( lambda x, y: x + y, cf)
if abs(npv) < lim:
if npv * sign > 0:
r = r * 1.9
r = r / 1.3
if sign > 0 and r < 0.0001:
r = - 20.
sign = -1
print "irr = ", r
This is a rather randomised algorithm; Newton's method has been mentioned as being used in open source spreadsheet programs.
Newton's method relies on the differentiation , or finding a derivative function to tell the slope of the graph of another function. The basic rule is that if there is a term which is axn then the derivative has a term , n.axn-1.
The npv function is a function of R the rate of return, such that npv is y, and R is x in the general function y = f(x) . Hence the derivative of the npv function is dy/dx = d(npv)/d(R) , which then requires finding the derivatives of all the terms in the npv function.
In Newton's method, an arbitrary R which is x, gives a NPV , which is a y value , when divided by the gradient which is delta-y/delta-x , gives delta-x , which is subtracted from R ( substitute x) to give another R' that is closer to the IRR, when NPV = 0 ( or the x value where y is zero, or where the function crosses the x-axis ). Using R' as the next R, this is repeated until a good approximation of IRR is achieved. The gradient is always recalculated at the start of each iteration , using the derivative function.
So if npv = CF0 / R0 + CF1 / R1 + .. + CFn / Rn,
or npv = CF0 + CF1 x R-1 + CF2 x R-2 + .. + CFn x R-n,
then d(npv)/dR = 0 + - CF1x R -2 + - 2 CF2x R -3 ... + -n x CFn x R-n - 1.
- REDIRECT Computation instead of Table Lookup