[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();
}