Your bot can receive a result without a fill. My MT5 run passed 3 synthetic return-code checks and sent zero orders. I keep rejection, placement and completion separate before considering another request.
A trader asked how to check a failed Python order and send it again. The thread reported return code 10006. The journal did not give the trader a useful cause. The request included a market order, stop loss and take profit.
The useful next step is to retain the request and returned result together. An error number alone cannot tell you whether changing a price, stop distance or filling mode addresses this particular failure.
Before: one label hides three states
This reduced logging pattern loses the distinction a retry decision needs:
Print("order result received");
Receiving a result and filling a trade are different events. A log that collapses them leaves the next attempt without a clear starting state.
The official Python order_send reference returns a trade-result structure. Its request field contains the submitted request. The example expands both structures with _asdict(). Keep that detail rather than reducing the result to one short string.
After: preserve distinct local states
I used this small original classifier in a native MT5 script:
string Classify(uint code) {
if(code==TRADE_RETCODE_REJECT) return "REJECTED_REASON_UNKNOWN";
if(code==TRADE_RETCODE_DONE) return "COMPLETED_RECONCILE_DEAL";
if(code==TRADE_RETCODE_PLACED) return "PLACED_NOT_FILLED";
return "UNCLASSIFIED_RECONCILE";
}
The classifier takes a number and returns a label. It does not send an order or choose a retry. The unknown branch matters too. A new code must remain visible instead of falling through to a success label.
The native result
The script supplied three fixed inputs. The runtime receipt retained these outputs:
| Synthetic input | Local classification |
|---|---|
| 10006 | REJECTED_REASON_UNKNOWN |
| 10009 | COMPLETED_RECONCILE_DEAL |
| 10008 | PLACED_NOT_FILLED |
All three comparisons passed. The native run recorded orders_sent=0 and server_reject_reproduced=false. The EURUSD chart was the capture surface. It was not a trade in this test.
The result supports one narrow claim: the local classifier kept those three chosen values separate. It establishes no broker cause, server rejection or complete execution state machine.
Keep the receipt before choosing another attempt
For one real failed request, retain the original symbol, volume, order type, requested prices and timestamp. Keep the returned code, comment, order and deal fields beside it. If an external return code is present, retain that too. A local attempt identifier helps join later order and deal records without confusing a trading intent with a new submission.
Then compare the relevant order, deal and position state for the operation you requested. A placed order and a completed request need different handling. Even completion needs reconciliation with the corresponding account record.
The official OrderSend reference explains why a true function return alone does not establish a completed market trade. A retry loop should not turn missing information into a second entry.
Open one rejected request and compare its returned code, comment, order and deal fields with its original request and timestamp. If your log saved only a label, improve that receipt first. If the reason is missing, keep it unknown.
The original native proof and its boundaries are on the FIX-15 page.
If your first receipt loses these fields, check that logging change with one rejected, one placed and one completed example before enabling any automatic retry.
For a bounded source review, Free EA Code Check begins with readable code and one expected result.

Top comments (0)