Mortgage Calculation Demo -- Commentary and Description
Program Description and General Comments
This demo will allow you to calculate the regularly scheduled series of payments
needed to pay off a mortgage or any other type of long term annuity. Besides,
displaying the payment schedule in table form the program will also solve for
one of either two unknown variables in the calculation. The program can either
be asked to solve for the payment value needed to pay off the debt in exactly
equal sized payments or the time it takes to pay off the debt given the current
set of financial data. Originally, I also planned to solve for the interest rate,
but my browser (Internet Explorer) seems to choke on this.
Overview of The Mortgage Class
The main areas of interest in this class are the member functions:
- SetupData
- Amortize
- FindPayment
- FindRate
- FindTime
- CheckArguments
The other methods are not very interesting. They are basically utility functions
used for setting the internal class data and for displaying the final results.
The above listed functions are the one's that will be doing the actual calculation
work.
Overview of SetupData method
The SetupData function is used to initialize member variables of a Mortgage
object based on the data entered onto the form. Specifically it initializes:
- Effective which is used as the multiplier for the balance. This
is used to get the value of the balance on each successive payment period.
- TotalPeriods which is the total number of payment periods for the
mortgage calculation.
- LowerBound which is the lower asymptote limit for the payment value
when solving for time.
- Min which is the low end value for the payment when solving for
payment value.
- Max which is the high end value for the payment when solving for
payment value.
These internal values are used within the program to do the calculations.
The Min and Max values are used as the high and low ends for the bisection
root finding algorithm used for finding the value required for exact sized
mortgage payments.
Overview of Amortize method
The amortize method implements the algorithm for mortgage amortization. Amortize
is just financial jargon for paying off a debt in regularly scheduled payments.
A simple for loop is able to accomplish this. Within the loop, each successive
balance value is subtracted by the payment value to get the result of the debt
amortization. In addition to this, each payment period has a break down of the
payment as to what portion goes toward paying the interest and what goes toward
paying the principal of the loan. The payment, interest paid, principal paid and
balance are stored in an array of objects with each object being able to store
these four values. The amortize method returns the ending balance after all
payments have been completed. A positive result would indicate that the payment
value was not sufficiently high enough to pay off the loan within the specified
time interval. A negative value indicates that it was too high. A zero value
would indicate that the loan was paid off with exactly equal payments of the
specified size. These return values are very useful to the root finding
algorithm covered later on.
Overview of FindPayment method
The find payment method implements the textbook
bisection root finding algorithm to find the required value for
exact equal sized payments to fit a given payment schedule. The idea of the
algorithm is simple: Repeatedly execute the function with the midpoint value
of the high and low ends passed as the argument. If the result comes out
positive it means the midpoint value was too low. We find another midpoint
using the current midpoint as the low end value in the calculation. If the
result comes out negative it means the midpoint value was too high. We find
another midpoint using the current midpoint as the high end value in the
calculation.
There are other methods available for root finding. Another commonly used
one is Newton's method. I did not choose to use Newton's method because I
saw no real advantage in using it over the bisection method in this situation.
Newton's method is able to find the root of a function which has both increasing
and decreasing slope over an interval, but the amortization function only has
decreasing slope over the whole of its interval. The bisection method is quite
reliable in finding roots of function that are either increasing or decreasing
so there's no disadvantage in this area. Furthermore, we need to solve for the
derivative of the function when applying Newton's method. In the case of the
amortization function there is no easy way to simplify the function into its
derivative form. The only choice is to call the amortization method twice per
iteration, once for the function value and once for the value given by the
derivative of the function. Any efficiency gained by Newton's method over the
bisection method would not be overwhelming in this case.
Overview of FindRate method
The FindRate method also uses the bisection method, but on a different term
of the amortization formula. The method solves for the interest rate needed
for equal sized payments of the given payment value to completely pay off the
mortgage within the given amount of time. To do this we simply solve for the
low end rate by re-arranging the formula for finding the "Max" high end payment
value in the SetupData method. We also solve for the high end rate by re-arranging
the formula for finding the "Min" low end payment value. By doing this we assume
that the given payment value is at the lowest allowable value and therefore,
requires the highest interest rate or that the given payment value is at the
high end and therefore, requires the lowest interest rate value. Using the
bisection method we can verify any matching values that lie in between these
two extremes.
Overview of FindTime Method
The FindTime method simply runs the Amortize method once to find the required
time to completely eliminate the mortgage. If solving for "time required"
is specified for a mortgage object then the loop iteration limit within the
Amortize method is set to maximum number of iterations instead of the specified
TotalPeriods. This is so that the program can iterate through an arbitrary number
of payment periods until the resulting balance finally reaches zero. The iteration
limit is set high enough as to allow reasonably valid time intervals. One limit
in solving for required time is that the payment value must be greater or equal
to a specified minimum value. This is reasonable, since the payment value must
be at least high enough to repay the interest on the loan. To have any chance
of repaying the loan, the payment value must also be high enough to pay at least
a small portion of the principal during each payment period.
Overview of CheckArguments Method
The CheckArgument method does exactly what its name describes. The method checks
the input arguments of the user to determine if they meet a specific boundary
condition like an absolute minimum value. If the input values fail in any
of the tests the procedure returns false and the program will not execute.
More specifically the CheckArgument method tests for:
- TotalTime, this value must be greater than zero
- Price, any monetary value like the price must be at least 1 cent or greater.
- Payment, the payment value must be at least high enough to repay the interest
when solving for time. And cannot be so low that it is not even able to repay
interest free loans within the given time interval when solving for equal
sized payments.
Prototype of Mortgage Program
A prototype of the mortgage program was first written in C++ to test ideas and
algorithms. Prototyping is a commonly used technique in software projects to
make a model of the problem to be solved. The idea is to build a small scale
working model which closely follows how the real program should function. Once
the prototype is finished and working according to plan, the ideas used in its
development are transferred over in the development of the real program. The
C++ prototype program that I've made is an exact working copy of the JavaScript
demo program used in this website. In fact its more functional since the solve
for "interest rate" feature works on the prototype. The only minor glitch is
that it is command line driven (sorry no GUI). Here it is:
compound.cpp
Testing The Mortgage Calculator
As with any other serious programs, when preparing to test the mortgage
program we must come up with a detailed and complete test plan so we can be
sure to catch most if not all of the potential errors in the program. The test
plan for the mortgage program is simple and involves two stages:
- General Testing
- Boundary Value Testing
First we test the general case. To do this, we input typical values into the
form and then execute the script. The script should produce the correct answers
for the requested calculation. With a calculator we can verify that these answers
are indeed correct.
Next we do boundary value testing. To do this, we input values into the program
that are almost at the bounding limit for valid data. For example, the lower
bound limit for the payment value when solving for "time needed" is $806.705
given the rest of the financial data is:
- pay period: monthly
- price: $90,000
- interest rate: 11%
- compounding: Semi-Annually
so we put in 806.71 which is just 1 cent greater than $806.705 as the payment
value and execute the script. It should still give us the correct results even
at this lower limit.
The boundary values for the rest of the tests are as follows:
- In solving for interest rate the boundary test value for payment is:
500.01
- In solving for payment value the boundary test value for time is:
0.1 years
The rest of the financial data is the same as the preceeding list.
Note On Performance of Demo Program
Note: because of the performance problems inherent in JavaScript and other
interpreted scripting languages it is best to do the boundary testing of the
program in a compiled language like C++. The prototype for this demo was
written in C++ so you can use the prototype to do the testing instead of the
demo itself. The C++ version is faster and doesn't take nearly as much
resources to run.
Summary
Although this is a relatively simple program in terms of coding and design,
it has the most immediate and practical uses of all the demo programs. With
this program you could generate payment schedules for mortgages or loans.
You could also answer a number of what-if scenarios, by changing the financial
data listed in the form controls. You can also find out some computed values
like the value of equal sized payments and the total time needed to repay the
loan. In the actual implementation of the program I used simple conditional
loops and textbook examples of algorithms, nothing fancy at all.