Optimise a cBot¶
The optimize command searches a range of cBot parameter values to find combinations that score well against the criteria you choose. It runs the same genetic or grid sweep as the cTrader desktop application, driven from the terminal plus a JSON file of parameter settings. It is the optimisation counterpart of the backtesting command.
Scope¶
The optimize command optimises cBot parameters. Indicators and plugins are managed through their own commands (indicator calculate, indicator history, create, build) and are not part of optimisation.
Prerequisites¶
- cTrader CLI is installed and you can sign in.
- The cBot is exported as an
.algofile and built for .NET 8. - A parameters file that defines which parameters to sweep.
Note
The optimize command is available in the local cTrader CLI edition only. It is not part of the internal or cloud build.
The optimize command¶
ctrader-cli optimize <path-to-algo-file> --params=<path-to-params-file> [options]
The path to the .algo file is the first argument. --params is required. The base timeframe must come from either --timeframe or the parameters file. If neither provides it, the command stops with an error.
Optimisation options¶
Only --params is required. Common optional choices shown in the examples below are --timeframe, --method, --criteria, --optres and --passes-dir.
A few options are worth knowing before you run:
--method–genetic(default) orgrid. Pickgridwhen the parameter space is small and you want every combination; pickgeneticwhen the space is large and a guided search is faster.--cores– number of parallel workers that run the backtest leg of each pass in parallel. Each worker uses one CPU thread, so the run uses roughly the same number of threads as the value you pass. Accepted values are integers of 1 or more. Defaults to half the processor count plus one. Lower it on a small VPS to leave room for other workloads, or raise it on a dedicated machine to spread a genetic sweep across more threads.--auto-select-best– automatically select the best pass when the run finishes, so the strongest.cbotsetis ready to use without a second step.
Note
The optimize command uses --timeframe, not --period. The run and backtest commands keep --period. Passing --period to optimize is rejected as an unknown option.
The parameters file¶
The --params file is a JSON object with a parameters array. This is the same shape that the cTrader desktop optimisation interface exports, so a file exported from the desktop application can be passed directly.
{
"parameters": [
{ "Name": "SlowPeriods", "Optimize": true, "Min": "5", "Max": "50", "Step": "5" },
{ "Name": "StopLossPips", "Optimize": true, "Min": "10", "Max": "60", "Step": "5" },
{ "Name": "MAType", "Optimize": true, "Values": ["0", "1", "2"] },
{ "Name": "MySymbol", "Optimize": true, "Values": ["EURUSD", "GBPUSD"] }
]
}
Field rules¶
Nameis required and should match a cBot property name. Runctrader-cli metadata <path-to-algo>to see the available property names. A name that is not found in the cBot metadata is logged and skipped, and the run continues with the remaining parameters.Optimizeset totrueincludes the parameter in the sweep. Set tofalseholds it fixed.- Range parameters, such as integers and doubles, that are being swept need
Min,MaxandStep. - Value parameters, such as enumerations and symbols, that are being swept need a non-empty
Valuesarray. ParameterTypeis optional. When omitted, the type is resolved from the cBot metadata by matchingName.
Fix a parameter to a single value¶
To hold a parameter at a fixed value, include it with Optimize: false and its Value:
{ "Name": "MAType", "Value": "1", "Optimize": false },
{ "Name": "FastPeriods", "Value": "5", "Optimize": false }
Warning
The parameters file is authoritative. Before applying it, cTrader CLI resets every parameter so that only the parameters you list with Optimize: true are swept. A parameter left out of the file entirely is held at its default value, even if it would default to optimised in the cBot. List a parameter with Optimize: true to include it.
Optimise the main timeframe¶
The optimize command can sweep the main timeframe as well as the cBot parameters. The main timeframe comes from two sources, with --timeframe taking precedence.
--timeframe <tf>– one value pins the main timeframe; several comma-separated values sweep it.- Parameters file – a desktop-exported file already includes a synthetic timeframe parameter for this purpose.
The base data timeframe is the single value, the pinned value or the smallest of the swept values.
Timeframe and data-mode compatibility¶
The swept or pinned main-timeframe values must be loadable under the chosen --data-mode.
| Data mode | Valid main-timeframe values |
|---|---|
open | Timeframes that are the same frame type and an exact multiple of the smallest selected timeframe. |
m1 or m1-csv | Any time-based timeframe; non-time frames such as Renko and range are rejected. |
ticks | Any non-custom timeframe. |
Note
An invalid combination stops the command before any data is loaded and lists the values that caused the failure.
Criteria¶
Each entry in --criteria pairs a performance index with a direction of max or min, such as NetProfit:max. The table below lists every supported index name and what it measures.
| Index | What it measures |
|---|---|
NetProfit | Final profit or loss in account currency |
ProfitFactor | Gross profit divided by gross loss |
MaxEquityDrawdownPercentages | Largest percentage peak-to-trough drop in equity |
MaxBalanceDrawdownPercentages | Largest percentage peak-to-trough drop in balance |
MaxEquityDrawdown | Largest absolute drop in equity, in account currency |
MaxBalanceDrawdown | Largest absolute drop in balance, in account currency |
WinningTrades | Number of trades that closed in profit |
LosingTrades | Number of trades that closed in loss |
TotalTrades | Total number of closed trades |
AverageTrade | Net profit divided by the number of closed trades |
To maximise net profit while minimising the maximum equity drawdown:
--criteria="NetProfit:max,MaxEquityDrawdownPercentages:min"
For a custom ranking, pass --fitness instead. The cBot's GetFitness method returns the score, and the run keeps the passes with the highest return value. --fitness is mutually exclusive with --criteria; pass exactly one.
Testing-context options¶
optimize reuses the testing-context options from backtest. The table below lists the options that the live CLI accepts, what each one sets and the difference between the two commands where it matters.
| Option | Purpose | Availability |
|---|---|---|
--account | Trading account number. | Both |
--symbol | Symbol to test on. | Both |
--start | Start date and time of the test range. | Both |
--end | End date and time of the test range. | Both |
--balance | Starting balance for the simulation. | Both |
--data-mode | open, m1, m1-csv, tick-csv or ticks. | Both |
--data-file | Path to a CSV file for m1-csv or tick-csv. | Both |
--commission | Commission amount per trade. | Both |
--spread | Spread in pips. | Both |
--precise-conversion | Use precise conversion for cross-currency pairs. | Both |
--timeframe | Base timeframe for the sweep. | optimize only |
--period | Base timeframe for the run. | backtest only |
--report | Path to save an HTML report. | backtest only |
--report-json | Path to save a JSON report. | backtest only |
Note
The report flags do not apply to optimize, so save results with --optres and --passes-dir instead.
Example¶
ctrader-cli optimize "C:/test/Sample Trend cBot.algo" \
--params=C:/test/optimize-params.json \
--account=1234567 --symbol=EURUSD --timeframe=h1,h2 \
--start="01/01/2025" --end="01/02/2025" \
--balance=100000 --data-mode=open --commission=30 --spread=2 \
--method=grid \
--criteria="NetProfit:max,MaxEquityDrawdownPercentages:min" \
--auto-select-best \
--optres=C:/test/result.optres \
--passes-dir=C:/test/result-passes \
--ctid=letstrade --pwd-file=C:/test/password.pwd
Output¶
While it runs, optimize streams progress to the terminal:
Progress | Loading EURUSD, h1 | 42.00 % |
Progress | Optimization | 37.50 % |
- Summary – on completion, cTrader CLI prints a summary to the terminal, including the total number of passes, the elapsed time and the best pass with its statistics.
- Result file – when you pass
--optres, cTrader CLI writes the full result as a.optresJSON file that lists every pass. This file uses the same format as the desktop optimisation results, so it can be opened or imported in the desktop optimisation interface. - Per-pass reports – when you pass
--passes-dir, cTrader CLI writes the per-pass report files into that directory, one subfolder per pass, each containing.html,.txt,.jsonand.cbotsetfiles. The.cbotsetfile shows the exact parameter values that pass used.
If you provide neither --optres nor --passes-dir, the run completes and only the summary is printed.
Note
The optimize command does not produce an aggregate HTML report. The per-pass HTML files are still written into --passes-dir when you provide it.
Validate that an optimisation applied correctly¶
After a run, confirm that the sweep did what you intended.
- Open a per-pass
.cbotsetfile under--passes-dirand check that the optimised parameters change between passes, while pinned and omitted parameters stay fixed. - When you swept the timeframe, check the
Chart.Periodvalue in each pass.cbotsetfile. It should match the timeframes you selected. - Open the
.optresfile, or import it into the desktop optimisation interface, to review the configuration and every pass together.
Validation and common errors¶
Each row in the table below shows the symptom, the likely cause, the exit code cTrader CLI returns on this failure and the next step to take. cTrader CLI exits with a non-zero status for every validation failure, so a script can stop on the first error without parsing the message.
Exit code in the table refers to the value cTrader CLI returns to the shell. Specific numbers are not published, so an entry of non-zero means the command failed without a distinct code; unknown means the failure is internal and the next step is to switch build or contact support.
| Symptom | Likely cause | Exit | Next step |
|---|---|---|---|
Validation error: missing --params | The JSON parameters file was not supplied. | non-zero | Pass --params=<path>. |
| Validation error: unknown timeframe | A --timeframe value is not a known token. | non-zero | Run ctrader-cli periods and use one of the listed tokens. |
| Validation error: invalid main timeframe | A timeframe value is not loadable under the chosen --data-mode. | non-zero | Pick a different timeframe or --data-mode. |
| Validation error: criteria pairs malformed | An index name is wrong, or a direction is not max or min. | non-zero | Use one of the supported index names with max or min. |
| Validation error: unknown criteria index | A --criteria name is not in the supported list. | non-zero | Use one of the supported index names listed under Criteria. |
Validation error: unknown --method value | --method is not genetic or grid. | non-zero | Use --method=genetic (default) or --method=grid. |
--fitness and --criteria both supplied | The two are mutually exclusive. | non-zero | Pass --fitness or --criteria, not both. |
optimize not available | The CLI build is the internal or cloud edition. | unknown | Switch to the local user edition. |