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.