|
It is very effective and simple to optimize strategy
parameters using TSGenotic. Let’s
review an example of parameters optimization
of the simplest cross strategy of
the two MA.
Text of source strategy:
inputs: Price(Close), FastLength(9), SlowLength(18), SdFast(1), SdLow(5) ;
variables: FastAvg(0), SlowAvg(0) ; FastAvg = AverageFC( Price, FastLength )[SdFast] ;
SlowAvg = AverageFC( Price, SlowLength )[SdLow] ;
if CurrentBar > 1 and FastAvg crosses over SlowAvg then
Buy ( "MA1CrossMA2" ) next bar at market ;
if CurrentBar > 1 and SlowAvg crosses over FastAvg then
SellShort ( "MA2CrossMA1" ) next bar at market ;
|
We can see 4 parameters in this strategy,
which can be optimized: FastLength(9),
SlowLength(18), SdFast(1), SdLow(5).
Let’s set the following limits of optimization for these parameters:
FastLength: from 0 to 30;
SlowLength: from 10 to 100;
SdFast: from 0 to 10;
SdLow: from 0 to 10;
Let’s prepare this strategy for optimization using TSGTEditor. Take a population
of 30 individuals and run it through
300 generations (these genetic algorithm
parameters can be a lot smaller for
such simple strategies). Generally
speaking, based on the experience
of using genetic algorithms, we recommend
using not less than 150 generations,
but on the same hand, there is not
point of setting more than 300. In
most cases, any system is able to
rich its maximum within 300 generations.
Although it is only fair if the number
of the individuals as well as other
GA parameters are set correctly.
If population size is understated intentionally, then optimization process
can stretch for a larger number of
generations and sometimes this process
might not converge one local maximum.
At the same time you should not increase
population size too much, since it
prolongs total optimization time.
For most strategies, population size of 1000 individuals can be sufficient.
So, let’s review the code obtained using TSGTEditor, which is ready for strategy
optimization. Of course, this code
can be written manually, though it
is much faster and simpler to do it
using the editor.
First section determines those parameters which will not be optimized, and
also contains an important GTSteps
parameter. This parameter is used
for starting optimization within TradeStation.
GTWork parameter is responsible for
optimizer’s mode of operation. If
GTWork equals 0, then optimization
takes place, if GTWork equals 1, then
those individuals that have already
been calculated get recalculated again.
//---------------------------------------------------------------
//inputs section
//---------------------------------------------------------------
inputs: GTsteps(1),GTWork(0);
Inputs: Price(Close);
|
In the next section, there will
be a description of genetic algorithm
parameters as well as individuals
necessary for optimizer’s functioning.
//---------------------------------------------------------------
//initialization: step1
//---------------------------------------------------------------
var:
intrabarpersist GTiter(0),
intrabarpersist GTcVarWork(0),
intrabarpersist GTres(false),
intrabarpersist GTindI(0),
intrabarpersist GTiPopul(30), //total Populaton
intrabarpersist GTiEpoch(300), //total Epochs
intrabarpersist GTiGen(4), //total Gens
intrabarpersist GTCrossover(0.98), //probability crossover
intrabarpersist GTMutation(0.15), //probability mutation
intrabarpersist GTInversion(0.05), //probability inversion
intrabarpersist GTElite(0), //Elitism strategy (on/off)
intrabarpersist GTiFitness(0), intrabarpersist GTXrom(1), //current hromosom
intrabarpersist GTEpoch(1); //current epoch
array: intrabarpersist float GTCProfit[2000000](0), intrabarpersist float GTCIdLine[2000000](0); |
Here, we can see that our parameters turned into variables. That is the way
it should be, since the parameters
are not to be set by the user but
the genetic optimizer.
var: intrabarpersist FastLength(1);
var: intrabarpersist SlowLength(10);
var: intrabarpersist SdFast(0);
var: intrabarpersist SdLow(0);
//inputs: Price(Close), FastLength(9), SlowLength(18), SdFast(1), SdLow(5) ;
variables: FastAvg(0), SlowAvg(0) ; |
Next section will execute initialization of TSGenotic optimizer. The optimizer
receives the data about all parameters,
their limits, types and steps.
//---------------------------------------------------------------
//initialization: step2
//---------------------------------------------------------------
if ((barnumber=1) and (GTsteps=1) and (GTiter=0) and (GTWork=0)) then
begin
GTres=TSGTConnect("localhost");
GTres=TSGTGenSet(1,"1;30;int;FastLength;default;");
GTres=TSGTGenSet(2,"10;100;int;SlowLength;default;");
GTres=TSGTGenSet(3,"0;10;int;SdFast;default;");
GTres=TSGTGenSet(4,"0;10;int;SdLow;default;");
GTres=TSGTiNitialize(numtostr(GTiPopul,0)+";"+ numtostr(GTiEpoch,0)+";"+ numtostr(GTiGen,0)+";"+numtostr(GTCrossover,2)+";"+ numtostr(GTMutation,2)+";"+ numtostr(GTInversion,2)+";"+ numtostr(GTElite,0)+";");
GTres=TSGTDisconnect("self");
end; |
This section is exercised at every execution on first bar on chart. The strategy
requests the optimizer for parameter
values of a current individual.
//---------------------------------------------------------------
//initialization: step current
//---------------------------------------------------------------
if ((barnumber=1) and (GTsteps>=1) and (GTiter=0)) then
begin
GTres=TSGTConnect("localhost");
GTcVarWork=0;
GTcVarWork=TSGTVarwork(GTstepsáGTWork);
FastLength=TSGTGenGet(GTcVarWork,1);
SlowLength=TSGTGenGet(GTcVarWork,2);
SdFast=TSGTGenGet(GTcVarWork,3);
SdLow=TSGTGenGet(GTcVarWork,4);
GTres=TSGTDisconnect("self");
end; |
Then goes source strategy calculation.
| if GTcVarWork<>0 then begin //---------------------------------------------------------------
//source strategy
//---------------------------------------------------------------
FastAvg = AverageFC( Price, FastLength )[SdFast] ;
SlowAvg = AverageFC( Price, SlowLength )[SdLow] ;
if CurrentBar > 1 and FastAvg crosses over SlowAvg then
Buy ( "MA1CrossMA2" ) next bar at market ;
if CurrentBar > 1 and SlowAvg crosses over FastAvg then
SellShort ( "MA2CrossMA1" ) next bar at market ;
//---------------------------------------------------------------
//end of source strategy
//--------------------------------------------------------------- |
Final section. Fitness, profit and drawdown calculation of the strategy as
well as transfer of those values to
TSGenotic optimizer will take place
here.
In this case, fitness calculation is exercised based on coefficient of correlation
of yield curve.
//---------------------------------------------------------------
//final section
//---------------------------------------------------------------
end;
GTiter=GTiter+1; GTCProfit[barnumber]=NetProfit;
if ((lastbaronchart) and (GTsteps>=1)) then
begin
for GTindI=1 to barnumber begin GTCIdLine[GTIndI]= ((GTCProfit[barnumber]-GTCProfit[1])/barnumber)*GTindI+ GTCProfit[1]; end;
GTiFitness=round(10000* CoefficientRArray(GTCProfit,GTCIdLine,BarNumber)*((GTCProfit[barnumber]- GTCProfit[1])/barnumber),0);
//send result of strategy
GTres=TSGTConnect("localhost");
if GTcVarWork<>0 then begin
GTres=TSGTFitness(GTcVarWork,numtostr(GTiFitness,4)+";");
GTres=TSGTProfit(GTcVarWork,numtostr(NetProfit,4)+";");
GTres=TSGTDrodown(GTcVarWork,numtostr(MaxIDDrawDown,4)+";");
end;
GTres=TSGTNextStep(GTcVarWork);
GTres=TSGTDisconnect("self");
end; |
As is clear from the example, strategy structure for TSGenotic is rather
simple. Although, we recommend using
TSGTEditor for strategy preparation.
When the strategy is ready for optimization, you should complete
following steps:
Start TradeStation.
Open the chart and the period you are interested in. For example, GBP/USD
timeframe 5 minutes for 2 months.
Add prepared strategy on chart.
Set the MaxBarsBack parameter. (in this particular example, it should equal
150, in general, it is set up as maximum
possible that might be required during
optimization process, i.e. what maximum
MaxBarsBack is required at any strategy
parameters combination).
Further you should set GTsteps strategy parameter optimization from 1 to
a number equal a product of number
of individuals by number of generations.
In this example, it is up to 9000.
GTWork should equal 0.
Press “Ok”. Ignore possible message about incorrect MaxBarsBack settings.
Press “Yes”.
The strategy in TS is ready for optimization.
Start TSGenotic.
There should not be any data in a table at this moment, except cases of continuation
of optimization.
Press “Optimize” button in TradeStation.
There starts optimization process. As the calculation goes on, executed individuals
will get filled with fitness, profit
and drawdown values in the optimizer’s
table.
In TSGenotic, you can see current results, sorted based on profit by pressing
“Sorted results”.
Optimization process can be aborted at any moment by pressing “Abort” in
TS or you can simply wait till the
optimization process is complete.
By setting GTSteps parameter as a number
of the individual you are interested
in from the first column and GTWork
parameter to be 1, you will get the
work results for the strategy with the
parameters, written on the line of the
individual you are interested in.
This is how the results look like after 10 generations.
As seen from the table, we could see good results at 180th step on the first
line. We completed optimization, but
the results have not improved. This
is a normal occurrence. Since genetic
algorithms are not based on direct
enumeration, but the search of the
maximum of some generalized parameters
surface, best variants will appear
at early stages of optimization. Although
we recommend to always complete the
optimization.
In order to realize that optimization
has come to its logical end, you should
analyze several latest executed populations.
If all individuals have similar results
and these results do not improve from
one generation to another, it means
that the optimization process can
be considered complete.
I would like to remind you that we strongly recommend executing at least
300 generations before evaluating
your results.
This is an equity curve chart of the test strategy that was optimized using
TSGenotic. Optimization criterion
(fitness) is a coefficient of correlation
of yield curve.
Summing it all up, you can notice that instead of direct enumerating of 270000
variants, we have executed only 9000,
that took us less than an hour. And
despite the fact that we got good
results on 180th step, optimization
was still completed.
|