Walk-forward optimization library for MetaTrader: User Guide

15 August 2016, 19:42
Stanislav Korotky

This post is a part of documentation of WalkForwardOptimizer library for MetaTrader4/5 - here is the table of contents.

Rolling walk-forward optimization

Once you included WFO library into EA (the header is attached below), approach is as follows. Setup optimization for an entire desired period (say, 2001-2015 on D1 timeframe). Next choose optimization window size and walk-forward step size as meta-parameters wfo_windowSize and wfo_stepSize provided by the library. Both can be selected from a predefined list (year, half-of-year, quarter, month, week, day), but step size should be a lesser period than the window. For example, we can choose yearly window and quarterly step. Next you should specify for the tester how many forward steps you want to perform via wfo_stepOffset - this is one more meta-parameter, and it's most interesting because it must be included into optimization. You should always use 1 as increment for wfo_stepOffset optimization, because it ensures seamless intergation of all forward steps into consolidated forward test. All meta-parameters come from the library header.

Because of the tester limitation MQL can not detect ending point of optimization beforehand, this is why user should calculate himself how many steps fit into entire region. The period 2001-2015 comprises 1 complete year (window), and the rest is covered by forward steps, which gives (15 - 1) years multiplied by 4 quarters = 14*4 = 56. So user should enable optimization of the wfo_stepOffset meta-parameter in the region 0 - 56 with step 1. Strictly speaking, if you set final value to 56, it will be 1-st quarter of 2016. This happens because in this WFO implementation the forward test is taken outside optimization window. In our example, since the 1-st quarter of 2016 is there, we can neglect the "overflow". But this may become important if you run WFO up to the latest known date. In this case user should take care to not specify more steps than available. Again, this nuance exists due to the fact that MetaTrader tester does not allow us to know ending testing date from the expert being tested.

The setup described above is known as rolling walk-forward testing. The library does also support cluster analysis and anchored modes, which are covered below.


Common instructions 

Before you start optimization, open first tab on the expert properties dialog of the tester and set Optimized parameter to Custom. Actual meaning of the custom parameter should be selected by means of the special meta-parameter of the library - wfo_estimation - on the second tab with inputs. Also make sure to utilize Use date flag and From / To fields on the tester's Settings tab as appropriate.

While using MetaTrader 4, on the tab with Optimization results (unfortunately, the tab is only accessible if optimization has been started at least once) find the option Skip useless results in the context menu and disable it - this is required. While using MetaTrader 5, make sure Forward dropdown option is selected as No (the built-in forward testing provided by MetaTrader 5 can not be integrated with the library).

As usual, user should enable optimization for those EA parameters that require optimization. If the number of parameters is large, one may enable genetic algorithm, but this has some drawbacks described below.

When all is prepared, start optimization and wait. As a result, you'll finally get a csv-file with all performance estimators for every run (profit, profit factor, number of trades, and other values including a custom OnTester value, all of them for optimized and forward periods in the same row). Also you'll get a list of global variables showing best cases (indices of runs with winning parameter sets) for every of 56 forward runs (actually there will be 57, if you specify 0 as the start index and 56 as the last).

In case of MetaTrader 4 user should move the resulting csv-file from the tester/Files folder to MQL4/Files folder. In case of MetaTrader 5 this is done automatically, that is the file is generated in MQL5/Files folder.

The type of the main estimator (which is used during optimization and indicates if EA performs good or bad) is selected by means of another special input meta-parameter wfo_estimation provided by WFO library. You can choose from profit amount, profit factor, sharpe ratio, drawdown percent(inversed, calculated on balance curve), or custom expression combining all these values (see formula reference for details). Also 2 universal built-in estimators (loose and strict) are provided: their formulae comprise sharpe, profit factor, profit amount and number of trades. The difference between loose and strict variant is that the former takes all orders into account, while the later excludes those with profit larger than mean single profit plus three sigma. In other words, the strict method removes lucky outliers from balance before calculation of the estimator.

At this point, you can analyze the results by running a special WFR script, which parses the csv-file and global variables, and builds html-page with a summary.

NB: Forward test is calculated as continuation of corresponding optimization run, with parameters optimized only on in-sample data. In other words, EA continues trading outside optimization window during next forward step period, with current balance (not initial deposit), and performance estimators are calculated by the library separately for the optimization and test parts. Optimization part values are returned back to the tester via OnTester handler. After the optimization is finished, we have performance values for all optimization windows (with all the different parameter sets) and all corresponding forward steps. Using these values the tester selects a best set as usual (for every window), and we know at once the result of the corresponding forward step.

