Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Computing a Rate of Return

5.00/5 (4 votes)
20 Apr 2009Ms-PL3 min read 22.6K   155  
Using a root-finder to solve a transcendental equation.

Introduction

Let’s use numerical methods to solve a simple financial engineering problem. We will model an investment account into which you make regular payments, such as a retirement account or college savings fund.

The Math

If the balance P in an account earns a rate of return r, and we make a regular payment p into the account, then the account balance changes according to the differential equation:

DiffEqP2.gif

This differential equation is easily solved:

PEquation2.gif

Given an initial balance, a rate of return, and a payment rate, this equation gives you the balance after a given time. With a little algebra, you can solve it for p, to tell you the payment rate you would need to achieve a given balance after a given time. Or you could solve it for t, to tell you how long you would need to save in order to achieve a given balance.

What you cannot do with algebra is turn it into an equation for r, the rate of return you earned on an investment. This is because r appears both in the argument of the exponent and outside it. But, knowing what return we have achieved is a common question, to which we would like an answer.

The Code

We can solve this problem numerically. We will simply define a function of r that measures how far the predicted final balance differs from the actual final balance:

FEquation2.gif

and search for a root of this function that is a value of r that makes f(r)=0.

We will use the root-finding capabilities of the Meta.Numerics library. Just download this free numerics library, add a reference to Meta.Numerics.dll to your project, and add the appropriate using statements.

C#
using Meta.Numerics;
using Meta.Numerics.Functions;

Next, define the function whose roots we want as a delegate.

C#
// define a mismatch function
Function<double, double> f = delegate (double r) {
    double rt = r * t;
    if (Math.Abs(rt) > 1.0e-6) {
        return ((P1 + p / r) * Math.Exp(rt) - (P2 + p / r));
    } else {
        return ((P1 + p * t - P2) + rt * (P1 + p * t / 2.0));
    }
};

Notice that we treat f(r) specially near r=0. Direct application of the expression above would result in division by zero, but in fact, f(r) is perfectly well-behaved there. You can see this for yourself by expanding the exponential in a power series, the first few terms of which give our linear approximation.

Now, all that remains is to find a root of this function. Like all numerical root-finders, the Meta.Numerics library requires that you provide an initial guess (or a bracket) for the root – otherwise, how could it know which root of a multi-rooted function to find? In most cases, it is worthwhile to put some work into finding a good initial guess. But in this case, our function can be easily evaluated everywhere, has only a single root, and has a simple, monotonic shape – this is really unnecessary. We will simply start the root-finder at r=0.

C#
// make it zero
double rate = FunctionMath.FindZero(f, 0.0);

That’s it! We have solved a transcendental equation with a delegate definition and a method invocation.

More to Know

The algorithms behind the FindZero function are fairly complicated. After all, it needs to handle arbitrary functions, without derivative information, with as few function evaluations as possible. If you need an easy-to-use, robust, efficient root-finder and don’t want to worry about the underlying algorithmic details, it’s a great choice. And, if you do want to worry about the underlying algorithmic details, the Meta.Numerics sources are available for your perusal.

If you don’t want or need to solve transcendental equations in code, but you do want or need to model account balances, you can just use this online calculator, which uses the Meta.Numerics library under the hood.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)