Your strategy level and your market execution price need separate variables. My MT4 run passed 3 local price checks and accepted current Ask, while a deliberately fractional request failed. The returned error was 4107. I did not reproduce error 129.
An old MQL4 question shows the distinction well. A trader had Bid at 104.323 and Ask at 104.355, then tried a SELL at 104.326. The value had three decimal places. The code refreshed prices and allowed slippage. The remaining question was where that requested price came from: a pivot level used by the strategy.
That is a useful debugging question even when your own error number differs. Find the assignment that produced the submitted value before changing the entry rule.
Before: the trigger level travels into OrderSend
This reduced example illustrates the mistake. It is not the original trader's complete code.
double requested = NormalizeDouble(triggerLevel, Digits);
int ticket = OrderSend(Symbol(), OP_SELL, lots,
requested, 10, 0, 0);
triggerLevel may explain why the strategy wants to enter. It does not establish the current price for a market SELL. If the requirement is to enter only at a specified future price, define the appropriate pending-order behaviour separately.
The official OrderSend reference says market BUY requests use Ask and market SELL requests use Bid. It also distinguishes invalid prices, outdated prices and slippage handling. Adding a larger slippage value does not establish that your calculated level is a valid requested market price.
After: take a fresh quote and retain the actual result
For the chart symbol, separate the signal decision from the request value:
RefreshRates();
double requested = NormalizeDouble(Bid, Digits);
ResetLastError();
int ticket = OrderSend(Symbol(), OP_SELL, lots,
requested, 10, 0, 0);
int sendError = ticket < 0 ? GetLastError() : 0;
Print("price=", DoubleToString(requested, Digits),
" ticket=", ticket, " error=", sendError);
This is a small request-path example, not a complete EA. A different traded symbol requires that symbol's quote and precision. Capture the values close to submission. A chart screenshot taken later cannot tell you what the earlier request contained.
What the native test actually showed
I used MT4 build 1491 and the existing EURUSD H4 Strategy Tester environment. The test EA refuses initialization outside the tester. The native compiler reported zero errors and warnings.
The local price guard had three cases: reject zero, reject a fractional-point value and accept current Ask. All three passed. Those are local validation results, not invented trade-server responses.
The first simulated BUY requested 1.2054370. It returned ticket -1 and error 4107. The next request used refreshed, normalized Ask at 1.2054. It opened simulated ticket 1 with error 0. Reading that ticket back confirmed the opening price, and simulated cleanup succeeded.
The retained native log includes the actual error and the ticket-price comparison. The earlier attempt expecting 129 remains in the proof package. I changed the claim to match the result, rather than relabelling 4107 as the number I had hoped to reproduce.
Your five-minute check
Choose one failed request. Put its symbol, order type, submitted price, Bid, Ask, timestamp and immediately captured error on one line. Then trace the submitted price back to its assignment. Was it a quote, a stored quote or the level that triggered the strategy?
Keep that trace when you compare the next request. Otherwise, a successful retry may hide which input actually changed. My stance is simple: preserve the failed request before making the next one look cleaner.
This test sent zero account orders. It did not reproduce server error 129 or prove that a broker would accept the next request. The useful result is the separation between a signal level, a local check and an observed execution response.
For a small source check, Free EA Code Check starts with the readable code and one expected result.

Top comments (0)