This is done because otherwise, if EA would perform optimization and forward test in separate runs, it's impossible to identify and tie up these 2 runs with each other due to MQL API limitations in the standard MateTrader4 tester. Due to this nuance it's strictly recommended to use a constant lot during optimization.

Genetic algorithm

You may enable genetic algorithm if you want, but it have some drawbacks.

In MetaTrader 4 it requires you to clean up WF global variables before every optimization - either manually or using the reporter script. If genetics are not used, you can call wfo_setGVAutomaticCleanup(true) from your code, and the library will clean up its global variables for you before every optimization. Unfortunately, MQL API does not provide means to check if genetics are enabled, this is why it's impossible to switch wfo_setGVAutomaticCleanup automatically. Do it as appropriate in your code. Starting from version 1.2 one may use wfo_setCleanUpTimeout function. In MetaTrader 5 all WF global variables are cleared automatically before every optimization, so there is no hassle.

Also, please, note that genetic algorithm skips many combinations of input parameters, including specific pairs of (window size;step size) and rolling steps, so some forward tests can be unavailable. Another drawback of genetic algorithm is in its "fast search", which is sub-optimal and thus giving lower values on in-sample data than straight-forward optimization - as a result, walk-forward effectiveness can seem overoptimistic (in other words, a single genetic optimization pass on in-sample data without WF library outperforms specific walk-forward genetic optimization run on the same window, but out-of-sample profit remain on average the same, because found parameters are always sub-optimal in changing future). While using straight-forward optimization there is no such problem.

You may use "control points" method - it seems fast and adequate enough for long running strategies. This is a good compromise between "open prices" and "every tick" modes. "Open prices" is only applicable for robots developed specifically for trading at bar opening, whereas "every tick" mode may be too slow with walk-forward optimization. Bear in mind, that walk-forward optimization is actually implemented through additional optimization meta-parameters:  wfo_stepOffset,  wfo_customWindowSizeDays,  wfo_customStepSizePercent, which can produce a multitude of additional tester passes.


Clustered walk-forward optimization

As an extended case of WFO, a so-called cluster analysis may also be used.

It's supported via 2 more meta-parameters of the library - wfo_customWindowSizeDays and wfo_customStepSizePercent, which allows you to check forward stability while changing optimization window size and forward step size. wfo_customStepSizePercent is specified in percents of window size. This mode is intended for finding out if suitable EA setups exist for different meta-parameters, and deciding which window and step size to choose. 

A sidenote

Changing optimization window and step size can support but not necessarily prove robustness of EA. Our task is to confirm that performance is not degrading much, and not to find super-optimized meta-parameters of WFO itself, because such meta-parameters would be a subject of meta-optimization and meta-forward testing on a next meta-level, which forms an endless loop of meta-metas and hence goes out of consideration. Without this, finding optimal optimization window size and forward step is similar to overfitting (cheeting) on a meta-level, where selected part of history for WFO becomes in-sample meta-data and out-of-sample meta-test is missing. Moreover, instead of changing window size (and hence changing number of runs) it is also applicable to increase number of runs at the expense of taking a deeper history into account.

Anchored walk-forward optimization

WFO provides an additional optimization mode where starting position of optimization window remains intact, but window size increases in increments equal to forward step. This is a so called anchored walk-forward. For this mode forward step size must be specified as a value from the predefined list of common periods (not in percents), and window size should be optimized through wfo_customWindowSizeDays meta-parameter with a step equal to selected period length in days. This is so because otherwise, relative length of steps would vary on every forward pass and overlap with neighboring passes. For example, one can choose to optimize wfo_customWindowSizeDays from 60 to 150 with the step 30, and then select month constant as wfo_stepSize value (it's equal to 30, so every time the window will grow by 30 days, it will additionally swallow exactly forward test from previous pass, and all forward tests will seamlessly form a flow one after another). If you start optimization at the beginning of 2016, such anchored optimization will produce forward tests for March (optimized on January and February), April (optimized on January, February and March), May (optimized on January, February, March, and April), and finally test for June (optimized on January, February, March, April, and May).

You may find details in How To section of the documentation.

Share it with friends: