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

[GT] SVN Commit r615 - trunk/Scripts



Author: thomas
Date: 2008-04-21 01:18:25 +0200 (Mon, 21 Apr 2008)
New Revision: 615

Modified:
   trunk/Scripts/backtest_multi.pl
Log:
Make input consistent with other scripts, in particular backtest_many.pl

Modified: trunk/Scripts/backtest_multi.pl
===================================================================
--- trunk/Scripts/backtest_multi.pl	2008-04-20 23:17:23 UTC (rev 614)
+++ trunk/Scripts/backtest_multi.pl	2008-04-20 23:18:25 UTC (rev 615)
@@ -4,17 +4,10 @@
 # This file is distributed under the terms of the General Public License
 # version 2 or (at your option) any later version.
 
-use lib '/bourse/perl';
 use lib '..';
-use lib '../..';
 
-#use lib '/tmp';
-
 use strict;
 
-use XML::Simple;
-#use Data::Dumper;
-
 use GT::Prices;
 use GT::Portfolio;
 use GT::PortfolioManager;
@@ -22,32 +15,162 @@
 use GT::Report;
 use GT::BackTest;
 use GT::BackTest::Spool;
+use GT::List;
 use GT::Eval;
-use Getopt::Long;
 use GT::Conf;
 use GT::DateTime;
 use GT::Tools qw(:conf :timeframe);
 use Pod::Usage;
+use Getopt::Long;
+use Pod::Usage;
 
 GT::Conf::load();
 
+=head1 ./backtest_multi.pl [ options ] <market file> <system file>
 
+=head2 Description
+
+Backtest_many will test all system listed in a system
+file on all the values listed in the market file.
+
+The <system file> contains one line per defined system, where each
+system is defined by its full system name or by an alias. An alias is 
+defined in the configuration file with entries of the form 
+ Aliases::Global::<alias_name> <full_system_name>.
+
+The full system name consists of a set of properties, such as trade 
+filters, close strategy, etc., together with their parameters, 
+separated by vertical bars ("|"). Multiple properties of the same 
+type can be defined, e.g., there could be a set of close strategies.
+For example,
+  System:ADX 30 | TradeFilters:Trend 2 5 | MoneyManagement:Normal 
+defines a system based on the "ADX" system, using a trend following trade
+filter "Trend", and the "Normal" money management.
+
+The following abbreviations are supported:
+Systems = SY
+CloseStrategy = CS
+TradeFilters = TF
+MoneyManagement = MM
+OrderFactory = OF
+Signals = S
+Indicators = I
+Generic = G
+
+Another example of a full system name is 
+  SY:TFS|CS:SY:TFS|CS:Stop:Fixed 4|MM:VAR.
+
+=head2 Options
+
+=over 4
+
+=item --full, --start=<date>, --end=<date>, --nb-item=<nr>
+
+Determines the time interval to consider for analysis. In detail:
+
+=over
+
+=item --start=2001-1-10, --end=2002-11-17
+
+The start and end dates considered for analysis. The date needs to be in the
+format configured in ~/.gt/options and must match the timeframe selected. 
+
+=item --nb-items=100
+
+The number of periods to use in the analysis.
+
+=item --full
+
+Consider all available periods.
+
+=back
+
+The periods considered are relative to the selected time frame (i.e., if timeframe
+is "day", these indicate a date; if timeframe is "week", these indicate a week;
+etc.). In GT format, use "YYYY-MM-DD" or "YYYY-MM-DD hh:mm:ss" for days (the
+latter giving intraday data), "YYYY-WW" for weeks, "YYYY/MM" for months, and 
+"YYYY" for years.
+
+The interval of periods examined is determined as follows:
+
+=over
+
+=item 1 if present, use --start and --end (otherwise default to last price)
+
+=item 1 use --nb-item (from first or last, whichever has been determined), 
+if present
+
+=item 1 if --full is present, use first or last price, whichever has not yet been determined
+
+=item 1 otherwise, consider a two year interval.
+
+=back
+
+The first period determined following this procedure is chosen. If additional
+options are given, these are ignored (e.g., if --start, --end, --full are given,
+--full is ignored).
+
+=item --timeframe=1min|5min|10min|15min|30min|hour|3hour|day|week|month|year
+
+The timeframe can be any of the available modules in GT/DateTime.  
+
+=item --max-loaded-items
+
+Determines the number of periods (back from the last period) that are loaded
+for a given market from the data base. Care should be taken to ensure that
+these are consistent with the performed analysis. If not enough data is
+loaded to satisfy dependencies, for example, correct results cannot be obtained.
+This option is effective only for certain data base modules and ignored otherwise.
+
+=item --broker="NoCosts"
+
+Calculate commissions and annual account charge, if applicable, using
+GT::Brokers::<broker_name> as broker.
+
+=item --set=SETNAME
+
+Stores the backtest results in the "backtests" directory (refer to your options file for the location of this directory) using the set name SETNAME. Use the --set option of analyze_backtest.pl to differentiate between the different backtest results in your directory.
+
+=item --options=<key>=<value>
+
+A configuration option (typically given in the options file) in the
+form of a key=value pair. For example,
+ --option=DB::Text::format=0
+sets the format used to parse markets via the DB::Text module to 0.
+
+=back
+
+=head2 Examples
+
+=over 4
+
+=item
+./backtest_many.pl ../Listes/fr/CAC40 ../BackTest/HCB.txt --output-dir=../BackTest/ --set=HCB --full
+
+=back
+
+=head2 Example of system description
+
+SY:TFS 50 7|CS:SY:TFS 50|CS:Stop:Fixed 6|MM:VAR 10 2|MM:PositionSizeLimit 100
+
+=cut
+
 # Gestion des options
 my ($full, $nb_item, $start, $end, $timeframe, $max_loaded_items) =
    (0, 0, '', '', 'day', -1);
 my $man = 0;
 my @options;
