Annuity calculation/process.pl
<perl>
- !/usr/bin/perl -w
use strict; use CGI::Lite;
- 1) Setup
print "Content-type: text/html\n\n";
my $Lite = new CGI::Lite; my %form_data = $Lite -> parse_form_data($ENV{'REQUEST_METHOD'});
if(exists $form_data{debug})
{
print "=============== DEBUG ==============
";
foreach( keys %form_data) {
print "$_ => $form_data{$_}
";
}
print "====================================
";
}
my ($i, $ip, $n, $p, $C,$roundup)=(0.0685,12, 25, 52, 106000,0);
($form_data{"i"}) && ($i = $form_data{i}); ($form_data{"ip"}) && ($i = &ip_to_i($form_data{"i"}, $form_data{"ip"}));
($form_data{"n"}) && ($n = $form_data{n}); ($form_data{"p"}) && ($p = $form_data{p}); ($form_data{"C"}) && ($C = $form_data{C}); ($form_data{"roundup"}) && ($roundup = $form_data{"roundup"});
my %period_name =
( 12 => "month", 26 => "fortnight", 52 => "week", );
my $period; ($period_name{$p}) ? ($period = $period_name{$p}) : ($period = "period");
my $table = &repayment_schedule(i=>$i, n=>$n, p=>$p, C=>$C, roundup => $roundup);
- print $table;
print qq(\n); &print_table($table); print qq();
sub print_table {
my $table = shift; my @seq = 0 .. $#{$table->[2]}; my $append=0; my ($interest_sum, $capital_sum, $payments_sum) = (0,0,0);
- Calculate totals
foreach my $i (@seq) {
$interest_sum += $table->[1]->[$i]; $capital_sum += $table->[2]->[$i]; $payments_sum += $table->[3];
} $interest_sum = sprintf("%10.2f", $interest_sum); $capital_sum = sprintf("%10.2f", $capital_sum); $payments_sum = sprintf("%10.2f", $payments_sum);
if(scalar @seq >20) {
my $end = $#seq; @seq = (@seq[0..9], @seq[($end-9) ..$end]); $append=1;
}
$i = sprintf("%1.5f", $i); my $i_12 = sprintf("%1.5f",&i_to_ip(i=>$i,p=>12)); my $i_26 = sprintf("%1.5f",&i_to_ip(i=>$i,p=>26));
my $i_52 = sprintf("%1.5f",&i_to_ip(i=>$i,p=>52));
print qq(
i_52 (weekly) | i_26 (fortnightly) | i_12 (monthly) | i (effective) | |||
$i_52 | < | $i_26 | < | $i_12 | < | $i |
);
- Printing details
print qq(term=$n \(yrs\)
payments=$p \(${period}ly\)
Capital=$C
);
print qq(
\n); print qq(\n); my $color="#FFFFFF"; foreach my $i (@seq) { format STDOUT =$color, $i+1, $table->[0]->[$i], $table->[1]->[$i], $table->[2]->[$i], $table->[3] .
if($color eq "#FFFFFF") {
write; $color = "#EEEEEE";
}else {
write; $color="#FFFFFF";
};
if($append && $i==9) {print qq(\n);
} }printf qq();
nth payment in arrears |
Loan outstanding at start of nth $period |
Interest due at end of nth $period |
Capital repaid at end of nth $period |
Repayment each nth $period |
@########## | @#########.## | @#########.## | @#########.## | @#########.## |
... | ... | ... | ... | ... |
Totals | $interest_sum | $capital_sum | $payments_sum |
\n);
- foreach(@{$table->[2]}){$a+=$_}
}
sub i_to_ip {
my %params = (
i => 0.0685, p => 52, @_, );
my $i = $params{"i"}; my $p = $params{"p"}; my $ip = (((1+$i)**(1/$p))-1)*$p; return $ip;
}
sub Anp {
my %params = (
i => 0.0685, n => 25, p => 52, @_, );
my $i = $params{"i"}; my $n = $params{"n"}; my $p = $params{"p"}; my $v = 1/(1+$i);
my $ip = &i_to_ip(i=>$i,p=>$p); my $Anp = (1-$v**$n)/$ip; return $Anp
}
sub repayment_schedule {
my %params = (
i=>0.0685, n=>25, p=>52, C=>106000, roundup => 0, @_, );
my $i = $params{"i"}; my $n = $params{"n"}; my $p = $params{"p"}; my $C = $params{"C"}; my $roundup = $params{"roundup"};
my $ip = &i_to_ip(i=>$i, p=>$p); my $Anp = &Anp(i=>$i, n=>$n, p=>$p);
my $np = $n * $p; my $payment = $C/($Anp*$p); if($roundup) {
$payment = &roundup($payment);
} my @loan = ($C); my @interest; my @capital; my ($loan_sum, $interest_sum, $capital_sum) = (0,0,0);
foreach(1 .. $np) {
push(@interest, $loan[-1] * $ip/$p); push(@capital, $payment - $loan[-1] * $ip/$p); push(@loan, $loan[-1] * (1+$ip/$p) - $payment);
} return [\@loan, \@interest, \@capital, $payment];
}
sub roundup
{
my $value = shift; $value =~ m/(\d+\.\d{2})(\d)/; if($2) {
$value = $1+0.01;
} return $value;
}
sub ip_to_i {
my $ip = shift; my $p = shift; my $i = (1 + $ip/$p)**$p -1; return $i;
} </perl>