File Coverage

blib/lib/Math/Business/RSI.pm
Criterion Covered Total %
statement 82 83 98.8
branch 20 28 71.4
condition n/a
subroutine 14 15 93.3
pod 0 10 0.0
total 116 136 85.2


line stmt bran cond sub pod time code
1             package Math::Business::RSI;
2              
3 3     3   3592 use strict;
  3         7  
  3         58  
4 3     3   10 use warnings;
  3         4  
  3         52  
5 3     3   10 use Carp;
  3         5  
  3         104  
6              
7 3     3   904 use Math::Business::SMA;
  3         6  
  3         73  
8 3     3   537 use Math::Business::EMA;
  3         5  
  3         1683  
9              
10             1;
11              
12 0     0 0 0 sub tag { (shift)->{tag} }
13              
14             sub recommended {
15 1     1 0 4 my $class = shift;
16              
17 1         1 $class->new(14);
18             }
19              
20             sub new {
21 5     5 0 288 my $class = shift;
22 5         35 my $this = bless {
23             U => Math::Business::EMA->new,
24             D => Math::Business::EMA->new,
25             RSI => undef,
26             cy => undef,
27             }, $class;
28              
29 5         10 my $alpha = shift;
30 5 100       9 if( defined $alpha ) {
31 4         8 $this->set_alpha( $alpha );
32             }
33              
34 5         10 return $this;
35             }
36              
37             sub set_alpha {
38 4     4 0 5 my $this = shift;
39 4         5 my $alpha = shift;
40              
41             # NOTE: this alpha is different than you might think ... it's really inverse alpha
42             # Wilder uses alpha=14 instead of alpha=(1/14) like you might expect
43              
44 4         7 my $days = 2*$alpha - 1; # so days is 2*$alpha-1 instead of the expected 2*(1/$alpha)-1
45              
46 4         5 eval { $this->set_days( $days ) };
  4         8  
47 4 50       7 croak "set_alpha() is basically set_days(2*$alpha-1), which complained: $@" if $@;
48 4         6 $this->set_tag;
49             }
50              
51             sub set_standard {
52 1     1 0 2 my $this = shift;
53 1         2 my $rm = ref $this->{U};
54              
55 1 50       4 if( $rm =~ m/SMA/ ) {
56 1         3 $this->{U} = Math::Business::EMA->new;
57 1         2 $this->{D} = Math::Business::EMA->new;
58              
59 1 50       2 if( my $d = $this->{days} ) {
60 1         2 $this->set_days($d);
61             }
62             }
63 1         2 $this->set_tag;
64             }
65              
66             sub set_cutler {
67 1     1 0 3 my $this = shift;
68 1         1 my $rm = ref $this->{U};
69              
70 1 50       3 if( $rm =~ m/EMA/ ) {
71 1         4 $this->{U} = Math::Business::SMA->new;
72 1         2 $this->{D} = Math::Business::SMA->new;
73              
74 1 50       3 if( my $d = $this->{days} ) {
75 1         3 $this->set_days($d);
76             }
77             }
78 1         2 $this->set_tag;
79             }
80              
81             sub set_days {
82 7     7 0 8 my $this = shift;
83 7         9 my $arg = int(shift);
84              
85 7 50       10 croak "days must be a positive non-zero integer" if $arg <= 0;
86              
87 7         26 $this->{U}->set_days($this->{days} = $arg);
88 7         16 $this->{D}->set_days($arg);
89 7         10 delete $this->{cy};
90 7         8 delete $this->{RSI};
91 7         10 $this->set_tag;
92             }
93              
94             sub set_tag {
95 13     13 0 19 my $this = shift;
96              
97 13 100       39 if( $this->{U}->isa("Math::Business::EMA") ) {
98 11         22 $this->{tag} = "RSI($this->{days})";
99              
100             } else {
101 2         4 $this->{tag} = "RSI($this->{days},cutler)";
102             }
103             }
104              
105             sub insert {
106 2527     2527 0 2926 my $this = shift;
107 2527         2462 my $close_yesterday = $this->{cy};
108              
109 2527         2308 my $EMA_U = $this->{U};
110 2527         2224 my $EMA_D = $this->{D};
111              
112 2527 50       2841 croak "You must set the number of days before you try to insert" if not $this->{days};
113 2527         3011 while( defined( my $close_today = shift ) ) {
114 3277 100       3604 if( defined $close_yesterday ) {
115 3271         3236 my $delta = $close_today - $close_yesterday;
116              
117 3271         3578 my ($U,$D) = (0,0);
118 3271 100       4219 if( $delta > 0 ) {
    100          
119 1619         1433 $U = $delta;
120 1619         1422 $D = 0;
121              
122             } elsif( $delta < 0 ) {
123 1635         1438 $U = 0;
124 1635         1470 $D = abs $delta;
125             }
126              
127 3271         5276 $EMA_U->insert($U);
128 3271         4085 $EMA_D->insert($D);
129             }
130              
131 3277 100       4036 if( defined(my $eu = $EMA_U->query) ) {
132 3187         3768 my $ed = $EMA_D->query;
133 3187 50       4282 my $rs = (($ed == 0) ? 100 : $eu/$ed ); # NOTE: This is by definition apparently.
134              
135 3187         3916 $this->{RSI} = 100 - 100/(1+$rs);
136             }
137              
138 3277         4792 $close_yesterday = $close_today;
139             }
140              
141 2527         3139 $this->{cy} = $close_yesterday;
142             }
143              
144             sub query {
145 2528     2528 0 2198 my $this = shift;
146              
147 2528         3268 return $this->{RSI};
148             }
149              
150             __END__