next up previous contents index
Next: Basic Option Pricing, analytical Up: Cash flow algoritms. Previous: Present value.   Contents   Index


Internal rate of return.

The internal rate of return of a cash flow is the interest rate that makes the present value of a cash flow equal to zero.

Finding an internal rate of return is thus to find a root of of the equation

\begin{displaymath}PV(C,t,r)=0 \end{displaymath}

As any textbook in basic finance, such as Brealey and Myers (1996), Ross et al. (1996) or Sharpe and Alexander (1990) will tell, there is a number of problems with the IRR, most of them stemming from the possibility for more than one interest rate being defined.

If we know that there is one IRR, the following method is probably simplest, bisection. It is an adaption of the bracketing approach discussed in Press et al. (1992), chapter 9. Note that this approach will only find one interest rate, if there is more than one irr, the simplest is always to graph the PV as a function of interest rates, and use that to understand when an investment is a good one.

// file
// author: Bernt A Oedegaard

#include <cmath>
#include <algorithm>
#include <vector>

#include "fin_algoritms.h"

const double ERROR=-1e30;

double cash_flow_irr(vector<double>& cflow_times, vector<double>& cflow_amounts) {
// simple minded irr function.  Will find one root (if it exists.)
// adapted from routine in Numerical Recipes in C.
    if (cflow_times.size()!=cflow_amounts.size()) return ERROR;
    const double ACCURACY = 1.0e-5;
    const int MAX_ITERATIONS = 50;
    double x1=0.0;
    double x2 = 0.2;
// create an initial bracket, with a root somewhere between bot,top
    double f1 = cash_flow_pv(cflow_times, cflow_amounts,  x1);
    double f2 = cash_flow_pv(cflow_times, cflow_amounts,  x2);
    int i;
    for (i=0;i<MAX_ITERATIONS;i++) {
	if ( (f1*f2) < 0.0) { break; }; // 
	if (fabs(f1)<fabs(f2)) { f1 = cash_flow_pv(cflow_times,cflow_amounts,  x1+=1.6*(x1-x2)); }
	else {f2 = cash_flow_pv(cflow_times,cflow_amounts,  x2+=1.6*(x2-x1)); };
    if (f2*f1>0.0) { return ERROR; };
    double f = cash_flow_pv(cflow_times,cflow_amounts, x1);
    double rtb;
    double dx=0;
    if (f<0.0) {	rtb = x1;	dx=x2-x1;     }
    else {	rtb = x2;	dx = x1-x2;     };
    for (i=0;i<MAX_ITERATIONS;i++){
	dx *= 0.5;
	double x_mid = rtb+dx;
	double f_mid = cash_flow_pv(cflow_times,cflow_amounts, x_mid);
	if (f_mid<=0.0) { rtb = x_mid; }
	if ( (fabs(f_mid)<ACCURACY) || (fabs(dx)<ACCURACY) ) return x_mid;
    return ERROR;   // error.

Check for unique irr.

If you worry about finding more than one IRR, the following implements a simple check for that. It is only a neccesary condition for a unique IRR, not sufficient, so you may still have a well-defined IRR even if this returns false.

The first test is just to count the number of sign changes in the cash flow. From Descartes rule we know that the number of real roots is one if there is only one sign change. If there is more than one change in the sign of cash flows, we can go further and check the aggregated cash flows for sign changes (See Norstrom (1972), or Berck and Sydsæter (1995)).

// file 
// author Bernt A Oedegaard

#include <cmath>
#include <vector>

inline int sgn(double& r){ if (r>=0) {return 1;} else {return -1;}; };

bool cash_flow_unique_irr(vector<double>& cflow_times, vector<double>& cflow_amounts) {
    // check whether the cash flow has a unique irr.
    int sign_changes=0;     // first check Descartes rule
    for (unsigned t=1;t<cflow_times.size();++t){
	if (sgn(cflow_amounts[t-1]) !=sgn(cflow_amounts[t])) sign_changes++;
    if (sign_changes==0) return false;  // can not find any irr
    if (sign_changes==1) return true;

    double A = cflow_amounts[0]; // check the aggregate cash flows, due to Norstrom
    for (unsigned t=1;t<cflow_times.size();++t){
	if (sgn(A) != sgn(A+=cflow_amounts[t])) sign_changes++;
    if (sign_changes<=1) return true;
    return false;

next up previous contents index
Next: Basic Option Pricing, analytical Up: Cash flow algoritms. Previous: Present value.   Contents   Index
Bernt Arne Odegaard