Skip to content

Backtesting and Optimizing a cBot

Introduction

Backtesting exists to evaluate cBots by allowing them to trade on historical market data under certain pre-defined conditions.

When backtesting, you can run a cBot instance on past market movements. Afterward, cTrader will generate a detailed report about the trading operations performed by your cBot and the final equity/balance statistics.

Note that any trading actions performed when backtesting cBots will not affect any of your accounts. Backtesting is not intended to deal with any real funds. Instead, this feature only exists for analysis purposes.

To backtest a cBot, select one of its instances and switch to the 'Backtesting' tab.

Image title

Backtesting Settings

To set up how backtesting works, click on the 'cog' icon located in the upper-left corner of the UI. cTrader should open the following menu.

Image title

The options in this menu are defined as follows. All money-related parameters (e.g., the starting capital) are specified in USD.

Option Name Action and Description
Starting Capital Define the starting capital with which your cBot will operate when trading.
Commission Establish the commission rate per million traded units.
Data Choose which timeseries data that your cBot will be tested on. The available options are as follows.
  • Tick data from server. The data will be taken directly from the server on a per-tick basis. This is the most accurate historical data source.
  • M1 bars from the server. The data will be taken from one-minute bars generated by the server.
  • M1 bars in CSV file. The data will be taken from one-minute bars defined in a locally stored CSV file.
  • H1 bars from the server The data will be taken from one-hour bars generated by the server.
Spread Select the spread value(s) that will be applied during backtesting. The following options are available.
  • Fixed Value. Only one value will apply for the entirety of backtesting. You can choose it from a drop-down menu, input a custom value, or match the value to the current symbol spread (which is updated every tick).
  • Random. Establish the minimum and maximum spread rates. When your cBot places an order, a random spread value ranging between the chosen rates will apply to this order.

Sample CSV M1 Data

To source trading data from your local machine, make sure to create a comma-separated CSV file containing the following data.

  • Date
  • Time
  • Open Price
  • High Price
  • Low Price
  • Close Price
  • Volume

Example

1
2
3
4
2003.06.18,16:01,1.11423,1.11428,1.11332,1.11374,19
2003.06.18,16:02,1.11364,1.11436,1.11361,1.11405,7
2003.06.18,16:03,1.11402,1.11455,1.11400,1.11440,5
2003.06.18,16:04,1.11446,1.11461,1.11401,1.11447,14

Backtesting Procedure and Modes

Specify the period for testing using the controls summarized below.

  • Use the interactive slider at the top of the 'Backtesting' tab.
  • Select the necessary values from the calendar menus to the left and right of the slider.
  • Input custom values (using the DD:MM:YYYY format) into the fields on both sides of the slider.

Image title

You can run backtesting using the following modes.

  • Non-real-time testing. Your bot performs all of the required operations in sequence; afterward, you only have access to the final results including trading statistics, the equity chart, etc.
  • Real-time (visual mode) testing. The historical data you have provided is passed to your cBot at a certain playback speed that you can customize. As a result, you can see trading operations as they are placed. All trading statistics are also updated at the playback speed you have chosen.

Non-Real-Time Testing

After setup is finished, click on the 'Play' button to the right of the slider. Depending on the length of the specified period and your local machine specs, you may need to wait several minutes before cTrader Automate generates the results.

Real-Time (Visual Mode) Backtesting

Specify the required settings including the testing period and enable the 'Visual Mode' flag located below the calendar slider.

Image title

Adjust the data playback speed by dragging the 'Speed' slider or using the menu to its right. After you are finished setting up, press the 'Play' button.

cTrader will then start displaying a trading chart for the chosen period in real-time accelerated using your playback speed setting. Note that you can adjust the playback speed dynamically as backtesting occurs.

Your cBot will also perform trading operations in real-time reacting to the technical analysis signals that materialize in the chart. The backtesting statistics will be automatically updated based on the actions taken by your cBot.

Depending on your chosen period and the playback speed, visual mode testing may be time-consuming. Nonetheless, if your cBot is not behaving as expected, you can test its reactions to various market conditions by using visual mode testing and custom trading data sourced from a CSV file.

Backtesting Using Renko Charts and Range Bars

cTrader supports backtesting cBots on Renko and range bar charts. To perform such a backtest, create a new cBot instance and select a Renko/range bar chart as the trading chart to which it is attached.

Image title

Alternatively, with a cBot instance already selected, use the chart selector menu at the top of the screen by clicking on the 'three-dots' icon. In the menu that has appeared, select one of the available volume thresholds for generating Renko bricks or range bars.

Image title

After cTrader generates a Renko/range bar chart for the chosen symbol, switch to the 'Backtesting' tab. In it, configure the backtesting mode/settings as you normally would. Click on the 'Play' icon to perform a backtest on the chosen chart.

