File Coverage

blib/lib/Finance/Performance/Calc.pm
Criterion Covered Total %
statement 60 72 83.3
branch 16 22 72.7
condition n/a
subroutine 11 11 100.0
pod 4 5 80.0
total 91 110 82.7


line stmt bran cond sub pod time code
1             package Finance::Performance::Calc;
2            
3 1     1   25921 use 5.006001;
  1         3  
  1         36  
4 1     1   5 use strict;
  1         2  
  1         33  
5 1     1   5 use warnings;
  1         6  
  1         142  
6            
7             require Exporter;
8            
9             our @ISA = qw (Exporter);
10             our %EXPORT_TAGS = ( 'all' => [ qw (ROR
11             link_ROR
12             ized_ROR
13             return_percentages
14             trace
15             ) ] );
16             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
17             our @EXPORT = qw ();
18             our $VERSION = '1.01';
19            
20 1     1   6 use Carp;
  1         2  
  1         1117  
21            
22             my %CFG = (
23             return_percentages => 0,
24             trace => 0
25             );
26            
27             sub return_percentages {
28 16     16 1 9656 my $retval = $CFG{'return_percentages'};
29 16 100       44 $CFG{'return_percentages'} = $_[0] if scalar(@_);
30 16         32 return $retval;
31             }
32            
33             sub trace {
34 32     32 1 2344 my $retval = $CFG{'trace'};
35 32 100       66 $CFG{'trace'} = $_[0] if scalar(@_);
36 32         62 return $retval;
37             }
38            
39             sub ROR {
40 8 50   8 1 73 if(scalar(@_) == 2) {
41             ## ($bmv, $emv) = ($_[0],$_[1]);
42 0 0       0 if($CFG{'trace'}) {
43 0         0 print "ROR Trace: Perf calc #1 of 1:\n";
44 0         0 print "BMV = $_[0]\n";
45 0         0 print "EMV = $_[1]\n";
46 0         0 print "ROR = " . _decimal_to_pct(($_[1]-$_[0])/$_[0]) . " ( (EMV - BMV)/BMV, ($_[1]-$_[0])/$_[0] )\n";
47             }
48 0         0 return _decimal_to_pct(($_[1]-$_[0])/$_[0]);
49             }
50            
51             ## Validate args
52 8         24 my %args = @_;
53 8 50       19 if (!defined($args{'bmv'})) {
54 0         0 push @{$args{'errs'}}, "Required argument 'bmv' not specified";
  0         0  
55             }
56 8 50       19 if (!defined($args{'emv'})) {
57 0         0 push @{$args{'errs'}}, "Required argument 'emv' not specified";
  0         0  
58             }
59 8 50       17 if ($args{'errs'}) {
60 0         0 croak join("\n",@{$args{'errs'}});
  0         0  
61             }
62            
63 8         29 my @rors = ();
64            
65             ## Treat bmv and emv as cash flow zero events at the boundry points.
66 8         10 unshift @{$args{'flows'}},{mvpcf=>$args{'bmv'},cf=>0.0};
  8         2247  
67 8         19 push @{$args{'flows'}},{mvpcf=>$args{'emv'},cf=>0.0};
  8         31  
68            
69 8         14 my $idx = undef;
70 8         15 for (my $i = 0;$i
  32         92  
71            
72             ## If you are looking for optimizations, don't bother trying
73             ## to replace the 'my' vars. I tried it, it wasn't faster.
74 24         54 my $bmv = $args{'flows'}->[$i]->{mvpcf} + $args{'flows'}->[$i]->{cf};
75 24         39 my $emv = $args{'flows'}->[$i+1]->{mvpcf};
76 24         35 push @rors, ($emv - $bmv)/$bmv;
77 24 100       62 if($CFG{'trace'}) {
78 14         27 print "ROR Trace: Perf calc #" . ($i+1) . " of " . (scalar(@{$args{'flows'}})-1) . ":\n";
  14         105  
79 14         84 print "BMV = $bmv (mvpcf $args{'flows'}->[$i]->{mvpcf} + cf $args{'flows'}->[$i]->{cf})\n";
80 14         71 print "EMV = $emv (mvpcf $args{'flows'}->[$i+1]->{mvpcf})\n";
81 14         120 print "ROR = $rors[-1] ( (EMV - BMV)/BMV, ($emv - $bmv)/$bmv )\n";
82             }
83             }
84 8         27 return link_ROR(@rors);
85             }
86            
87             sub link_ROR {
88             ## Use @_ and save the memcopys.
89             ## my @returns = @_;
90 12     12 0 43 my $ror = (map{$_+1.00} map{_pct_to_decimal($_)} shift )[0];
  12         33  
  12         29  
91 12         18 my $idx = 1;
92 12         28 for(map{$_+1.00} map{_pct_to_decimal($_)} @_) {
  24         52  
  24         36  
93 24 100       50 print "Link @{[$idx++]} of @{[scalar(@_)]}: $ror * $_ = " if ($CFG{'trace'});
  14         53  
  14         435  
94 24         69 $ror *= $_;
95 24 100       116 print "$ror\n" if ($CFG{'trace'});
96             }
97 12         38 return _decimal_to_pct($ror - 1.0);
98             }
99            
100             sub ized_ROR {
101             ## Save the memory copy by using @_
102             ## my ($ror,$periods) = ($_[0],$_[1])
103 4     4 1 30 return _decimal_to_pct(((_pct_to_decimal($_[0])+1.0) ** (1.0/$_[1]))-1);
104             }
105            
106             sub _pct_to_decimal {
107 40     40   51 my $decimal = $_[0];
108 40         136 $decimal =~ s|(.*)%|$1/100.|e;
  8         46  
109 40         129 return $decimal;
110             }
111            
112             sub _decimal_to_pct {
113 16 100   16   108 return ($CFG{'return_percentages'}
114             ? ($_[0] * 100) . '%'
115             : $_[0]);
116             }
117            
118             1;
119             __END__