Adaptrade Software Newsletter Article
When developing a trading strategy, our own biases and preconceived notions of how the markets trade (or how we think they should trade) often interfere with the process of finding a good strategy. Using a trading strategy generator, such as Adaptrade Builder is a good way to avoid introducing unhelpful biases into the build process. However, what if you already have a trading idea or an existing trading strategy you want to develop further? Is there a way to exploit the features of Adaptrade Builder when starting with an existing trading strategy?
A new feature of Builder, called strategy cloning, is intended for this scenario. This article discusses some of the use cases for strategy cloning and demonstrates how to use this new feature to effectively develop strategies based on an existing strategy or trading idea. The project files used for the example, as well as the strategy code, are available below.
How Does Strategy Cloning Work?
The basic idea of strategy cloning is simple. It copies the selected strategy and optionally introduces random changes to the copies, which are added to the main population. The menu item for the strategy cloning feature, which is available via the right-click (context) menu of the Build Results table, is shown below in Fig. 1. Any member of the main population can be selected; if you want to clone a member of the Top Strategies population, you can first copy it to the main population.
Figure 1. The strategy cloning function is available via the right-click (context) menu in the Build Results table of Adaptrade Builder.
Selecting the Clone Strategy command brings up the Clone Settings window, as shown below in Fig. 2. You can specify the number of copies you want to add to the population, whether the copies are exact or mutated, the degree of mutation (parameter values only or mutating both parameter values and strategy logic), and how the copies are added to the population. Copies can be added to the end of the population or they can replace existing members. To replace existing members, you can select whether the least-fit members are replaced or negative tournament selection is used to replace members. The latter means that a random number of members is selected, and the least-fit one is replaced. If negative tournament selection is used, the tournament size is taken from the setting on the GP Settings window.
Figure 2. Selecting the Clone Strategy command brings up the Clone Settings window, which contains the options for cloning the selected strategy. The resulting copies are added to the main population.
Once the cloned strategies have been added to the population, the build process can be started from the new population. To make sure the population is not re-initialized, the "Reset on Build" option on the GP Settings window (Build menu) needs to be deselected or the population will be replaced with randomly generated strategies prior to the first generation. Also, the population size entry on GP Settings should be set to the number of strategies in the main population.
Applications of Strategy Cloning
There are a number of different ways the strategy cloning feature can be used within Adaptrade Builder, including the following:
- Start with a trading idea and use the built-in editor of Builder to implement the basic idea with the goal of exploring its viability on one or more markets.
- Identify a promising trading strategy from an existing population in Builder with the goal of improving it for the same market for which it was originally designed.
- Start with a trading strategy that's been proven on one market with the goal of applying it to a different market or markets.
- Start with a trading strategy that's been proven on one market and try to expand its application to a portfolio of markets, including the one for which it was originally designed.
- Start with a proven trading strategy designed for one side of the market — long or short — with the goal of applying it to the other side of the same or a different market.
- Start with an existing trading strategy and use the cloning feature to perform an approximate parameter optimization on the strategy inputs.
- Intervene in the build process by using the cloning feature to replace less fit members in the population with more favorable strategies identified from the current generation.
The first five applications follow the same basic template: replace the population with clones of the strategy of interest and evolve the population according to new settings, data, and goals. The strategy of interest might be from the current population, exported from a different project file, or a trading idea implemented via the built-in editor and saved as a .gpcode file.
Application #6 — using the cloning feature to perform a parameter optimization — takes advantage of the option to mutate only the parameter values when cloning a strategy. It works as follows: start with a population consisting only of the strategy of interest (i.e., delete all other strategies from the main population using the right-click "Delete Selected Strategies" command). Clone the strategy to generate a large number of copies (e.g., 2000) using the option to mutate only the parameter values. Because the cloning process can be time-consuming, it's recommended that no more than about 1000 copies at a time are generated; i.e., for a large number of copies, it's more efficient to generate the copies in multiple steps. After the copies are generated, sort the table of build results by the fitness metric (listed at the far right of the table) on the training segment. This is equivalent to performing an optimization on the training segment, where the optimization "algorithm" consists of randomly selecting the parameter values. The optimal results will be those with the highest fitness. This application of strategy cloning will be illustrated below.
Note that if no optimization was previously performed on the population prior to this process, the training segment will be undefined, so it will be necessary to perform a brief build, such as a single generation on a small population, before performing the steps described above in order to establish the segments. Running a brief build will also be necessary if changes are made to the default metrics in order to define the fitness.
The last application listed above is a way to override the normal build process based on your subjective evaluation of specific trading strategies observed during the build process. While the fitness metrics are intended to capture your idea of what constitutes good strategies, sometimes a strategy that looks good may not rank as high as you expect. Normally in that case, you would either redefine the fitness to better represent what you want or you could set up metric conditions to filter that strategy into the Top Strategies population. Using strategy cloning is a third option. If you see a trading strategy that looks particularly good, you can stop the build process, clone the strategy to replace less fit members, then restart the build process from the modified population. For example, you could replace the least fit quarter of the population with the strategy you like, which will bias the population towards the cloned strategy.
To illustrate the strategy cloning process, a simple trading strategy was created in Adaptrade Editor, the built-in editor that comes installed with Builder. The strategy enters long (short) on a stop at the highest high (lowest low) provided a short-term moving average is above (below) a long-term moving average. A protective stop for a long (short) position is placed at the entry price minus (plus) the width of a channel defined by the highest high minus the lowest low. At the same time, a target exit for a long (short) position is placed at the entry price plus (minus) the same channel width as for the protective stop. The long and short sides use the same parameter values: the short and long-term moving average lengths are 5 and 25 bars, respectively; the look-back length for the highest high and lowest low for the entry prices is 3 bars; the look-back length for the highest high and lowest low for both the protective stop and target exits is 10 bars.
The strategy described above was unoptimized; the logical elements and parameter values were chosen without the benefit of hindsight. It can be thought of as a rough trading idea that needs further examination to determine whether it's viable. Towards that end, the figure below displays the equity curve resulting from applying this strategy to daily bars of the E-mini S&P 500 futures (symbol ES). As can be seen from the figure, the strategy is not profitable in its original form. Given that the stock market has a pronounced upward bias, whereas the strategy trades both sides of the market using the same rules, this is probably not surprising. In fact, as a contribution to the total net profit, the long trades are profitable overall whereas the short trades are not. This can be seen even more clearly when the original strategy is split into long-only and short-only versions in the editor. Although not shown, if the short side is removed from the strategy without changing anything else, the strategy is profitable over the same data. Likewise, if the long side is removed, the short-only strategy is unprofitable.
Figure 3. Closed trade equity curve versus trade number for the original long/short strategy evaluated on daily bars of the E-mini S&P 500 (ES).
Although one obvious way to improve the viability of the original strategy would be to restrict it to long trades, let's assume that we want to be able to trade both sides of the market. The first thing we might look at is the parameter values. Perhaps if the short-side parameter values were more attuned to that side of the market, the short trades would be profitable. To find out, the strategy cloning technique suggested above in application #6 can be used.
I first redefined the fitness by adding several build objectives to the default metrics: No. Trades ≥ 100; Drawdown ≤ $15,000.00; and Ratio Long/Short Profit ≥ 0.000. The latter helps ensure that the short trades are profitable since, otherwise, the ratio of long to short profit would be negative. I then ran a brief build over a population of 100 members for 1 generation to establish the fitness function and the segments, which are defined on the Build Symbols window. I then deleted the population, imported the original strategy from the .gpcode file, and cloned it. For cloning, I mutated only the parameter values, adding the members to the end of the population, which initially contained only the original strategy. I generated 999 clones followed by 1000 clones to create a population of 2000 members. Costs were set to $25 per contract. Lastly, I selected a member from the Build Results table, selected "Evaluate All" from the Evaluation menu, and sorted the resulting table by the fitness on the training segment.
The results are shown below in Figs. 4 and 5. Fig. 5 depicts the strategy listed at the top of the table in Fig. 4, which has the highest fitness on the training segment. As can be seen in Fig. 5, the results are not great, although they are profitable out-of-sample. The first three strategies shown in Fig. 4 are similar, whereas the next three have negative out-of-sample results. This suggests that modifying the strategy inputs alone may not be sufficient to make this a viable strategy for the ES market.
Figure 4. Build results after cloning with parameter value mutation, sorted by training fitness.
Figure 5. Closed trade equity curve versus trade number for the long/short strategy with mutated parameter values for the strategy with the highest fitness on the training segment.
One way to proceed would be to repeat the process above but mutate both the parameter values and strategy logic. However, this would be essentially the same as running the build process, only less effective. For that reason, I instead chose to start with a population of clones of the initial strategy and run the build process on this initial population. As above, I started with an empty population, imported the original strategy from the .gpcode file, and cloned it to produce a population of 200 members. I mutated only the parameter values, adding the members to the end of the population, which initially contained only the original strategy. This created an initial population of copies of the original strategy, where the copies (clones) differed only in the parameter values, just like in the example above.
After unchecking the "Reset on Build" option on the GP Settings window and setting the population size to 200, I ran a few initial builds. This led me to make a change to the default metrics: I added a drawdown condition (Drawdown ≤ $25,000.00). As before, I set the trading costs to $25 per contract. Using a nonzero value for costs helps prevent the build process from settling on strategies with an unrealistically small net profit. With these settings, I ran the build process until the fitness on the test segment started to decline (based on the Build Termination Tracking chart of the Build Progress window).
The results are shown below in Figs. 6 and 7. Comparing the Build Results in Fig. 6 to those of Fig. 4, it's apparent that the results in Fig. 6 are much better, with greater net profit, smaller drawdown, and lower complexity. The equity curve for the top strategy, based on the training fitness, is displayed in Fig. 7, where it shows positive results on all three segments. Examining the strategy code reveals why the complexity is lower: the entry conditions (moving average crossover) of the original strategy have been removed by the evolutionary build process. The resulting strategy retains the channel breakout entry, which is now the only entry condition. The build process found that the moving average entry condition was unhelpful and only reduced the strategy's performance.
Figure 6. Build results after building from an intial population of clones of the original strategy.
Figure 7. Closed trade equity curve versus trade number for the strategy with the highest training fitness after building for 39 generations, starting with a population of clones of the original strategy.
The original breakout strategy described above is contained in this editor file, which is compatible with Adaptrade Editor version 1.1 or newer. The project file used for the parameter mutation test (see Fig. 4) is available here. The project file used for the build test (see Fig. 6) is available here. The project files can be opened in Adaptrade Builder version 4.1 or newer. Builder is available as a free trial for those who want to examine the project file or editor file but don't have a licensed copy of the program. The EasyLanguage code in text file format for the original breakout strategy described above is available here. The EasyLanguage code in text file format for the optimized version of the original breakout strategy described above (see Fig. 7) is available here.
Summary and Discussion
The strategy cloning feature in Adaptrade Builder can be an effective way to utilize the features of the program with an existing trading strategy. As illustrated here, if you have a basic idea for a trading strategy, you can implement it using the built-in editor then develop it further using strategy cloning. The simplest application of the cloning feature is to mutate the strategy input parameters. If more extensive changes are needed, the build process can be used to evolve an initial population of clones of the original strategy, as illustrated above.
While starting with an existing strategy may not always make sense, when it does, it may be less likely to lead to an over-fit solution than starting with a randomly generated population. Starting with an existing strategy usually means less variation across the population, which means that fewer changes have been made to the strategies. Fewer changes means it's less likely that the strategies will over-fit the training data. At one end of this spectrum is cloning the strategy by mutating only the parameter values. At the other end, all parts of the strategy — logic and parameter values — are subject to mutation during the build process. However, even when all elements of the strategy are subject to change, as in the results shown in Fig. 6, the fact that the initial population is relatively uniform means there will be less variation in the results and therefore a lower likelihood of over-fitting compared to a normal build process.
Mutating the strategy inputs as a way to optimize them, as illustrated in the first part of the example (Figs. 4, 5) is similar in some ways to the stress testing feature of Builder. The latter uses Monte Carlo analysis to randomly vary aspects of the strategy, which can be restricted to the strategy inputs, and reports the results at a specified confidence level. If stress testing had been applied to the original strategy above, a so-called "spaghetti" plot of the different equity curves generated by varying the input parameters would have been created, and the listed performance results would have been those at the specified confidence level. While the random changes to the inputs would have been similar to those from the strategy cloning technique, the purpose of the stress testing feature is to assess the robustness of the strategy as given, not to explore different input values. The strategy cloning technique, on the other hand, generates and displays the results from each set of input values, which allows us to find the best set.
For the second part of the example, where the population was evolved, the initial population was created by cloning the original strategy using the option to mutate only the strategy inputs. I could have chosen to create the initial population by mutating both the input values and the strategy logic. Or I could have selected the option to create exact copies of the original strategy. However, initial testing suggested that if all elements of the strategy were mutated, the initial population would contain so much variation that after a few generations, it would be similar to starting with a random population. On the other hand, starting with a completely uniform population, where all strategies in the initial population were identical, would require additional generations to introduce sufficient variation into the population. In general, starting from an initial population where only the strategy inputs have been mutated seems to provide the best compromise.
The combination of strategy cloning with the built-in editor and the ability to import individual strategies and copy and delete members of the population offers a different way to use Adaptrade Builder. In cases where you have an existing trading strategy or idea that you want to develop further, it may be worth keeping in mind the seven applications of strategy cloning listed above.
Good luck with your trading.