Backtesting Results

cTrader Automate generates several trading statistics to showcase backtesting results. To view this data, proceed to the tabs located to the right of the 'Parameters' window.

Image title

Backtesting Results

cTrader generates several trading statistics to showcase backtesting results. To view this data, proceed to the tabs located just below the trading chart.

Image title

The Equity Chart

When backtesting is performed (regardless of whether you use visual mode), cTrader generates an equity chart with the number of trades on the X-axis and the account balance on the Y-axis. It contains the following statistics.

  • The yellow line showcases the account balance as it changes with each trade.
  • The grey zone highlights how total equity increases or decreases depending on the trades made by your bot.

To get a better idea of what the equity chart does, consider the example above. It shows that our bot has performed more than 290 trades during backtesting. With each change in the account balance, we can also see a corresponding change in total equity.

Trade Statistics

The 'Trade Statistics' tab contains data on how exactly your cBot has performed throughout backtesting.

Image title

In the above example, our bot has managed to achieve a +848% return given our initial capital. The 'Trade Statistics' tab includes the following fields.

Field Name Definition
Net Profit The total net profit of all trades.
Profit Factor The ratio calculated by dividing the total net profit by the total net loss.
Commission The total amount of commissions paid for the trades made by your cBot.
Max Balance Drawdown The maximum amount of the balance drop-down.
Max Equity Drawdown The maximum amount of the equity drop-down.
Total Trades The total number of trades performed by your cBot.
Winning Trades The total number of trades that have resulted in realized profits.
Max Consecutive Winning Trades The largest number of consecutive trades that have generated realized profits.
Largest Winning Trade The largest realized profit generated by one trade.
Losing Trades The total number of trades that have generated realized losses.
Max Consecutive Losing Trades The largest number of consecutive trades that have generated realized losses.
Largest Losing Trade The large amount of realized losses generated by one trade.
Average Trade The average realized P&Ls generated by all trades.
Sharpe Ratio A ratio measuring the risk-adjusted performance of your bot. It is calculated by dividing the total cBot returns by their standard deviation. Higher ratio values are indicattive of higher performance.
Sortino Ratio An alternative to the Sharpe ratio. Instead of using standard deviation in its calculation, it uses downvard deviation.

Positions

The 'Positions' tab showcases all positions that are currently open by your cBot. It is structured analogously to the 'Positions' tab in the regular 'Trade Watch' display and contains the same data.

Image title

Click on the 'cog' icon in the lower-right corner to customize what data is displayed in the central table.

Orders

The 'Orders' tab contains information about the orders that have been placed by your cBot. Its structure and appearance copy the 'Orders' tab in the main 'Trade Watch' display.

Image title

History

The 'History' tab displays statistics on all opening and closing deals that have been recorded during backtesting. Similarly to other tabs discussed above, it copies the 'History' tab in the 'Trade Watch' display.

Image title

Events

The 'Events' tab lists all server-related communications and displays various parameters of these events.

Image title

Log

Last but not least, the 'Log' tab displays your cBot output throughout backtesting. The list of messages is fully searchable and filterable by event type and instance.

Image title

Optimization

It can be difficult to specify an optimal set of initial parameters for a cBot. To address this issue, cTrader offers a built-in bot optimization feature. Optimization takes your code and runs it several times with each 'pass' being based on various parameter values. It then presents you with a set of customizable results which you could use to define the optimal parameter configuration.

To use this feature, select a cBot instance and switch to the 'Optimization' tab.

Image title

Afterward, define the backtesting period for optimization by using the drop-down calendars or by dragging the slider.

Image title

Optimization Settings

As optimization is essentially just a series of backtests, you can specify backtesting settings analogously to how it is done in the 'Backtesting' tab.

Optimization Parameters

Click on the 'Parameters' button to the left of the calendar slider. You should see the following window.

Image title

In it, check the flags next to the cBot parameters that you would like to optimize. The 'Timeframe' parameter is available for all cBots.

Optimization Criteria

Press the 'Criteria' button located to the right of the 'Optimization Parameters' button. cTrader will open the following tab.

Image title

Optimization criteria define how the optimization algorithm ranks your result after backtesting. You can choose between the following options.

  • Standard. A series of predefined criteria that you can aim to either minimize or maximize. To do this, choose a criterion from a drop-down menu to the right and select the optimization direction in its related menu to the left. To add a new criterion, click 'Add Criterion'.
  • Custom. A custom criterion defined within your cBot code using the GetFitness() method as shown in the below examples.
