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

RE: [GT] alias resolution ... sub resolve_alias revisited



Robert,

This is a good idea, except that you break backtest if you use
  while ($sysname !~ /\|/) {

Here is the reason: You could use as a simple alias name to stand for a
"full system name". In that case, there will be no vertical bars in the
full system name and the expansion will fail. It is better to
specifically look for the absence of any of the components in a full
system name.

Cheers, Th.



> -----Original Message-----
> From: Robert A. Schmied [mailto:ras
AT
acm.org]
> Sent: Thursday, May 01, 2008 1:26 AM
> To: devel
AT
geniustrader.org
> Subject: [GT] alias resolution ... sub resolve_alias revisited
> 
> aloha gt'ers
> 
> i've hacked up a replacement resolve_alias subroutine for evaluation.
> the entire sub is provided so you can hack it in for eval by renaming
> the current version something else.
> 
> what does it do you're thinking. well, it gives you a helpful error
> message
> when it doesn't find the alias, or it gives you complete feedback if
> any parameter is missing.
> 
> examples are better than my ramblings:
> 
> with these aliases in your .gt/options file:
> aliases::global::mysma[]            	SY:SMA | TF:AcceptAll |
> CS:Stop:Fixed #1
> aliases::global::tfs[]              	SY:TFS #1 #2 | CS:SY:TFS #1 |
> CS:Stop:Fixed #3
> aliases::global::tts                	TTS
> aliases::global::tts[]              	SY:TTS #1 #2 |
> CS:Stop:ExtremePrices #2 #3 | TF:OneTrade
> aliases::global::ttsx               	TTS[20,10,1]
> aliases::global::rw_sys4[]          	SY:Generic S:Generic:And {
> S:Generic:Above { I:Generic:Eval int( { I:Generic:PeriodAgo 1 {
> I:Prices VOLUME } } * #1 ) } { I:Generic:Eval int( {
> I:Generic:PeriodAgo 2 { I:Prices VOLUME } } * #2 ) } } {
> S:Generic:Above { I:Generic:Eval int( { I:Generic:PeriodAgo 1 {
> I:Prices CLOSE } } * #3 ) } { I:Generic:Eval int( {
I:Generic:PeriodAgo
> 2 { I:Prices CLOSE } } * #4 ) } } | OF:ClosedToClose | TF:LongOnly |
> CS:Stop::KeepRunUp | MM:FixedShares
> 
> if you do %    backtest.pl 'rw_sys4[20,30]' GOOG
> backtest.pl: error: alias 'rw_sys4[20,30]' is missing parameters #3
#4.
> The alias expands to
> "SY:Generic S:Generic:And { S:Generic:Above { I:Generic:Eval int( {
> I:Generic:PeriodAgo 1 { I:Prices VOLUME } } * 20 ) } { I:Generic:Eval
> int( { I:Generic:PeriodAgo 2 { I:Prices VOLUME } } * 30 ) } } {
> S:Generic:Above { I:Generic:Eval int( { I:Generic:PeriodAgo 1 {
> I:Prices CLOSE } } * #3 ) } { I:Generic:Eval int( {
I:Generic:PeriodAgo
> 2 { I:Prices CLOSE } } * #4 ) } }
> |  OF:ClosedToClose
> |  TF:LongOnly
> |  CS:Stop::KeepRunUp
> |  MM:FixedShares"
> 
> or if you try %    backtest.pl mysma GOOG
> backtest.pl: error: alias key "Aliases::Global::mysma" was not found.
> However, `mysma[]' was. It expects 1 parameter, try 'mysma[#1]'
> That alias expands to
> "SY:SMA
> |  TF:AcceptAll
> |  CS:Stop:Fixed #1"
> 
> an alias without params like ttsx now works as 'ttsx[]'
> %     backtest.pl 'ttsx[]' GOOG
> ## Analysis of SY:TTS
> ...
> 
> but if you throw in a param it fails, but helpfully: %     backtest.pl
> 'ttsx[45]' GOOG
> backtest.pl: error: alias key "Aliases::Global::ttsx" was not found.
> ah ha! Alias `ttsx[45]' doesn't expect any parameters, try 'ttsx'
> That alias expands to
> "TTS[20,10,1]"
> 
> and if you really mis-tpye things  %    backtest.pl myema  GOOG
> backtest.pl: error: alias key "Aliases::Global::myema" was not found.
> just like before, but you will not be staring at your list of aliases
> and seeing Aliases::Global::myema[] but not knowing why it's not being
> found.
> 
> 
> even with these improvements it still fails if you have defined
> recursive
> aliases like tts and tts[] in the examples list above.
> %      backtest.pl tts  GOOG
> Deep recursion on subroutine "GT::Tools::resolve_alias" at
> ../GT/Tools.pm line 252.
> 
> i haven't found a solution for that yet.
> 
> oh yea! almost forgot. extra whitespace in the param list will not
> cause
> problems. so things like 'mysma[   20  ]', 'tts[ 30   ,   40, 50   ]'
> work now.
> 
> finally i've not incorporated the alternate while ($sysname !~ /\|/)
> regex
> as i've yet to find a condition where it helps. of course the amount
of
> testing
> i've conducted is very limited and certainly simplistic. however, i'd
> argue that
> gt identifiers (e.g. indicator, signal and system component
> specifications) are
> case sensitive and have been so forever, so the pattern /i modifier is
> likely
> incorrect.
> 
> 
> feedback is welcome
> 
> ras
> 
> replacement subroutine -- rename existing one and drop in this one
> oh yea! filename might be extremely helpful: GT/Tools.pm
> sub resolve_alias {
>     my ($alias) = @_;
>     my $name = $alias;
>     my @param = ();
>     my $sysname = '';
>     my $msg = '';
> 
>     if ($alias =~ m/^\s*(.*)\s*\[(.*)\]\s*$/) {
>         $name = $1;
>         ( $_ = $2 ) =~ tr/[ \t]//d;
>         @param = split /,/;
>     }
> 
>     # remove "Aliases::Global::" in any case, just in case
>     $name =~ s/aliases:+global:+//ig;
> 
>     if (scalar @param) {
>         if ( $sysname = GT::Conf::get("Aliases::Global::$name" . "[]")
> ) {
>             # $sysname is valid
>         } else {
> 
>             $msg = "alias key \"Aliases::Global::$name\""
>              . " was not found.\n";
> 
>            if ( $sysname = GT::Conf::get("Aliases::Global::$name") ) {
>                $msg .= "ah ha! Alias `$alias' doesn't expect any
> parameters, "
>                 . "try '$name'\n";
>                $sysname =~ s
AT
\|@\n| @g;
>                $msg .=  "That alias expands to\n\"$sysname\"\n";
>            }
>         ( my $prog_name = $0 ) =~ s
AT
^.*/@@;    # lets identify ourself
>         die "$prog_name: error: " . "$msg";
>         }
> 
>     } else {
>         if ( $sysname = GT::Conf::get("Aliases::Global::$name") ) {
>             # $sysname is valid
>         } else {
> 
>             $msg = "alias key \"Aliases::Global::$name\""
>              . " was not found.\n";
> 
>             if ( $sysname = GT::Conf::get("Aliases::Global::$name" .
> "[]") ) {
>                 my @param = $sysname =~ m/#(\d+)/g;
> 
>                 my $param_count = 0;
>                 foreach ( @param ) {
>                     $param_count = max( $_, $param_count );
>                 }
> 
>                 my $plural = "";
>                 $plural = "s" if ( $param_count > 1 );
>                 $alias =~ s/\[\]//;
>                 $msg .= "However, `$alias\[\]' was. "
>                  . "It expects $param_count parameter$plural,";
>                 if ( $param_count == 1 ) {
>                     $msg .= " try '$name" . "[#1]'\n";
>                 } elsif ( $param_count == 2 ) {
>                     $msg .= " try '$name" . "[#1, #2]'\n";
>                 } elsif ( $param_count == 3 ) {
>                     $msg .= " try '$name" . "[#1, #2, #3]'\n";
>                 } else {
>                     $msg .= " try '$name" . "[#1, #2, ..
> #$param_count]'\n";
>                 }
>                 $sysname =~ s
AT
\|@\n| @g;
>                 $msg .= "That alias expands to\n\"$sysname\"\n";
>               }
>          ( my $prog_name = $0 ) =~ s
AT
^.*/@@;    # lets identify
ourself
>          die "$prog_name: error: " . "$msg";
>          }
> 
>     }
> 
>     # The alias content may list another alias ...
>     while ($sysname !~ /\|/) {
>     #while ($sysname !~
> /^(I|Indicators|S|Signals|SY|Systems|CS|CloseStrategy|
>     #
> MM|MoneyManagement|TF|TradeFilters|OF|OrderFactory|
>     #                    A|Analyzers|PE|PortfolioEvaluation)/i) {
>     #while ($sysname !~ /^(I|SY|S|CS|MM|TF|OF|A|PE)|
>     #                   ^(Indicators|Signals|Systems|CloseStrategy|
>     #
> MoneyManagement|TradeFilters|OrderFactory|Analyzers|
>     #                   PortfolioEvaluation)/i) {
>         $sysname = resolve_alias($sysname);
>     }
>     my $n = 1;
>     foreach (@param)
>     {
>         $sysname =~ s/#$n/$_/g;
>         $n++;
>     }
> 
>     # Take care about operators + - / * in a string like #1+#2
>     eval {
>         $sysname =~ s|(\d+)\*(\d+)| $1 * $2 |eg;
>         $sysname =~ s|(\d+)\/(\d+)| $1 / $2 |eg;
>         $sysname =~ s|(\d+)\+(\d+)| $1 + $2 |eg;
>         $sysname =~ s|(\d+)\-(\d+)| $1 - $2 |eg;
>     };
> 
> #    if ($sysname =~ /#(\d+)/)
>     if ( my @missing_params = $sysname =~ /(#\d+)/g )
>     {
>         my $msg = '';
>         if ( $#missing_params == 0 ) {
>             $msg = "alias '$alias' is missing parameter
> @missing_params.\n";
>         } else {
>             $msg = "alias '$alias' is missing parameters
> @missing_params.\n";
>         }
>         $sysname =~ s
AT
\|@\n| @g;
>         $msg .= "The alias expands to\n\"$sysname\"\n";
>         ( my $prog_name = $0 ) =~ s
AT
^.*/@@;    # lets identify ourself
>         die "$prog_name: error: " . "$msg";
>     }
>     return $sysname;
> }