IRR and NPV in Mathematica

If you work in finance, you probably compute net present values (NPVs) and internal rates of return (IRRs) from time to time. As of version 7, Mathematica does not have built-in functions for these. There are add-on libraries that one might buy but it seems wrong to have to pay for something that is both so simple and so important. I have tried to convince Wolfram to add functions for computing these to the standard libraries, but thus far without success. So I will provide sample code here for anybody looking to do these things in Mathematica.

Generally when working with financial data series, I prefer to use data objects that have an identifying header rather than just raw data. In the long run, it makes life much simpler. In a later post I will explain this in more detail and give examples. For this post, I will not use that technique, and will show how to complete the calculations of NPV and IRR in Mathematica for a simple list of {date/datum} pairs.

First, since we are going to be using Mathematica’s date functions, and my sample dates are in “Month/Day/Year” format, we had better shut off some warnings:

Off[AbsoluteTime::ambig]

Now a function that takes a list of dates and a fixed annual discount rate, and returns a discount factor for each date.


sternDiscountFactors[dateList_, r_] := Module[{absDates, firstDate},
absDates = Map[AbsoluteTime[#] &, dateList];
firstDate = Min[absDates];
Transpose[{dateList, Map[1/(1 + r)^DateDifference[firstDate, #, "Year"][[1]] &, absDates]}]]

For an example of how this works, run
In[]:= sternDiscountFactors[{"1/1/2001", "1/1/2002", "1/1/2005", "1/10/2005"}, .05]

Out[]= {{"1/1/2001", 1.}, {"1/1/2002", 0.952381}, {"1/1/2005", 0.822702}, {"1/10/2005", 0.821713}}

Then we need a function for computing the net present value of a cash flow, given a fixed annual discount rate. Basically, it takes the dot product of vectors representing the discount factor on each date and the net payment on that date.


sternNetPV[dateAndCashFlowList_, r_] :=
Module[{cashflows, discountfactors},
cashflows = Transpose[dateAndCashFlowList][[2]];
discountfactors =
Transpose[sternDiscountFactors[Transpose[dateAndCashFlowList][[1]], r]][[2]];
cashflows.discountfactors]

Here is some sample data that we will use to test the NPV function and, in a minute, the IRR function:

testFlow = {{"1/1/2001", -1}, {"1/1/2002", .3}, {"1/1/2005", .4}, {"1/10/2005", .5}};

You can then test the NPV function with
In[]:= sternNetPV[testFlow, .05]

Out[]= 0.0256519

Computing the internal rate of return is now simple:

sternIrr[dateAndCashFlowList_] :=
Module[{eqn, r}, eqn = sternNetPV[dateAndCashFlowList, r] == 0; FindRoot[eqn, {r, .1}]]

and this can be tested with
In[]:= sternIrr[testFlow]

Out[]={r$3479 -> 0.0584316}

Aquí tiene. In real world applications, one would not typically rely on a fixed annual discount rate, and the NPV function would in most important contexts use a yield curve instead.