A successful order response is not the same thing as the full requested size being executed. If your cTrader cBot treats the request as the position, a partial fill can leave its internal state out of step with the account.
Start with what actually executed
In cTrader, an order is an instruction; a deal records an execution. One order can produce several deals at different prices when available liquidity cannot fill the requested volume at once. A position is the exposure resulting from executed deals. cTrader's positions-and-deals guide explains those relationships. FINRA's overview of the trade lifecycle independently notes that an order may fill partially or not at all when its terms cannot be met; its example concerns stocks, not cTrader accounts. FINRA's trade-lifecycle guide
That distinction gives the bot three separate things to track: the requested order, each confirmed deal, and the resulting account position. Do not use the requested quantity as a shortcut for any of them.
A reconciliation loop for the bot
Use this sequence whenever execution updates arrive:
- Keep the order identity. Associate each execution update with the order that produced it. Do not create a second full-size request just because the first update is smaller than requested.
- Record each confirmed deal once. Store its identifier, executed volume, price and time. Treat a repeated notification as something to reconcile, not as proof that another fill occurred.
- Recalculate the remainder. Compare the original request with the confirmed executed volume. Keep any still-open remainder distinct from what has already traded.
- Read the account position. Confirm the position after the deal update. On a hedging account, several positions can exist for one symbol; on a netting account, deals on that symbol affect one net position. cTrader documents both account behaviours.
- Choose the next action from the reconciled state. Wait while the order remains active, handle a confirmed cancellation or expiry, or submit a deliberately sized new request only after the prior order's status and remaining exposure are clear.
The exact event fields and order-state transitions depend on the integration you use. Keep the adapter-specific code separate from the strategy decision so you can verify its behavior against the current cTrader order documentation.
Test the awkward sequence, not just the happy path
A useful hypothetical test is: a bot requests size Q, receives a deal for A, then receives another deal for B while some requested volume remains open. Assert that the recorded executions total A plus B, that duplicate delivery of either update does not add volume again, and that the bot does not submit the original Q a second time. Then test a cancellation or expiry with some volume already executed. The expected result is a real position for the filled part and no assumption that the remainder traded.
Run the same scenario for the account type you use. On netting accounts, a new deal may change the symbol's existing net exposure; on hedging accounts, the platform can keep multiple positions for that symbol. A position count alone therefore is not a reliable measure of how much the order filled.
For broader execution review, keep the bot's decision and order trail alongside a cBot decision log and a slippage journal. They answer different questions: what the bot intended, what the broker executed, and how the execution compared with its benchmark.
What this check cannot guarantee
A reconciliation loop cannot make an unfilled remainder execute or promise a particular price; an order can remain partly or wholly unexecuted when its terms cannot be met. It does make the bot's view auditable and helps prevent a second action from being based on an outdated assumption. Verify the actual order events, account type and position state in the cTrader version and broker environment you run. FINRA's trade-lifecycle overview describes the general partial-execution limitation for stock orders.