1
2
3
4
5
protected override double GetFitness(GetFitnessArgs args)
{
    // Maximize the winning trades/losing trades ratio.
    return args.WinningTrades / args.LosingTrades;
}
1
2
3
4
5
6
protected override double GetFitness(GetFitnessArgs args)
{
    /* Maximize the winning trades/losing trades ratio
    while giving winning trades more weight. */
    return Math.Pow(args.WinningTrades, 2) / args.LosingTrades;
}

Multi-Criteria Calculations

If multiple criteria are used to calculate parameter effectiveness, cTrader will use all of them equally to calculate the fitness value for an optimization pass.

Specifically, the platform multiplies the values of all maximizing criteria and separately multiplies the values of all minimizing criteria. Subsequently, it divides the absolute multiplication value for maximizing criteria by the same value for minimizing criteria.

The following pseudocode highlights how exactly multi-criteria fitness values are calculated.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
numerator = 1.0
if (valuesToMaximize.Length > 0)
    numerator = Abs(Multiply(criteriaValuesToMaximize))

denominator = 1.0
if (valuesToMinimize.Length > 0)
    denominator += Abs(Multiply(criteriaValuesToMinimize))

/* The 'sign' variable can be either +` or -1 depending on whether
there are criteria for which their values are less than 0. */
sign = criteriaValuesToMinimize.Concat(criteriaValuesToMaximize).Any(v => v < 0) ? -1 : 1

fitness =  sign * numerator / denominator

Method

Press the 'Method' button (showcased either as GA or # depending on which option is chosen). In the below menu, choose which optimization method is used by the platform.

Image title

The following options are available.

  • Genetic Algorithm. This algorithm emulates the biological evolution process. Please, see a separate section for its detailed description.
  • Grid (#). This algorithm sequentially backtests each possible set of parameters.

In our estimation, the genetic algorithm is significantly faster for finding optimal parameter values.

Resources

Click the 'Resources' button to select which percentage of your CPU load is allocated for backtesting. Move the slider to set the CPU usage percentage.

The more resources you allocate, the faster the optimization process will be completed. However, you may see a noticeable drop in performance when using other applications.

Image title

Note that the CPU resources can also be adjusted during optimization itself.

Starting and Managing the Optimization Procedure

To proceed with optimization, click on the 'Play' button to the right of the calendar slider. Depending on your machine resources, the optimization settings, and cBot complexity, optimization may take some time.

The UI bar immediately below the calendar slider will provide information about the number of backtesting passes completed, the elapsed time, and the remaining time estimate.

Image title

The central screen in the 'Optimization' tab, meanwhile, will provide a real-time grid containing information about all of the backtesting passes that the algorithm has completed.

Image title

To apply a set of parameters tested during a certain pass, press the 'Apply' button. It only becomes active if no optimization procedures are currently running.

Alternatively, check the 'Autoselect the best pass' flag in the upper-left corner to select the pass (and the parameters) that has achieved the best possible result according to your specified optimization criteria.

Optimization Results

After optimization is completed, the central table will display the final list of all backtesting passes and their results.

This table has the following columns. As the grid is fully configurable, these columns can be dragged-and-dropped or disabled altogether after right-clicking on the table and deselecting them from the contextual menu.

Field Definition
Pass The pass number.
Fitness The value showcasing how well the pass fits the optimization criteria.
Equity Total equity at the end of the pass.
Balance Total balance at the end of the pass.
Net Profit The difference between the final balance and the starting balance.
Trades The total number of closed positions.
Winning Trades The total number of winning trades achieved during the pass.
Losing Trades The total number of losing trades achieved during the pass.
Profit Factor The total profit/total loss ratio.
Max Equity Drawdown (%) The maximum percentage of the equity drawdown.
Max Balance Drawdown (%) The maximum percentage of the balance drawdown.
Max Equity Drawdown The maximum equity drawdown specified in the account deposit currency.
Max Balance Drawdown The maximum balance drawdown specified in the account deposit currency.
Sharpe Ratio A ratio measuring the risk-adjusted performance of your bot. It is calculated by dividing the total cBot returns by their standard deviation. Higher ratio values are indicattive of higher performance.
Sortino Ratio An alternative to the Sharpe ratio. Instead of using standard deviation in its calculation, it uses downvard deviation.
Average Trade An average profit for all trades made during the pass.
Pass Parameters Click on the 'Apply' button in this column to apply the parameters from this pass to your cBot.

Select a pass to view detailed statistics about it in the display below the central grid.

Image title

The first seven tabs in this display provide the same information as the same tabs in the 'Backtesting' window. The 'Pass Parameters' tab is unique to optimization.

Pass Parameters

The 'Pass Parameters' tab provides the following information.

Image title

Automate will highlight all optimized parameters in green while all fixed parameters (not enabled in the 'Parameters' menu) will remain unhighlighted.


Last update: January 27, 2023