[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GT] SVN Commit r641 - branches/exp/GT/Indicators
Author: thomas
Date: 2008-06-17 04:47:51 +0200 (Tue, 17 Jun 2008)
New Revision: 641
Added:
branches/exp/GT/Indicators/BOLENV.pm
branches/exp/GT/Indicators/VIDYA.pm
Log:
Two indicators: A generic bollinger-type band around an indicator and Chande's VIDYA
Added: branches/exp/GT/Indicators/BOLENV.pm
===================================================================
--- branches/exp/GT/Indicators/BOLENV.pm (rev 0)
+++ branches/exp/GT/Indicators/BOLENV.pm 2008-06-17 02:47:51 UTC (rev 641)
@@ -0,0 +1,100 @@
+package GT::Indicators::BOLENV;
+
+# Copyright 2000-2002 Rapha�Hertzog, Fabien Fulhaber
+# Copyright 2008 Thomas Weigert
+# Based on and for GeniusTrader (C) 2000-2002 Rapha�Hertzog, Fabien Fulhaber
+# This file is distributed under the terms of the General Public License
+# version 2 or (at your option) any later version.
+
+# Standards-Version: 1.0
+
+# $Id$
+
+use strict;
+use vars qw(@ISA @NAMES @DEFAULT_ARGS);
+
+use GT::Indicators;
+use GT::Indicators::StandardDeviation;
+use GT::Prices;
+
+
AT
ISA = qw(GT::Indicators);
+
AT
NAMES = ("BOLENV[#1,#3]","BOLENVSup[#1,#2,#3]","BOLENVInf[#1,#2,#3]");
+
AT
DEFAULT_ARGS = (20, 2, "{I:SMA 20 {I:Prices CLOSE}}", "{I:Prices CLOSE}");
+
+=head2 GT::Indicators::BOL
+
+This indicator draws Bollinger style envelopes around some
+indicator. The envelope bands are drawn at standard devidation levels
+above and below the indicator.
+
+The first argument is the length of the indicator to consider in calculating
+the standard deviation, the 2nd argument is the distance of the bands, in terms
+of multiple of standard deviations.
+
+The indicator is given as the 3rd argument, while the standard deviation
+is computed based on the 4th argument. (Typically, these arguments are
+related as seen above, but need not be.)
+
+Note that
+ BOL[#1,#2,#3] = BOLENV[#1,#2,SMA[#1,#3,#4],#4]
+
+=cut
+
+sub initialize {
+ my ($self) = @_;
+
+ if ($self->{'args'}->is_constant(1)) {
+ $self->add_prices_dependency($self->{'args'}->get_arg_constant(1));
+ }
+
+ $self->{'sd'} = GT::Indicators::StandardDeviation->new([ $self->{'args'}->get_arg_names(1),
+ $self->{'args'}->get_arg_names(4) ]);
+
+ if ($self->{'args'}->is_constant(1)) {
+ $self->add_prices_dependency($self->{'args'}->get_arg_constant(1));
+ $self->add_arg_dependency(3, $self->{'args'}->get_arg_constant(1));
+ $self->add_arg_dependency(4, $self->{'args'}->get_arg_constant(1));
+ $self->add_indicator_dependency($self->{'sd'}, 1);
+ }
+}
+
+=head2 GT::Indicators::BOLENV::calculate($calc, $day)
+
+=cut
+
+sub calculate {
+ my ($self, $calc, $i) = @_;
+ my $indic = $calc->indicators;
+ my $period = $self->{'args'}->get_arg_values($calc, $i, 1);
+ my $nsd = $self->{'args'}->get_arg_values($calc, $i, 2);
+ my $sd = $self->{'sd'};
+ my $sd_name = $sd->get_name;
+ my $bol_name = $self->get_name(0);
+ my $bolsup_name = $self->get_name(1);
+ my $bolinf_name = $self->get_name(2);
+
+ return if ($indic->is_available($bol_name, $i) &&
+ $indic->is_available($bolsup_name, $i) &&
+ $indic->is_available($bolinf_name, $i));
+ return if (! $self->check_dependencies($calc, $i));
+
+ # Get indicator value
+ my $bol_value = $indic->get($bol_name, $i) ||
+ $self->{'args'}->get_arg_values($calc, $i, 3);
+
+ # Get Standard Deviation value
+ my $sd_value = $indic->get($sd_name, $i);
+
+ # Bollinger Band Sup is equal to the value of the indicator + standard deviation
+ my $bolsup_value = $bol_value + ($nsd * $sd_value);
+
+ # Bollinger Band Inf is equal to the value of the indicator - standard deviation
+ my $bolinf_value = $bol_value - ($nsd * $sd_value);
+
+ # Return the results
+ $indic->set($bol_name, $i, $bol_value);
+ $indic->set($bolsup_name, $i, $bolsup_value);
+ $indic->set($bolinf_name, $i, $bolinf_value);
+}
+
+1;
Added: branches/exp/GT/Indicators/VIDYA.pm
===================================================================
--- branches/exp/GT/Indicators/VIDYA.pm (rev 0)
+++ branches/exp/GT/Indicators/VIDYA.pm 2008-06-17 02:47:51 UTC (rev 641)
@@ -0,0 +1,184 @@
+package GT::Indicators::VIDYA;
+
+# Copyright 2000-2002 Rapha�Hertzog, Fabien Fulhaber
+# Copyright 2008 Thomas Weigert
+# Based on and for GeniusTrader (C) 2000-2002 Rapha�Hertzog, Fabien Fulhaber
+# This file is distributed under the terms of the General Public License
+# version 2 or (at your option) any later version.
+
+# Standards-Version: 1.0
+
+# $Id: VIDYA.pm 621 2008-04-26 15:26:51Z thomas $
+
+use strict;
+use vars qw(@ISA @NAMES @DEFAULT_ARGS);
+
+use GT::Indicators;
+use GT::Indicators::SMA;
+use GT::Eval;
+
+
+
AT
ISA = qw(GT::Indicators);
+
AT
NAMES = ("VIDYA[#*]", "Days");
+
AT
DEFAULT_ARGS = (9, "{I:G:Divide {I:CMO 10 {I:Prices CLOSE}} 100}", "{I:Prices CLOSE}");
+
+=head1 NAME
+
+GT::Indicators::VIDYA - Variable Length Dynamic Average
+
+=head2 DESCRIPTION
+
+The VIDYA indicator was developed by Trushar Chande and presented 1994
+in the book "The New Technical Trader". Its "length" is adjusted
+automatically, based on price action. VIDYA adapts to market volatility,
+increasing its length when prices trade in a narrow range, and shortening
+it when prices move rapidly.
+
+In addition to the indicator, I:VIDYA also outputs the effective length
+of the indicator for each day.
+
+=head2 Parameters
+
+=over
+
+=item N (default 9)
+
+The number of equivalent days the average is calculated over.
+
+A scaling factor. Given N, alpha
+by
+
+ alpha = 2 / (N + 1)
+
+and thus, solving for N
+
+ N = (2 - alpha)/alpha
+
+gives us the "length" corresponding to a neutral market. Care must be taken
+that alpha*k is positive.
+
+=item k (default {I:G:Divide {I:CMO 10 {I:Prices CLOSE}} 100})
+
+k is the current value of a measure of market volatility, or more general,
+any dimensionless series. Typical examples are the volatility index
+STDDEV(n)/STDDEV(reference), the coefficient of determination, the
+Chande Momentum Oscillator, etc.
+
+The absolute value is chosen to ensure this quantity is positive.
+
+=item input stream C (default {I:Prices CLOSE})
+
+The third argument can be used to specify an other stream of input data
+for the average instead of the close prices. This could be another price
+data, or an indicator.
+
+=back
+
+=head2 Calculation
+
+ alpha = 2 / ( N + 1 )
+ VIDYA[n] = alpha * k * C[n-1] + (1 - alpha * k * C[n])
+
+We chose C[0] as the starting value, but we could use a suitable average
+such as SMA also.
+
+=head2 Creation
+
+ GT::Indicators::VIDYA->new()
+ GT::Indicators::VIDYA->new([9])
+
+If you need a 9 days equivalent VIDYA of the opening prices you can write
+one of those lines :
+
+ GT::Indicators::VIDYA->new([9, "{I:CMO}", "{I:Prices OPEN}"])
+
+=head2 Examples
+
+ ./display_indicator.pl --tight --nb-item=20 I:VIDYA 13000 5 {I:G:Divide {I:StandardDeviation 10} {I:SMA 50 {I:StandardDeviation 50}}}
+
+ ./display_indicator.pl --tight --nb-item=20 I:VIDYA 13000 5 {I:RSquare}
+
+=cut
+
+sub calculate {
+ my ($self, $calc, $i) = @_;
+ my $indic = $calc->indicators;
+ my $period = $self->{'args'}->get_arg_values($calc, $i, 1);
+ my $name = $self->get_name;
+
+ return if (! defined($period));
+
+ $self->remove_volatile_dependencies();
+ $self->add_volatile_arg_dependency( 2, $period );
+ $self->add_volatile_arg_dependency( 3, $period );
+
+ return if ($indic->is_available($name, $i));
+ return if (! $self->check_dependencies($calc, $i));
+
+ my $alpha = 2 / ($period + 1);
+ my $k = abs ($self->{'args'}->get_arg_values($calc, $i, 2) );
+
+ my $kalpha = $k * $alpha;
+ die "k ($k) * alpha ($alpha) must not be negative; please adjust your period.\n" if $kalpha < 0;
+
+ # Compute the effective days used
+ my $days = (2 - $kalpha)/$kalpha unless $kalpha == 0;
+
+ my $yesterday = $indic->get($name, $i - 1) || $self->{'args'}->get_arg_values($calc, $i - 1, 3);
+
+ my $vidya = $kalpha * $self->{'args'}->get_arg_values($calc, $i - 1, 3) +
+ (1 - $kalpha) * $yesterday;
+
+ $indic->set($name, $i, $vidya);
+ $indic->set($self->get_name(1), $i, $days);
+
+}
+
+sub calculate_interval {
+ my ($self, $calc, $first, $last) = @_;
+ my $indic = $calc->indicators;
+ my $period = $self->{'args'}->get_arg_constant(1);
+ my $name = $self->get_name;
+
+ return if (! defined($period));
+
+ $self->remove_volatile_dependencies();
+ $self->add_volatile_arg_dependency( 2, $period );
+ $self->add_volatile_arg_dependency( 3, $period );
+
+ return if ($indic->is_available_interval($name, $first, $last));
+ while (! $self->check_dependencies_interval($calc, $first, $last)) {
+ return if $first == $last;
+ $first++;
+ next;
+ }
+
+
+ my $alpha = 2 / ($period + 1);
+
+ $indic->set($name, $first - 1, $self->{'args'}->get_arg_values($calc, $first - 1, 3));
+
+ for (my $i=$first;$i<=$last;$i++) {
+
+ my $k = abs ($self->{'args'}->get_arg_values($calc, $i, 2) );
+
+ my $kalpha = $k * $alpha;
+ die "k ($k) * alpha ($alpha) must not be negative; please adjust your period.\n" if $kalpha < 0;
+
+ # Compute the effective days used
+ my $days = (2 - $kalpha)/$kalpha unless $kalpha == 0;
+
+ my $yesterday = $indic->get($name, $i - 1);
+
+ my $vidya = $kalpha * $self->{'args'}->get_arg_values($calc, $i - 1, 3) +
+ (1 - $kalpha) * $yesterday;
+
+ $indic->set($name, $i, $vidya);
+ $indic->set($self->get_name(1), $i, $days);
+
+ }
+
+ return ($first, $last);
+}
+
+1;