[MAS-tips] Re: [MAS-discuss] Building indicators
Brought to you by:
jcochrane
From: Jim C. <jt...@di...> - 2003-05-26 05:07:34
|
Hi Paul. > Jim, > > I'm hoping you may be able to point me in the right direction. What I am > trying to build is an indicator ( I think its an indicator rather than > an analyser/generator ). The spec is:- > > Objective - to detect the point at which the MACD Histogram changes > direction. > > The direction of the histogram for the 3 prior days must be the same ( > in other words it slopes up/down then changes direction ). > > The intention is then to build a generator which tests the point at > which the change of direction occurs ( ie against a signal line of zero > slope ). > > I seem to have the change of direction sorted - but I am having trouble > understanding the way in which to build the 3 day test. You're using a slope analyzer for the change of direction, right? For the 3-day test, for such criteria I've found it helps to put it into algorithmic form (e.g, if slopesign (f)[now] = slopesign(f)[now-1] = slopesign(f)[now-2] then ..., or something like that), then translate the algorithm into a mas indicator/command structure. Sorry I don't have time to ponder what the exact structure would be, but I think because of the 3-day check you'll want an n-record-one-variable-function with n=3 that takes the macd hist. as input. And for the if slope... algorithm itself, I think you'll want to use the "boolean-numeric-client" command (which has been renamed in the current version as numeric-conditional-command, since it can be used for if/else logic). Once you figure out what to use for its "boolean operator" (the 3-day test), you can do something like: for its true command use a constant with value 1, for the false cmd, constant with value 0. (constant has been renamed numeric-value-command in the current version.) So if the result is 1, your condition holds; combine that with the slope change criteria with the and-operator and I think you'll have what you want. (I've also found that it helps to draw the command/operator tree you will use before using mas to create the indicator - you sort of have to turn yourself into a lisp machine :-).) (I think you can do what you want with 1.6.5, but you may want to upgrade, if you haven't already, to what I just put up on sourceforge (1.6.6g), since a couple powerful operator/commands have been added. This allowed me to implement parabolic SAR, which I don't believe was possible before. I'll include the "macl script" for parabolic SAR, since it may give you some good clues on how to use the numeric-conditional-command (with apologies for the difficult to parse "script syntax").) Hope this helps. Jim > > Hope this is within bounds of the discussion group - if not tell me - I > have a thick skin !! > > Regards, > > > > ------------------------------------------------------- > This SF.net email is sponsored by: ObjectStore. > If flattening out C++ or Java code to make your application fit in a > relational database is painful, don't do it! Check out ObjectStore. > Now part of Progress Software. http://www.objectstore.net/sourceforge > _______________________________________________ > Eiffel-mas-discuss mailing list > Eif...@li... > https://lists.sourceforge.net/lists/listinfo/eiffel-mas-discuss Here's the parabolic SAR script. # This macl -i script implements the Parabolic SAR formula. The formula # is fairly complex and requires the new NUMERIC_VALUED_COMMAND_WRAPPER # and COMMAND_SEQUENCE operators. Below, in comments, is a perl script # that implements the formula, which I used to test that I had gotten it # right and as a model for implementing the formula in MAS. ##!/usr/bin/perl -wn # #BEGIN { # $long = 1; # $short = 2; # $prev_sar = 0; # $prev_af = 0; # $prev_ep = 0; # $af_max = .1999; # $af_increment = .02; # $trade_state = $long; # $initial_af_value = .2; # $af = $initial_af_value; # $sar = 0; # $ep = 0; # $line_count = 0; # $succeeded = 1; #} # #END { # if ($succeeded) { # print "SUCCEEDED\n"; # } else { # print "FAILED\n"; # } #} # #if (/^#/) { next; } #@a = split; #$date = $a[0]; #$high = $a[1]; #$low = $a[2]; #++$line_count; # #if ($line_count == 1) { # init(); # $prev_sar = $sar; # $prev_af = $af; # $prev_ep = $ep; # next; #} # #execute(); #report(); #$prev_sar = $sar; #$prev_af = $af; #$prev_ep = $ep; # #sub sar_calculation { # return ($prev_ep - $prev_sar) * $prev_af + $prev_sar; #} # #sub init { # $sar = $low; # $ep = $high; #} # #sub execute { # if ($trade_state == $long) { # # long block # if (change_direction ($trade_state)) { # switch_to_short(); # $trade_state = $short; # } else { # # remain long # $sar = sar_calculation(); # if ($high > $prev_ep) { # if ($af < $af_max) { # $af = $af + $af_increment; # } # $ep = $high; # } # } # } else { # # short block # # check $trade_state == $short end # if (change_direction ($trade_state)) { # switch_to_long(); # $trade_state = $long; # } else { # # remain short # $sar = sar_calculation(); # if ($low < $prev_ep) { # if ($af < $af_max) { # $af = $af + $af_increment; # } # $ep = $low; # } # } # } #} # #sub change_direction { # my ($state) = @_; # my $Result = 0; # if ($state == $long) { # # Change from long to short? # $Result = $low < $prev_sar; # } else { # # Change from short to long? # die if $state != $short; # $Result = $high > $prev_sar; # } # return $Result; #} # #sub switch_to_short { # $sar = $prev_ep; # $af = $af_increment; # $ep = $low; # print "[S] " #} # #sub switch_to_long { # $sar = $prev_ep; # $af = $af_increment; # $ep = $high; # print "[L] " #} # #sub report { # print "($date) "; # print "af: $af "; # print "ep: $ep "; # printf ("sar:%.4f ", $sar); # $ref_af = $a[3]; # $ref_ep = $a[4]; # $ref_sar = $a[5]; # print "(refs: $ref_af $ref_ep $ref_sar) "; # if (! req($af, $ref_af)) { # print "[af differs]"; # $succeeded = 0; # } # if (! req($ep, $ref_ep)) { # print "[ep differs]"; # $succeeded = 0; # } # if (! req($sar, $ref_sar)) { # print "[sar differs]"; # $succeeded = 0; # } # print "\n"; #} # #sub req { # my ($r1, $r2) = @_; # return abs ($r1 - $r2) < .0001; #} e c n ONE_VARIABLE_FUNCTION c Parabolic SAR No Input Function y NUMERIC_VALUED_COMMAND_WRAPPER e Root # This is the top-level command sequence, which includes an initialization # section, run only for the first period, a main body, three assignments to # update the previous AF, EP, and SAR, and the SAR value by itself to # provide the result of the calculation. COMMAND_SEQUENCE e Main sequence y NUMERIC_CONDITIONAL_COMMAND e If 1st period, Init; else main body EQ_OPERATOR e First period? UNARY_LINEAR_OPERATOR e Period number No Input Function y INDEX_EXTRACTOR c shared UNARY_LINEAR_OPERATOR (Period number) c NUMERIC_VALUE_COMMAND e One n 1 NUMERIC_VALUED_COMMAND_WRAPPER e Initialization # The Initialization sequence - only executed for the first period, # consisting of "variable" and "constant" initializations COMMAND_SEQUENCE e Initialization sequence y NUMERIC_VALUE_COMMAND e Previous SAR value n 0 n y NUMERIC_VALUE_COMMAND e Previous EP value n 0 n y NUMERIC_VALUE_COMMAND e Previous AF value n 0 n y NUMERIC_VALUE_COMMAND e short n -1 n y NUMERIC_VALUE_COMMAND e AF increment y .02 n y NUMERIC_VALUE_COMMAND e Maximum AF value y .1999 n y NUMERIC_VALUE_COMMAND e Null operation n 0 n y NUMERIC_ASSIGNMENT_COMMAND e tradestate := long NUMERIC_VALUE_COMMAND e tradestate n 0 NUMERIC_VALUE_COMMAND e long n 1 n y NUMERIC_ASSIGNMENT_COMMAND e SAR := low NUMERIC_VALUE_COMMAND e SAR n 0 LOW_PRICE c n y NUMERIC_ASSIGNMENT_COMMAND e EP := high NUMERIC_VALUE_COMMAND e EP n 0 HIGH_PRICE c n y NUMERIC_ASSIGNMENT_COMMAND e AF := Initial AF value NUMERIC_VALUE_COMMAND e AF n 0 NUMERIC_VALUE_COMMAND e Initial AF value y .2 n n # The main body, executed on periods 2 to the end of the data - Corresponds # to the 'execute' routine in the perl script. NUMERIC_CONDITIONAL_COMMAND e Main body EQ_OPERATOR e tradestate = long? shared NUMERIC_VALUE_COMMAND ({tradestate}) c shared NUMERIC_VALUE_COMMAND ({long}) c # Corresponds to the "long block" in the perl script. NUMERIC_CONDITIONAL_COMMAND e Long block OR_OPERATOR e Change direction? AND_OPERATOR c shared EQ_OPERATOR (tradestate = long?) c LT_OPERATOR c shared LOW_PRICE c shared NUMERIC_VALUE_COMMAND ({Previous SAR value}) c AND_OPERATOR c EQ_OPERATOR e tradestate = short? shared NUMERIC_VALUE_COMMAND ({tradestate}) c shared NUMERIC_VALUE_COMMAND ({short}) c GT_OPERATOR c shared HIGH_PRICE c shared NUMERIC_VALUE_COMMAND ({Previous SAR value}) c NUMERIC_VALUED_COMMAND_WRAPPER e Switch to short # This section orresponds to the 'switch_to_short' routine in the perl # script - executed when 'long' and 'Change direction?' is true. COMMAND_SEQUENCE e "Switch to short" sequence y NUMERIC_ASSIGNMENT_COMMAND e SAR := Previous EP value shared NUMERIC_VALUE_COMMAND ({SAR}) c shared NUMERIC_VALUE_COMMAND ({Previous EP value}) c n y NUMERIC_ASSIGNMENT_COMMAND e AF := AF increment shared NUMERIC_VALUE_COMMAND ({AF}) c shared NUMERIC_VALUE_COMMAND ({AF increment}) c n y NUMERIC_ASSIGNMENT_COMMAND e EP := low shared NUMERIC_VALUE_COMMAND ({EP}) c shared LOW_PRICE c n y NUMERIC_ASSIGNMENT_COMMAND e tradestate := short shared NUMERIC_VALUE_COMMAND ({tradestate}) c shared NUMERIC_VALUE_COMMAND ({short}) c n n NUMERIC_VALUED_COMMAND_WRAPPER e Remain long # This section corresponds to the "remain long" block in the perl script. # It updates SAR and, conditionally, updates AF and EP. COMMAND_SEQUENCE e "Remain long" sequence y NUMERIC_ASSIGNMENT_COMMAND e Update SAR shared NUMERIC_VALUE_COMMAND ({SAR}) c ADDITION e SAR calculation MULTIPLICATION c SUBTRACTION c shared NUMERIC_VALUE_COMMAND ({Previous EP value}) c shared NUMERIC_VALUE_COMMAND ({Previous SAR value}) c shared NUMERIC_VALUE_COMMAND ({Previous AF value}) c shared NUMERIC_VALUE_COMMAND ({Previous SAR value}) c n y NUMERIC_CONDITIONAL_COMMAND c GT_OPERATOR e High > Previous EP? shared HIGH_PRICE c shared NUMERIC_VALUE_COMMAND ({Previous EP value}) c NUMERIC_VALUED_COMMAND_WRAPPER c COMMAND_SEQUENCE c y NUMERIC_CONDITIONAL_COMMAND e AF increment condition LT_OPERATOR e AF < Maximum AF value? shared NUMERIC_VALUE_COMMAND ({AF}) c shared NUMERIC_VALUE_COMMAND ({Maximum AF value}) c NUMERIC_ASSIGNMENT_COMMAND e Increment AF shared NUMERIC_VALUE_COMMAND ({AF}) c ADDITION e AF + AF increment shared NUMERIC_VALUE_COMMAND ({AF}) c shared NUMERIC_VALUE_COMMAND ({AF increment}) c shared NUMERIC_VALUE_COMMAND ({Null operation}) c n y shared NUMERIC_ASSIGNMENT_COMMAND (EP := high) c n n shared NUMERIC_VALUE_COMMAND ({Null operation}) c n n # Corresponds to the "short block" section of the perl script. NUMERIC_CONDITIONAL_COMMAND e Short block shared OR_OPERATOR (Change direction?) c NUMERIC_VALUED_COMMAND_WRAPPER e Switch to long # This section orresponds to the 'switch_to_long' routine in the perl # script - executed when 'short' and 'Change direction?' is true. COMMAND_SEQUENCE e "Switch to long" sequence y shared NUMERIC_ASSIGNMENT_COMMAND (SAR := Previous EP value) c n y shared NUMERIC_ASSIGNMENT_COMMAND (AF := AF increment) c n y shared NUMERIC_ASSIGNMENT_COMMAND (EP := high) c n y shared NUMERIC_ASSIGNMENT_COMMAND (tradestate := long) c n n NUMERIC_VALUED_COMMAND_WRAPPER e Remain short # This section corresponds to the "remain short" block in the perl script. # It updates SAR and, conditionally, updates AF and EP. COMMAND_SEQUENCE e "Remain short" sequence y shared NUMERIC_ASSIGNMENT_COMMAND (Update SAR) c n y NUMERIC_CONDITIONAL_COMMAND c LT_OPERATOR e Low < Previous EP? shared LOW_PRICE c shared NUMERIC_VALUE_COMMAND ({Previous EP value}) c NUMERIC_VALUED_COMMAND_WRAPPER c COMMAND_SEQUENCE c y shared NUMERIC_CONDITIONAL_COMMAND (AF increment condition) c n y shared NUMERIC_ASSIGNMENT_COMMAND (EP := low) c n n shared NUMERIC_VALUE_COMMAND ({Null operation}) c n n n y # The three assignment constructs below are executed last for each # period. They are equivalent to these lines from the perl script: # $prev_sar = $sar; # $prev_af = $af; # $prev_ep = $ep; NUMERIC_ASSIGNMENT_COMMAND e Previous SAR := SAR shared NUMERIC_VALUE_COMMAND ({Previous SAR value}) c shared NUMERIC_VALUE_COMMAND ({SAR}) c n y NUMERIC_ASSIGNMENT_COMMAND e Previous AF := AF shared NUMERIC_VALUE_COMMAND ({Previous AF value}) c shared NUMERIC_VALUE_COMMAND ({AF}) c n y NUMERIC_ASSIGNMENT_COMMAND e Previous EP := EP shared NUMERIC_VALUE_COMMAND ({Previous EP value}) c shared NUMERIC_VALUE_COMMAND ({EP}) c n y # This last sub-operator of the main command sequence is required in order # to provide the resulting value of the calculation for the period: SAR. shared NUMERIC_VALUE_COMMAND ({SAR}) c y n s - x |