-my ($outputdir, $set) = 
-   ('', '');
+my ($outputdir, $broker, $set, $init) = 
+   ('', '', '', 10000);
 $outputdir = GT::Conf::get("BackTest::Directory") || '';
 GetOptions('full!' => \$full, 'nb-item=i' => \$nb_item, 
 	   "start=s" => \$start, "end=s" => \$end, 
 	   "max-loaded-items" => \$max_loaded_items,
 	   "timeframe=s" => \$timeframe,
-	  'output-directory=s' => \$outputdir, 'set=s' => \$set,
+	   'output-directory=s' => \$outputdir, 'init=s' => \$init,
+	   'broker=s' => \$broker, 'set=s' => \$set,
 	   "option=s" => \
AT
options, "help!" => \$man);
 $timeframe = GT::DateTime::name_to_timeframe($timeframe);
-my $init = 10000;
 
 foreach (@options) {
     my ($key, $value) = split (/=/, $_);
@@ -59,92 +182,68 @@
 # Checks
 if (! -d $outputdir)
 {
-    die "The directory '$outputdir' doesn't exist !\n";
+  die "The directory $outputdir does not exist!\n";
 }
 
-# read the system-description
-my $filename = shift;
-my $xs = new XML::Simple( ForceArray => 1,
-			  KeyAttr => ['value'] );
-my $data = $xs->XMLin( $filename );
-#use Data::Dumper;
-#print Dumper($data);
+# Create all the framework
+my $list = GT::List->new;
+my $file = shift;
+if (! -e $file)
+{
+    die "File $file does not exist.\n";
+}
+$list->load($file);
 
 # Create the Portfoliomanager
 my $pf_manager = GT::PortfolioManager->new;
 
-# Set up the various system managers
-my @sys_manager = ();
+# Build the list of systems to test
+my @desc_systems = <>;
+my @sys_manager = {};
 my @brokers = ();
 my $cnt = 0;
-foreach my $sm ( @{$data->{'system-manager'}} ) {
 
-  # New manager
-  $sys_manager[$cnt] = GT::SystemManager->new;
+push @brokers, $broker; # the same broker for all systems
+foreach my $line (@desc_systems) {
+    chomp($line);
+    
+    my $sys_manager = GT::SystemManager->new;
 
-  # Set the system
-  my @systems = keys %{$sm->{'system'}};
-  my $system = $systems[0];
-  if ( $system =~/^\^/ ) {
-    $sys_manager[$cnt]->set_system(create_standard_object(split (/\s+/, "$system")));
-  } else {
-    $sys_manager[$cnt]->set_system(create_standard_object(split (/\s+/, "Systems::$system")));
-  }
+    # Aliases
+    if ($line !~ /\|/)
+    {
+	my $alias = resolve_alias($line);
+	die "Alias unknown '$alias'" if (! $alias);
+	$sys_manager->set_alias_name($line);
+	$line = $alias;
+    }
 
-  # Add the Orderfactory
-  my @ofs = keys %{$sm->{'of'}};
-  my $ofname = $ofs[0];
-  if ($ofname) {
-    $sys_manager[$cnt]->set_order_factory(create_standard_object(split (/\s+/, "OrderFactory::$ofname")));
-  }
+    $pf_manager->setup_from_name($line);
+    $sys_manager->setup_from_name($line);
+    $sys_manager->finalize;
 
-  # Add the Tradefilter
-  my @tfname = keys %{$sm->{'tf'}};
-  foreach (@tfname) {
-    $sys_manager[$cnt]->add_trade_filter(create_standard_object(split (/\s+/, "TradeFilters::$_")));
-  }
+    $sys_manager[$cnt] = $sys_manager;
 
-  # Add the Tradefilter
-  my @csname = keys %{$sm->{'cs'}};
-  foreach (@csname) {
-    $sys_manager[$cnt]->add_position_manager(create_standard_object(split (/\s+/, "CloseStrategy::$_")));
-  }
-
-  # Setting the broker
-  my @tbrokers = keys %{$sm->{'broker'}};
-  my $broker = $tbrokers[0];
-  if ( $broker ) {
-    push @brokers, $broker;
-  } else {
-    push @brokers, '';
-  }
-
-  $sys_manager[$cnt]->finalize;
-  $cnt++;
+    $cnt++;
 }
 
-$init = (keys %{$data->{'init'}})[0];
+my $def_rule = create_standard_object("MoneyManagement::Basic");
+$pf_manager->default_money_management_rule($def_rule);
 
-# Set the Money Management
-my @mmname = keys %{$data->{'mm'}};
-push @mmname, "Basic" if ($#mmname < 0);
-foreach (sort {$data->{'mm'}->{$a}->{sort} <=> $data->{'mm'}->{$b}->{sort}} @mmname) {
-  #print STDERR "Adding MM: $_\n";
-  $pf_manager->add_money_management_rule(create_standard_object(split (/\s+/, "MoneyManagement::$_")));
-}
-
-$pf_manager->default_money_management_rule(
-	create_standard_object("MoneyManagement::Basic"));
 $pf_manager->finalize;
 
-my @codes = keys %{$data->{'code'}};
+my @codes;
+for (my $d = 0; $d < $list->count; $d++)
+{
+  push @codes, $list->get($d);
+}
 
 # Now the hard part...
 my $analysis = backtest_multi($pf_manager, \
AT
sys_manager, \
AT
brokers, \
AT
codes, $timeframe, $full, $start, $end, $nb_item, $max_loaded_items, $init);
 
 # Print the analysis
 GT::Report::Portfolio($analysis->{'portfolio'}, 1);
-print "## Global analysis (each position is 10keuros, value of portfolio)\n";
+print "## Global analysis (each position is $init, value of portfolio)\n";
 GT::Report::PortfolioAnalysis($analysis->{'real'}, 1);
 #print "\n## Theoretical analysis (10keuros, full portfolio reinvested)\n";
 #GT::Report::PortfolioAnalysis($analysis->{'theoretical'}, $verbose);
@@ -161,11 +260,11 @@
 
     delete $analysis->{'portfolio'}->{objects};
 
-    print STDERR $set . " --> " . $filename . "\n";
+    print STDERR $set . " --> " . $file . "\n";
 
     $bkt_spool->update_index();
-    $bkt_spool->add_alias_name($set."-".$filename, $set);
-    $bkt_spool->add_results($set."-".$filename, "MULTI", $stats,
+    $bkt_spool->add_alias_name($set."-".$file, $set);
+    $bkt_spool->add_results($set."-".$file, "MULTI", $stats,
 			    $analysis->{'portfolio'}, $set);
     $bkt_spool->sync();
 }