File Coverage

blib/lib/GD/Graph/candlesticks.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             #==========================================================================
2             # Copyright (c) 2008 Paul Miller
3             #==========================================================================
4              
5             package GD::Graph::candlesticks;
6              
7 1     1   678 use strict;
  1         2  
  1         45  
8 1     1   6 use warnings;
  1         1  
  1         30  
9              
10 1     1   528 use GD::Graph::mixed; # NOTE: we pull this in so we can modify part of it.
  0            
  0            
11             use GD::Graph::axestype;
12             use GD::Graph::utils qw(:all);
13             use GD::Graph::colour qw(:colours);
14              
15             use constant PI => 4 * atan2(1,1);
16              
17             our $VERSION = "0.9703";
18             our @ISA = qw(GD::Graph::axestype);
19              
20             our %DEFAULT = (
21             correct_width => 1,
22             candlestick_width => 7,
23             candlestick_spacing => 0,
24             candlestickgroup_spacing=> 25,
25             );
26              
27             push @GD::Graph::mixed::ISA, __PACKAGE__;
28              
29             # working off gdgraph/Graph/bars.pm (in addition to ohlc.pm)
30              
31             # initialise {{{
32             sub initialise {
33             my $self = shift;
34              
35             $self->SUPER::initialise();
36              
37             while (my($key, $val) = each %DEFAULT)
38             { $self->{$key} = $val }
39              
40             return 1;
41             }
42             # }}}
43             # _has_default {{{
44             sub _has_default {
45             my $this = shift;
46              
47             return $DEFAULT{$_[0]} if exists $DEFAULT{$_[0]};
48             return $this->SUPER::_has_default(@_);
49             }
50             # }}}
51             # draw_data_set {{{
52             sub draw_data_set {
53             my $this = shift;
54             my $ds = shift;
55              
56             my @values = $this->{_data}->y_values($ds) or
57             return $this->_set_error("Impossible illegal data set: $ds", $this->{_data}->error);
58              
59             # Pick a colour
60             my $dsci = $this->set_clr($this->pick_data_clr($ds));
61              
62             my $GX;
63             my ($ox,$oy, $cx,$cy, $lx,$ly, $hx,$hy); # NOTE: all the x's are the same...
64             for (my $i = 0; $i < @values; $i++) {
65             my $value = $values[$i];
66             next unless ref($value) eq "ARRAY" and @$value==4;
67             my ($open, $high, $low, $close) = @$value;
68              
69             if (defined($this->{x_min_value}) && defined($this->{x_max_value})) {
70             $GX = $this->{_data}->get_x($i);
71              
72             ($ox, $oy) = $this->val_to_pixel($GX, $value->[0], $ds);
73             ($hx, $hy) = $this->val_to_pixel($GX, $value->[1], $ds);
74             ($lx, $ly) = $this->val_to_pixel($GX, $value->[2], $ds);
75             ($cx, $cy) = $this->val_to_pixel($GX, $value->[3], $ds);
76              
77             } else {
78             ($ox, $oy) = $this->val_to_pixel($i+1, $value->[0], $ds);
79             ($hx, $hy) = $this->val_to_pixel($i+1, $value->[1], $ds);
80             ($lx, $ly) = $this->val_to_pixel($i+1, $value->[2], $ds);
81             ($cx, $cy) = $this->val_to_pixel($i+1, $value->[3], $ds);
82             }
83              
84             # if (!$this->{overwrite}) {
85             # my $candlestick_s = $this->{candlestick_spacing}/2;
86             # my $window = $this->{x_step} - $this->{candlestickgroup_spacing};
87             #
88             # foreach my $x ($ox, $hx, $lx, $cx) {
89             # $x = $x
90             # - $window/2
91             # + ($ds - 1) * $window/$this->{_data}->num_sets
92             # + $candlestick_s + 1;
93             # }
94             # }
95              
96             $this->candlesticks_marker($ox,$oy, $cx,$cy, $lx,$ly, $hx,$hy, $dsci );
97             $this->{_hotspots}[$ds][$i] = ['rect', $this->candlesticks_marker_coordinates($ox,$oy, $cx,$cy, $lx,$ly, $hx,$hy)];
98             }
99              
100             return $ds;
101             }
102             # }}}
103             # half_width {{{
104             sub half_width {
105             my $this = shift;
106              
107             return int( $this->{candlestick_width} / 2 ) if exists $this->{candlestick_width};
108             return 3;
109             }
110             # }}}
111             # candlesticks_marker_coordinates {{{
112             sub candlesticks_marker_coordinates {
113             my $this = shift;
114             my ($ox,$oy, $cx,$cy, $lx,$ly, $hx,$hy) = @_;
115              
116             my $h = $this->half_width;
117             my ($l,$t,$r,$b) = ($ox - $h, $hy, $ox + $h, $ly);
118             return ($t <= $b) ? ( $l, $t, $r, $b ) : ( $l, $b, $r, $t );
119             }
120             # }}}
121             # candlesticks_marker {{{
122             sub candlesticks_marker {
123             my $this = shift;
124             my ($ox,$oy, $cx,$cy, $lx,$ly, $hx,$hy, $mclr) = @_;
125             return unless defined $mclr;
126              
127             $this->{graph}->line( ($lx,$ly) => ($hx,$hy), $mclr );
128              
129             my $h = $this->half_width;
130             if( $cy>$oy ) {
131             $this->{graph}->filledRectangle( ($cx - $h, $cy) => ($ox + $h, $oy), $mclr );
132              
133             } else {
134             $this->{graph}->filledRectangle( ($cx - $h, $cy) => ($ox + $h, $oy), $this->{bgci} );
135             $this->{graph}->rectangle( ($cx - $h, $cy) => ($ox + $h, $oy), $mclr );
136             }
137              
138             return;
139             }
140             # }}}
141              
142             1;