 NAME
 SYNOPSIS
 DESCRIPTION
 FUNCTIONS
 OBJECT ATTRIBUTES
 METHODS
 REMEMBER
 WARNINGS
 DISCLAIMER
 COPYRIGHT
 AUTHOR
NAME
Business::US_Amort  class encapsulating USstyle amortization
SYNOPSIS
use Business::US_Amort;
my $loan = Business::US_Amort>new;
$loan>principal(123654);
$loan>interest_rate(9.25);
$loan>term(20);
my $add_before_50_amt = 700;
sub add_before_50 {
my $this = $_[0];
if($this>{'_month_count'} == 50) {
$this>{'_monthly_payment'} += $add_before_50_amt;
}
}
$loan>callback_before_monthly_calc(\&add_before_50);
$loan>start_date_be_now;
$loan>run;
$loan>dump_table;
print "Total paid toward interest: ", $loan>total_paid_interest, "\n";
DESCRIPTION
This class encapsulates amortization calculations figured according to what I've been led to believe is the usual algorithm for loans in the USA.
I used to think amortization was simple, just the output of an algorithm that'd take just principle, term, and interest rate, and return the monthly payment and maybe something like total paid toward interest. However, I discovered that there's a need for loan calculations where, say, between the 49th and 50th month, your interest rate drops, or where you decide to add $100 to your monthly payment in the 32nd month.
So I wrote this class, so that I could amortize simply in simple cases while still allowing any kind of strangeness in complex cases.
FUNCTIONS
This module provides one function, which is a simple amortizer. This is just to save you the bother of method calls when you really don't need any frills.
 Business::US_Amort::simple $principal, $interest_rate, $term

Amortizes based on these parameters. In a scalar context, returns the initial monthly payment.
In an array context, returns a threeitem list consisting of: the initial monthly payment, the total paid toward interest, and the loan object, in case you want to do things with it.
Example usages:
$monthly_payment = Business::US_Amort::simple(123654, 9.25, 20);
($monthly_payment, $total_toward_interest, $o)
= Business::US_Amort::simple(123654, 9.25, 20);
Of course, if you find yourself doing much of anything with the loan object, you probably should be using the OOP interface instead of the functional one.
OBJECT ATTRIBUTES
All attributes for this class are scalar attributes. They can be read via:
$thing = $loan>principal OR $thing = $loan>{'principal'}
or set via:
$loan>principal(VALUE) OR $loan>{'principal'} = VALUE
MAIN ATTRIBUTES
These attributes are used as parameters to the run
method.
 principal

The principal amount of the loan.
 interest_rate

The annual rate, expressed like 8.3, not like .083.
Note that if you're defining callbacks, you can change this attribute at any time in your callbacks, to change the rate of interest from then on.
 term

The term of the loan, in years, not months.
 callback_before_monthly_calc

If set, this should be a coderef to a routine to call at the beginning of each month, before any calculations are done. The one parameter passed to this routine, in $_[0], is the object. See the SYNOPSIS, above, for an example.
 callback_after_monthly_calc

If set, this should be a coderef to a routine to call at the end of each month, after all monthly calculations are done. The one parameter passed to this routine, in $_[0], is the object.
 block_table

If set to true, this inhibits
run
from adding totable
. (This is false by default.) If you're not going to accesstable
, set this to true before callingrun
 it'll speed things up and use less memory.  start_date

If set to a date in the format "YYYYMM",
_date
will be defined appropriately for each month. You can setstart_date
to the current month by just saying $loan>start_date_be_now.  cent_rounding

If set to true, figures are rounded to the nearest cent at appropriate moments, so as to avoid having to suppose that the debtor is to make a monthly payment of $1025.229348723948 on a remaining principal of $196239.12082309123408, or the like.
These attributes are set by the run
method:
 initial_monthly_payment

The monthly payment that follows from the basic amortization parameters given. Compare with
_monthly_payment
.  total_paid_interest

