package GT::Graphics::Object::BuySellPricesArrows; # based on BuySellArrows # Copyright 2000-2002 Raphaël Hertzog, Fabien Fulhaber # Copyright 2008 Robert A. Schmied # Copyright 2009 Chia-liang Kao, Jon Edwards # # * alters the standard BuySellArrows api # * support non-prices base ds for positioning the arrows. # * adds yet another perl prerequiste List::Util (is this even needed?) # # @@@ requires a mod to graphic.pl to parse the graphic directive # and to arrange for the appropriate data source(s) # >>> both left to the reader to develop and hopefully share ... # # This file is distributed under the terms of the General Public License # version 2 or (at your option) any later version. # $Id: BuySellPricesArrows.pm,v 1.1 2009/11/12 18:58:05 ras Exp ras $ use strict; use vars qw(@ISA); @ISA = qw(GT::Graphics::Object); use GT::Prices; use GT::Graphics::Object; use GT::Graphics::Driver; use GT::Graphics::Tools qw(:color); use GT::Conf; use List::Util qw(min max); GT::Conf::default("Graphic::BuySellArrows::BuyColor", "green"); GT::Conf::default("Graphic::BuySellArrows::SellColor", "red"); GT::Conf::default("Graphic::BuySellArrows::Distance", 8); GT::Conf::default("Graphic::Candle::Height", 3); GT::Conf::default("Graphic::BuySellArrows::SizeFactor", 1); # # SizeFactor can be used to adjust the default size in both height and width # without it the width cannot be altered # # i recommend altering the size via the SizeFactor and leave Graphic::Candle::Height at 3 # # i considered changing Graphic::Candle::Height to the more logical Graphic::BuySellArrows::Height # but didn't know if there was a ulterior motive for this name or not so i left it alone # # we should also transparent these colors as well -- ah well you can do # that in your gt config options file: # Graphic::BuySellArrows::BuyColor "[0,135,0,64]" # partly transparent dark green # Graphic::BuySellArrows::SellColor "[150,0,0,64]" # partly transparent dark red # =head1 GT::Graphics::Object::BuySellPricesArrows This graphical object display buy and sell arrows. NOTE: the pod for this module is an unfinished and out-of-data =head2 Description and Usage Instead of using the bar high/low directly from prices, it makes the buysellPricesarrow object taking datasource for high/low (which actually means sell/buy arrow positioning) for rendering the arrows. the object doesn't accept arguments when created, however it reads gt configure file for and sets these values (default values are indicated): Graphic::BuySellArrows::BuyColor "green" Graphic::BuySellArrows::SellColor "red" Graphic::BuySellArrows::Distance 8 Graphic::Candle::Height 3 Graphic::BuySellArrows::SizeFactor 1 note: the default SizeFactor of 1 should make this modified version work identically to the prior version personally, i find a Distance of about 24 and a SizeFactor of 3 to 6 makes the arrow plot better. in addition i prefer to darken the colors and make them partly transparent Graphic::BuySellArrows::BuyColor "[0,135,0,64]" # very dark green Graphic::BuySellArrows::SellColor "[150,0,0,64]" # dark red =head2 used in graphic.pl graphic configuration file as shown below: =head2 plotting on the primary price plot --add=BuySellPricesArrows(Systems::Generic \ {S::Generic::CrossOverUp {I:EMA 3} {I:EMA 7}} \ {S::Generic::CrossOverDown {I:EMA 3} {I:EMA 7}} \ ) --add=BuySellPricesArrows(Systems::Generic \ { S::Generic::CrossOverUp {I::MACD/1 26 52 20} {I::MACD/2 26 52 20} } \ { S::Generic::CrossOverDown {I::MACD/1 26 52 20} {I::MACD/2 26 52 20} } \ ) =head2 plotting arrows on a secondary zone --add=New-Zone(5) --add=New-Zone(100) --add=Curve(I:MACD/1 26 52 20, [120, 40, 0]) --add=Curve(I:MACD/2 26 52 20, red) --add=Text("macd: 26 52 20", 2, 95, left, center, small, [120, 40, 0], arial) --add=Set-Scale(auto) --add=BuySellPricesArrows(Systems::Generic \ { S::Generic::CrossOverUp {I::MACD/1 26 52 20} {I::MACD/2 26 52 20} } \ { S::Generic::CrossOverDown {I::MACD/1 26 52 20} {I::MACD/2 26 52 20} } \ ) --add=Set-Special-Scale(auto,"log") NOTE: the pod for this module is an unfinished and out-of-data =cut sub init { my ($self, $high_ds, $low_ds, $min_high, $max_low) = @_; # Default values ... $self->{'buy_color'} = get_color( GT::Conf::get("Graphic::BuySellArrows::BuyColor") ); $self->{'sell_color'} = get_color( GT::Conf::get("Graphic::BuySellArrows::SellColor") ); $self->{'distance'} = GT::Conf::get("Graphic::BuySellArrows::Distance"); $self->{'height'} = GT::Conf::get("Graphic::Candle::Height"); $self->{'sizefactor'} = GT::Conf::get("Graphic::BuySellArrows::SizeFactor"); $self->{'high_ds'} = $high_ds; $self->{'low_ds'} = $low_ds; $self->{'min_high'} = $min_high; $self->{'max_low'} = $max_low; } sub display { my ($self, $driver, $picture) = @_; my $scale = $self->get_scale(); my $zone = $self->{'zone'}; my ($start, $end) = $self->{'source'}->get_selected_range(); my $space = $scale->convert_to_x_coordinate($start + 1) - $scale->convert_to_x_coordinate($start); my $xoff = int($space * $self->{'sizefactor'} / 2); my $arrowht = int($self->{'height'} * $self->{'sizefactor'}); for(my $i = $start; $i <= $end; $i++) { my ($low, $high) = map { $self->{$_}->get($i) } qw(low_ds high_ds); $low = min($low, $self->{max_low}) if defined $self->{max_low}; $high = max($high, $self->{min_high}) if defined $self->{min_high}; ($low, $high) = map { $scale->convert_to_y_coordinate($_) } ($low, $high); my $x = $scale->convert_to_x_coordinate($i); # Get the datasource value : # 1 => buy signal # 0 => no signal # -1 => sell signal my $value = $self->{'source'}->get($i); # Draw an Up and Green Arrow if value = 1 if ($value eq 1) { my $yb = $low - $self->{'distance'} - $arrowht; my $xa = $x + int($space / 2) - 1; ( $xa, my $ya ) = ( $xa, $low - $self->{'distance'} ); my ( $x2, $y2 ) = ( $xa - int($xoff / 2), $yb ); my ( $x3, $y3 ) = ( $xa + int($xoff / 2), $yb ); my @points = ( [$zone->absolute_coordinate( $xa, $ya )], [$zone->absolute_coordinate( $x2, $y2 )], [$zone->absolute_coordinate( $x3, $y3 )] ); $driver->filled_polygon($picture, $self->{'buy_color'}, @points); } # Draw a Down and Red Arrow if value = -1 if ($value eq -1) { my $yb = $high + $self->{'distance'} + $arrowht; my $xa = $x + int($space / 2) - 1; ( $xa, my $ya ) = ( $xa, $high + $self->{'distance'} ); my ( $x2, $y2 ) = ( $xa - int($xoff / 2), $yb ); my ( $x3, $y3 ) = ( $xa + int($xoff / 2), $yb ); my @points = ( [$zone->absolute_coordinate( $xa, $ya )], [$zone->absolute_coordinate( $x2, $y2 )], [$zone->absolute_coordinate( $x3, $y3 )] ); $driver->filled_polygon($picture, $self->{'sell_color'}, @points); } } } 1;