NAME

Finance::Math::IRR - Calculate the internal rate of return of a cash flow

SYNOPSIS

use Finance::Math::IRR;

# we provide a cash flow
my %cashflow = (
    '2001-01-01' => 100,
    '2001-03-15' => 250.45,
    '2001-03-20' => -50,
    '2001-06-23' => -763.12,  # the last transaction should always be <= 0
);

# and get the internal rate of return for this cashflow
# we want a precision of 0.1%
my $irr = xirr(%cashflow, precision => 0.001);

# or simply: my $irr = xirr(%cashflow);

if (!defined $irr) {
    die "ERROR: xirr() failed to calculate the IRR of this cashflow\n";
}

DESCRIPTION

The internal rate of return (IRR) is a powerfull tool when evaluating the behaviour of a cashflow. It is typically used to assess whether an investment will yield profit. But since you are reading those lines, I assume you already know what an IRR is about.

In this module, the internal rate of return is calculated in a similar way as in the function XIRR present in both Excell and Gnumeric. This means that cash flows where transactions come at irregular intervals are well supported, and the rate is a yearly rate.

An IRR is obtained by finding the root of a polynomial where each coefficient is the amount of one transaction in the cash flow, and the power of the corresponding coefficient is the number of days between that transaction and the first transaction divided by 365 (one year). Note that it isn't a polynomial in the traditional meaning since its powers may have decimals or be less than 1.

There is no universal way to solve this equation analytically. Instead, we have to find the polynomial's root with various root finding algorithms. That's where the fun starts...

The approach of Finance::Math::IRR is to try to approximate one of the polynomial's roots with the secant method. If it fails, Brent's method is tried. However, Brent's method requires to know of an interval such that the polynomial is positive on one end of the interval and negative on the other. Finance::Math::IRR searches for such an interval by trying systematically a sequence of points. But it may fail to find such an interval and therefore fail to approximate the cash flow's IRR:

API

xirr(%cashflow, precision => $float)

Calculates an approximation of the internal rate of return (IRR) of the provided cash flow. The returned IRR will be within $float of the exact IRR. The cashflow is a hash with the following structure:

my %cashflow = (
    # date => transaction_amount
    '2006-01-01' => 15,
    '2006-01-15' => -5,
    '2006-03-15' => -8,
);

To get the IRR in percent, multiply xirr's result by 100.

If precision is omitted, it defaults to 0.001, yielding 0.1% precision on the resulting IRR.

xirr may fail to find the IRR, in which case it returns undef.

xirr will croak if you feed it with junk.

DISCUSSION

Finding the right strategy to solve the IRR equation is tricky. Finance::Math::IRR uses a slightly different technique than the corresponding XIRR function in Gnumeric.

Gnumeric uses first Newton's method to approximate the IRR. If it fails, it evaluates the polynomial on a sequence of points ( '-1 + 10/(i+9)' and 'i' with i from 1 to 1024), hoping to find 2 points where the polynomial is respectively positive and negative. If it finds 2 such points, gnumeric's XIRR then uses the bisection method on their interval.

Finance::Math::IRR has a slightly different strategy. It uses the secant method instead of Newton's, and Brent's method instead of the bisection. Both methods are believed to be superior to their Gnumeric counterparts.

BUGS AND LIMITATIONS

This module has been used in recquiring production environments and thoroughly tested. It is therefore believed to be robust.

Yet, the method used in xirr may fail to find the IRR even on cash flows that do have an IRR. If you happen to find such an example, please email it to the author at <erwan@cpan.org>.

SEE ALSO

See Math::Polynom, Math::Function::Roots.

VERSION

$Id: IRR.pm,v 1.7 2007/01/04 13:11:13 erwan Exp $

THANKS

Kind thanks to Gautam Satpathy (gautam@satpathy.in) who provided me with his own implementation of XIRR written in Java. Its source can be found at http://www.satpathy.in/jxirr/index.html.

Thanks to the team of Gnumeric for releasing their implementation of XIRR in open source. For the curious, the code for XIRR is available in the sources of gnumeric in the file 'plugins/fn-financial/functions.c' (as of gnumeric 1.6.3).

AUTHOR

Erwan Lemonnier <erwan@cpan.org>

COPYRIGHT AND LICENSE

This code is distributed under the same terms as Perl itself.

DISCLAIMER OF WARRANTY

This is free code and comes with no warranty. The author declines any personal responsibility regarding the use of this code or the consequences of its use.