The total amount paid toward interest during the term of this loan.
 total_month_count

The total number of months the loan took to pay off. E.g., "12" for a loan that took 12 months to pay off.
 table

This will be a reference to a list of copies made of the object ("snapshots") each month. You can then use this if you want to generate a dump of particular values of the object's state in each month.
Note that snapshots have their
am_snapshot
attribute set to true, and have theirtable
attribute set to undef. (Otherwise this'd be a circular data structure, which would be a hassle for you and me.)  error

A string explaining any error that might have occurred, which would/should accompany
run
returning 0. Use like:$loan>run or die("Run failed: " . $loan>error);
Other attributes:
 am_snapshot

This attribute is set to true in snapshots, as stored in
table
.  _month_count_limit

This is a variable such that if the month count ever exceeds this amount, the main loop will abort. This is intended to keep the iterator from entering any infinite loops, even in pathological cases. Currently the
run
method sets this to twelve plus twice the number of months that it's expected this loan will take. Increase as necessary.
ITERATION ATTRIBUTES
These are attributes of little or no interest once run
is done, but may be of interest to callbacks while run
is running, or may be of interest in examining snapshots in table
.
 _month_count

This is how many months we are into the loan. The first month is 1.
 _abort

If you want callbacks to be able to halt the iteration for some reason, you can have them set
_abort
to true. You may also choose to seterror
to something helpful.  _monthly_payment

The amount to be paid to toward the principal each month. At the start of the loan, this is set to whatever
initial_monthly_payment
is figured to be, but you can manipulate_monthly_payment
with callbacks to change how much actually gets paid when.  _remainder

The balance on the loan.
 _date

The given month's date, if known, in the format "YYYYMM". Unless you'd set the
start_date
to something, this will be undef.  _h

The interest to be paid this month.
 _old_amount

What the remainder was before we made this month's payment.
 _c

The current monthly payment, minus the monthly interest, possibly tweaked in the last month to avoid paying off more than is actually left on the loan.
METHODS
 $loan = Business::US_Amort>new

Creates a new loan object.
 $loan>copy

Copies a loan object or snapshot object. Also performs a somewhat deep copy of its table, if applicable.
 $loan>destroy

Destroys a loan object. Probably never necessary, given Perl's garbage collection techniques.
 $loan>start_date_be_now

This sets
start_date
to the current date, based on$^T
.  $loan>run

This performs the actual amortization calculations. Returns 1 on success; otherwise returns 0, in which case you should check the
error
attribute.  $loan>dump_table

This method dumps a few fields selected from snapshots in the
table
of the given object. It's here more as example code than as anything particularly useful. See the source. You should be able to use this as a basis for making code of your own that dumps relevant fields from the contents of snapshots of loan objects.
REMEMBER
When in panic or in doubt, run in circles, scream and shout.
Or read the source. I really suggest the latter, actually.
WARNINGS
* There's little or no sanity checking in this class. If you want to amortize a loan for $2 at 1% interest over ten million years, this class won't stop you.
* Perl is liable to produce tiny math errors, like just about any other language that does its math in binary but has to convert to and from decimal for purposes of human interaction. I've seen this surface as tiny discrepancies in loan calculations  "tiny" as in less than $1 for even multimilliondollar loans amortized over decades.
* Moreover, oddities may creep in because of roundoff errors. This seems to result from the fact that the formula that takes term, interest rate, and principal, and returns the monthly payment, doesn't know that a realworld monthly payment of "$1020.309" is impossible  and so that ninth of a cent difference can add up across the months. At worst, this may cause a 30yearloan loan coming to term in 30 years and 1 month, with the last payment being needed to pay off a balance of two dollars, or the like.
These errors have never been a problem for any purpose I've put this class to, but be on the look out.
DISCLAIMER
This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.
But let me know if it gives you any problems, OK?
COPYRIGHT
Copyright 19992002, Sean M. Burke sburke@cpan.org
, all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
AUTHOR
Sean M. Burke sburke@cpan.org