MT4 (MQL4): The Synchronous Wrapper
In MT4, the client terminal is locked to a single thread during execution. The most common cause of failed orders is ERR_TRADE_CONTEXT_BUSY (146), which happens when the terminal is busy processing another EA's request.
This wrapper verifies the position pool first, clears the terminal lock, attempts execution, and routes errors based on broker feedback.
Code: Select all
int ExecuteSafeOrder_MT4(string symbol, int cmd, double volume, double price, int slippage, double sl, double tp, int magic, string comment) {
int maxRetries = 3;
int delayMs = 500;
for(int attempt = 1; attempt <= maxRetries; attempt++) {
// 1. Idempotency Check: Did a previous timeout actually fill at the broker?
for(int i = 0; i < OrdersTotal(); i++) {
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
if(OrderSymbol() == symbol && OrderMagicNumber() == magic) {
PrintFormat("ABORT RETRY: Position already open for Magic %d", magic);
return OrderTicket(); // Successfully filled
}
}
}
// 2. Clear terminal locks & update pricing
while(IsTradeContextBusy()) Sleep(100);
RefreshRates();
// 3. Execution Attempt
int ticket = OrderSend(symbol, cmd, volume, price, slippage, sl, tp, comment, magic, 0, clrNONE);
if(ticket > 0) return ticket; // Execution Success
// 4. Error Routing
int err = GetLastError();
// Transient errors: Broker busy, Requote, Context busy, Timeout
if(err == 136 || err == 138 || err == 146 || err == 128) {
PrintFormat("Transient Error %d - Attempt %d/%d. Retrying...", err, attempt, maxRetries);
Sleep(delayMs + (MathRand() % 250)); // Exponential backoff with Jitter
delayMs *= 2;
} else {
// Terminal Errors: Not enough money (134), Invalid stops (130)
PrintFormat("Terminal Error %d - Aborting signal execution.", err);
break;
}
}
return -1;
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.