cTrader Algo allows for backtesting cBots directly from a plugin, which opens many possibilities for algo developers. Read our one-minute summary below to learn more.
Backtest in plugins in one minute!
Launch backtesting programmatically or in response to user feedback and output the results in any suitable place in the cTrader UI where a plugin could be placed.
Extend built-in backtesting capabilities inside cTrader by adding new backtesting strategies such as Monte Carlo simulation.
Add custom statistics to backtesting results and show them directly in the cTrader UI.
Create complex optimisation methods going beyond the standard genetic algorithm.
How backtesting in plugins works
The Plugin base class has access to the Backtesting interface from which it can call the Start() method with the following signature.
In the parameterValues array, cBot parameters must be passed in a fixed order (the order in which they are specified in the cTrader UI). If some parameters are missing, default values are inserted automatically.
Backtest processes
When launching backtesting programmatically, you can launch several backtesting processes in parallel, which potentially could save you plenty of time.
In addition, the interface also contains two events, namely ProgressChanged and Completed. The arguments for the Completed event (BacktestingCompletedEventArgs) contain a JSON object of the final backtesting results (JsonReport), allowing you to interpret them as needed and display the resulting statistics to new users.
Create an example plugin
The following plugin displays a new block in Active Symbol panel (ASP). Inside the block, the plugin allows users to choose any cBot they own and backtest it on EURUSD h1. After backtesting concludes, the plugin displays the final ROI and net profit.
usingSystem;usingcAlgo.API;usingcAlgo.API.Collections;usingcAlgo.API.Indicators;usingcAlgo.API.Internals;usingSystem.Linq;usingSystem.Text.Json;usingSystem.Text.Json.Nodes;namespacecAlgo.Plugins{[Plugin(AccessRights = AccessRights.None)]publicclassBacktestingInPluginsSample:Plugin{// Declaring the necessary UI elements// and the cBot (RobotType) selected in the ComboBoxprivateGrid_grid;privateComboBox_cBotsComboBox;privateButton_startBacktestingButton;privateTextBlock_resultsTextBlock;privateRobotType_selectedRobotType;protectedoverridevoidOnStart(){// Initialising and structuring the UI elements_grid=newGrid(3,1);_cBotsComboBox=newComboBox();_startBacktestingButton=newButton{BackgroundColor=Color.Green,CornerRadius=newCornerRadius(5),Text="Start Backtesting",};_resultsTextBlock=newTextBlock{HorizontalAlignment=HorizontalAlignment.Center,VerticalAlignment=VerticalAlignment.Center,Text="Select a cBot...",};_grid.AddChild(_cBotsComboBox,0,0);_grid.AddChild(_startBacktestingButton,1,0);_grid.AddChild(_resultsTextBlock,2,0);varblock=Asp.SymbolTab.AddBlock("Backtesting Plugin");block.Child=_grid;// Populating the ComboBox with existing cBotsPopulateCBotsComboBox();// Assigning event handlers to the Button.Click,// ComboBox.SelectedItemChanged, and Backtesting.Completed events_startBacktestingButton.Click+=StartBacktestingButton_Click;_cBotsComboBox.SelectedItemChanged+=CBotsComboBox_SelectedItemChanged;Backtesting.Completed+=Backtesting_Completed;}protectedvoidStartBacktestingButton_Click(ButtonClickEventArgsobj){// Initialising and configuring the backtesting settingsvarbacktestingSettings=newBacktestingSettings{DataMode=BacktestingDataMode.M1,StartTimeUtc=newDateTime(2023,6,1),EndTimeUtc=DateTime.UtcNow,Balance=10000,};// Starting backtesting on EURUSD h1Backtesting.Start(_selectedRobotType,"EURUSD",TimeFrame.Hour,backtestingSettings);// Disabling other controls and changing// the text inside the TextBlock_cBotsComboBox.IsEnabled=false;_startBacktestingButton.IsEnabled=false;_resultsTextBlock.Text="Backtesting in progress...";}protectedvoidPopulateCBotsComboBox(){// Iterating over the AlgoRegistry and// getting the names of all installed cBotsforeach(varrobotTypeinAlgoRegistry.OfType<RobotType>()){_cBotsComboBox.AddItem(robotType.Name);}}protectedvoidBacktesting_Completed(BacktestingCompletedEventArgsobj){// Attaining the JSON results of backtestingstringjsonResults=obj.JsonReport;// Converting the JSON string into a JsonNodeJsonNoderesultsNode=JsonNode.Parse(jsonResults);// Attaining the ROI and net profit from backtesting results_resultsTextBlock.Text=$"ROI: {resultsNode["main"]["roi"]}\nNet Profit: {resultsNode["main"]["netProfit"]}";// Re-enabling controls after backtesting is finished_cBotsComboBox.IsEnabled=true;_startBacktestingButton.IsEnabled=true;}protectedvoidCBotsComboBox_SelectedItemChanged(ComboBoxSelectedItemChangedEventArgsobj){// Updading the variable to always contain// the cBot selected in the ComboBox_selectedRobotType=AlgoRegistry.Get(obj.SelectedItem)asRobotType;}}}
The plugin dynamically reacts to the status of the backtesting process. As soon as backtesting is finished, the plugin shows the results in the TextBlock. The _startBacktestingButton and the _cBotsComboBox are disabled throughout backtesting.
Summary
Backtesting via plugins is a powerful feature allowing you to build UI extensions on top of the already powerful backtesting logic provided by cTrader. Coupled with other API members such as AlgoRegistry, backtesting in plugins offers plenty of possibilities for anyone selling and developing cTrader algos.