[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GT] thoughts for cookbook ...



thomas

just some thoughts i think would help a complete novice like me get
into more trouble faster ... ;-)

don't forget your initial bits defining the terminology

Time series: a sequence of data values, ordered linearly by time (e.g.,
the series of the close of SPY). Note that this could also be an
intermediate result during the computation of an indicator.

An indicator is also a time series, of course.

An indicator is constructed by all or some of the following:

 (a) one or more data series.

 (b) an application of a transformation to a time series (results
     in a data series).

 (c) the sequential application of a computation on the current
     values of one or more time series.


make whatever use of the following you can or care to ...

aloha

ras




i)
while it might be over-the-top and out-of-scope, it would be nice to
have an explanation/discussion of when (what other method) calls
each of the indicator methods.


for example
initialize method is called when the indicator object is first created
by create_standard_object. this is typically a statement like:

  my $indic = create_standard_object("$indicator", @ARGV);

     where $indicator is a string like 'I:SMA', 'I:BOL/1'
     an    @ARGV contains the arguments to the indicator

  see perldoc -t GT/Eval.pm for details on create_standard_object method

this might be especially useful for calculate, calculate_all
and calculate_interval which are still something of a mystery to me.
(actually i believe the two methods used to compute an indicator are:
   i) $indicator->calculate_interval($calc, $first, $last);
  ii) GT::Indicators::calculate_interval($indicator, $calc, $first, $last);
where the latter would be the inherited method if the indicator itself
elected not to provide its own calculate_interval.)

calculate_interval (inherited or not) must call calculate as required
to perform the computations.


ii)   -- covered a bit in 3. output value
at the very minimum an indicator requires a calculate method.

the calculate method must perform all the operations necessary to compute
the value of the indicator for each time period and then call the following method with that value, the time period and the indicator name:
 $calc->indicators->set(<indicator_name>, <time_period>, <indicator_value>);

 see perldoc -t GT/CacheValues.pm for details on set method


iii) section 4. initialization
when writing an indicator if there are 'expectations' about the nature
of an argument (there are only two kinds of arguments?
constants and functions (series)?
(the question marks above denote that i'm not sure of the complete truth
of the preceeding phrase)

so, if for example, an indicator that expects ('requires') a constant
but gets a function (series) should detect it and throw an exception.
same goes for expecting a function (series) but getting a constant.
similarly, if there are no default arguments defined via the @DEFAULT_ARGS
array and arguments are required an exception should be thrown.

by detecting and handling argument errors in the initialize method the
indicator will be able to give the user substantially better information
about the problem than the following, which occurs when an indicator doesn't
perform appropriate argument validation and exception processing locally
is passed a constant when expecting a function (series):

Can't use string ("2") as an ARRAY ref while "strict refs" in use at ../GT/ArgsTree.pm line 204.

since the initialize method is only called once, when the indicator object
is created, there is very little additional overhead doing more, rather than
less, argument validation checking and exception processing.

here's a perl fragment for use in an indicators initialize method
that could serve as starting point to validate indicator arguments.

1    # indicator requires functions for 2nd and 3rd arguments
2    my $err = 0;
3    ( my $msg_n = $NAMES[0] ) =~ s/^(.*)\[.*/$1/;
4    my $msg = "$msg_n: argument error\n";
5    # skip $self and first arg
6    for ( my $i = 2; $i < @{ $self->{'args'} }; ++$i ) {
7      if ($self->{'args'}->is_constant($i)) {
8        my $msg_txt = "must be a function (series)\n";
9        $msg .= join "", "\targ #$i \"$self->{'args'}[$i]\" $msg_txt";
10        ++$err;
11      }
12    }
13    die "$msg" if ( $err );

all arguments that should not be constants are checked and the
user message includes both the indicator name as well as complete
info about which arguments are in error.