Build Algorithm

The build algorithm used in Adaptrade Builder is illustrated below. The core element of the algorithm is genetic programming (GP), which evolves a population of trading strategies based on their fitness. Fitter strategies combine to produce offspring strategies in analogy to the biological processes of reproduction and evolution.

The gray-shaded boxes in the figure represent the input data, which includes the price data for the market of interest, the indicators and order types in the so-called build set, and the options and performance criteria (build goals) selected by the user.

Build Algorithm

The algorithm starts with the Strategy Generation step. An initial population of trading strategies is randomly developed from the available technical indicators and rule types in the build set. Any options that the user has selected, such as exiting all positions at end-of-day, are applied at this point. Each strategy is then evaluated over the price data for the market of interest, and a fitness value is assigned based on a weighted average of the build goals specified by the user. For example, you might select net profit and drawdown as the two performance metrics and weight each one equally. The fitness would then be the average of the (normalized) net profit and drawdown.

To generate new members of the population, members of the current population are selected at random, and the fitter ones are chosen as parents for crossover and mutation. A less fit member is selected at random to be replaced by the new member. The process is repeated until as many new members have been created as there are members in the current population. This step represents one generation.

If the user has selected one of the Build Failure Rules, the results are checked on the test segment after the specified number of generations. If the results are not above the threshold chosen by the user, the process is reset, which causes the population to be re-initialized and the generation count to be reset to zero. After the specified number of generations has been successfully completed, the top strategies are listed in the Performance table in order of fitness.

Entry and Exit Conditions

The GP process evolves two essential strategy elements simultaneously: entry and exit conditions and orders for entry and exit. The entry and exit conditions are represented as tree structures, as shown below.

Entry conditions are stored in tree structures

The tree structure enables the generation of conditions with considerable complexity. Each node in the tree has between zero and three inputs, each of which leads to further branching. The tree is constructed recursively starting at the top with a logical operator (and, or, >, <, etc.) and proceeding to technical indicator functions, prices, and constants, such as indicator lengths. Each branch is terminated with a node that has no inputs. Available indicators in Builder are listed below. These are described in detail in the appendix to the user's guide. Custom indicators may be read into Builder as well.

Available Indicators in Builder

Simple moving average
Exponential moving average
Weighted moving average
Triangular moving average
Adaptive variable moving average
Zero-lag trend
Adaptive zero-lag trend
Moving average convergence divergence (MACD)
Triple exponential moving average (TRIX)
Rate of change (ROC)
Fast K stochastic
Fast D stochastic
Slow D stochastic
Relative strength indicator (RSI)
Inverse Fisher RSI
Inverse Fisher cycle
Adaptive inverse Fisher RSI
Adaptive inverse Fisher cycle
Commodity channel index (CCI)
Directional indicator (DI+/DI-)
Directional movement index (DMI)
Average directional index(ADX)
True range (TR)
Average true range (ATR)
Standard deviation
Ulcer index
Bollinger band
Keltner channel
Chaiken oscillator
Crosses above/below
Price patterns (e.g., O[2] < H[10], DayClose > L[1], etc.)
Consecutive bars up/down
Congestion count
Typical price
Floor trader pivots
Day of week
Time of day
Absolute value

The crossover operator of the GP process replaces a subtree in one parent with a subtree from the other parent. For example, the subtree on the right of the tree diagram, starting with “>” (i.e., SlowD(14) > FastK(5)), might be replaced with a different subtree from another member of the population. Mutation changes individual nodes in the tree. For example, the “Average” node might be replaced with “Lowest” so that the subtree Average(H, 23) becomes Lowest(H, 23).

An entry/exit condition is evolved separately for long and short trades unless the user selects “Long only”, “Short only”, or “Long/Short Symmetry”. Each condition is a logical statement; it evaluates to either true or false. A value of true means the condition is satisfied for that market side (long or short), which is necessary for the order to be placed.

In order to generate meaningful conditions, Builder applies both syntactic and semantic rules when building the conditions. Syntactic rules ensure that each node containing a function satisfies the input requirements for the function. For example, the Momentum function requires a price as the first input and a length as the second input. Semantic rules ensure that comparisons between different nodes are meaningful. For example, it makes sense to compare the Highest(C, 20) to a moving average since both functions return a price. However, it would not be meaningful to compare the closing price to the time of day or to compare a stochastic, which has a value between 0 and 100, to a moving average of price. The semantic rules enforce these requirements.

For additional information on the build process, including a description of the types of entry and exit orders and the general structure of trading strategies in Builder, please see the Introduction chapter in the user's guide.

Additional information on genetic programming for building trading strategies is available on the Articles page. Also, several newsletter articles illustrate the use of Builder and the genetic programming process.