A cTrader cBot restart is safe only if the restarted instance rebuilds its view of the account before it can send another order. A normal backtest usually starts from an empty, orderly state; a live restart may find open positions, pending orders and a half-finished decision. Test that boundary deliberately, or the first failure may be a duplicate trade.
This is not a prediction about a strategy. It is a reliability test: after a stop and start, does the cBot recognise what already exists, restore only the state it truly needs, and wait rather than guess?
A restart is an account-state problem
A restart test asks whether the cBot can reconcile its own records with the account as it is now. Reconciliation means reading the live positions and pending orders, identifying those that belong to this instance, and making a fresh decision from that evidence.
The distinction matters because a cBot can have two kinds of state:
| State | Safe source after a restart | Typical failure if it is wrong |
|---|---|---|
| Account truth | Current positions, pending orders, symbol and account data from cTrader | It opens an order that already exists or manages the wrong one |
| Strategy memory | A small, versioned record such as the last processed bar or a cooldown | It repeats a signal or skips a valid action |
| Derived values | Recalculate from current account data | It trusts stale P&L, volume or risk figures |
cTrader provides position Open, Modified and Closed events, including activity initiated manually as well as by a cBot. Its trading-operations documentation is a useful map of those events. Events are useful while the cBot is running; they are not a substitute for checking the collections again when it starts.
Define the restart contract before testing it
Write down what the cBot is allowed to do on its first pass after OnStart(). A cautious contract is simpler to test than a clever recovery routine.
For example, the contract might say:
- Read all current positions and pending orders.
- Filter them by the cBot's label, symbol and any instance identifier it owns.
- Reconstruct any necessary cooldown or once-per-bar guard.
- Subscribe to ongoing position and pending-order events.
- Do not create a new order until the reconciliation result is complete.
The exact label scheme is implementation-specific. What is not optional is the proof that the filter cannot confuse a manually opened trade, another cBot, or a second instance with its own work. A label is an identifier, not a decoration.
If the strategy uses local storage, make the stored record narrow and explicit. cTrader's local-storage guide says the default scope is instance-level, data is automatically saved every minute and on instance stop, and Flush() can save it without waiting. That is a reason to record a small checkpoint after a completed state transition, not a reason to assume a checkpoint proves an order reached the account.
Run a restart matrix, not one happy-path test
Stopping a flat cBot and starting it again tests almost nothing. Use a small matrix where the expected account state is visible before the restart.
| Scenario at stop | What the restarted cBot must prove | Red flag |
|---|---|---|
| No position and no pending order | It remains eligible only if the current signal is genuinely new | An immediate repeat of the last action |
| One managed position | It recognises the position and does not re-enter | A second position with the same intended exposure |
| A managed pending order | It finds, retains or cancels it according to the written rule | A duplicate pending order |
| A position changed outside the cBot | It follows the documented ownership rule | It silently overwrites manual risk controls |
| Restart on the same bar | The once-per-bar guard has a defined result | Two decisions from one bar |
For each case, retain a timestamped log before the stop, at startup and after the first decision cycle. Record the position IDs, labels, volumes, pending-order IDs and the decision made. A chart screenshot can show the outcome; it cannot show whether the second order was prevented by design or by luck.
Make the duplicate-order check binary
The most valuable assertion is plain: following a restart, the cBot creates zero extra orders for the already-processed setup. It should be possible to inspect the account history and say whether that statement is true.
This test should include a restart immediately before and immediately after the entry condition. Those are different states. If the system cannot say which bar or signal it has processed, it does not have a reliable answer at that boundary.
Local storage has limits that a backtest can hide
Local storage can help retain strategy memory across stops and starts, but cTrader documents a material distinction: during backtesting and optimisation, local-storage operations use memory only. A backtest can therefore validate trading logic without proving that persistent state behaves as expected in a real-time deployment.
The storage scope also changes the risk of collision. cTrader documents instance, type and device scopes; the broader the scope, the more deliberately the key must separate instances. Treat a shared scope as shared state, not as a convenient global variable.
Cloud execution adds another boundary. The cTrader Cloud requirements state that resources allocated to a cloud instance are freed when it is stopped or deleted, and files it created are deleted on restart or deletion. If a cBot depends on a file or local state surviving that event, test the exact deployment mode rather than inferring behaviour from a desktop run.
That is an honest limitation: a clean historical equity curve does not establish restart safety. It is evidence of a historical trading sequence, not proof that the live process can recover from interruption.
Keep recovery separate from the trading edge
Recovery code should reduce uncertainty, not invent a position. When the cBot finds a mismatch between its checkpoint and the account, the safe outcome may be to log the mismatch and stand aside until the next defined signal. Whether to close, alter or replace an order is a trading decision with consequences; it should not be smuggled into a restart handler.
This same separation improves a verifiable methodology: account constraints, execution assumptions and validation steps remain inspectable instead of hiding inside an equity curve. It also matters for a funding account, where an unwanted duplicate position can change the equity path that loss rules measure.
realbacktesting is a trading-software studio for cTrader built around tests a trader can inspect. A restart log is part of that standard. It does not make a strategy profitable, and it cannot guarantee a platform or network will never fail. It can prove whether the cBot's response to a defined interruption was controlled.
Frequently asked
Can a cTrader backtest prove restart recovery?
No. A backtest can test the strategy's historical order logic, but cTrader documents that local storage is in-memory during backtesting and optimisation. Test the chosen real-time deployment separately.
Should a cBot save every account detail locally?
No. Current positions and pending orders are account truth and should be reconciled from cTrader at startup. Persist only the minimum strategy memory needed to avoid repeating or skipping a defined action.
What is the first thing to check after a cBot restart?
Check whether the first decision cycle creates an extra order for an existing position, pending order or already-processed signal. That result should be visible in the account history and startup log.
Does local storage always survive a cloud restart?
Do not assume it does. cTrader's Cloud requirements say resources allocated to a stopped or deleted cloud instance are freed; test the exact cloud lifecycle and storage behaviour your cBot uses.
The stubborn takeaway
If a cBot cannot account for its existing orders after a restart, it has not earned the right to place the next one.