Annuity calculation/process.pl

From Organic Design wiki
Revision as of 13:20, 8 December 2011 by Nad (talk | contribs) (Category:PERL)

<perl>

  1. !/usr/bin/perl -w

use strict; use CGI::Lite;

  1. 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);

  1. 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);
  1. 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

);

  1. 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();


print 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);

  1. 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>