- CTrade - BuyLimit
- CTrade - SellLimit
- Common Functions - PlaySound
When you operate too close (or without any gap at all) to actual price or freeze level it can be easily hit, because ask or bid price can change a bit just at the same time as you send or delete your order.
I think adding at least 1 spread to the freeze distance could solve your issue.
Stanislav,
Try below code (make sure you place a freeze level in your symbol config for backtest). It will still throw an error (for buy limits only) no matter how big you make the 0.2 offset.
I am well familiar with the considerations for Stops and Freeze levels as indicated in https://book.mql4.com/appendix/limits. I also believe that based on this information TP and SL are irrelevant when deleting a pending order (only price level is relevant, as the order has not yet been triggered)
This statement is also corroborated by the example given by MQL5 on how to deal with freezelevels in regards to deleting orders (https://www.mql5.com/en/articles/2555#modify_in_freeze_level_prohibited)
Bottom line is that when the ask is not within freeze level distance from the open price of the Buy Limit, the order should be able to be deleted. For Buy Limits, this is however not the case.
#include <Trade/Trade.mqh> int OnInit() { Sleep(300000); CTrade trade(); trade.BuyLimit(1,SymbolInfoDouble(_Symbol,SYMBOL_ASK)-0.2,_Symbol,0,0); // place buy limit with SL=0 and TP=0 trade.SellLimit(1,SymbolInfoDouble(_Symbol,SYMBOL_BID)+0.2,_Symbol,0,0); // place sell limit with SL=0 and TP=0 trade.OrderDelete(OrderGetTicket(0)); // Delete buy limit trade.OrderDelete(OrderGetTicket(1)); // Delete sell limit return(INIT_SUCCEEDED); }
- 2016.08.01
- www.mql5.com
You did not specify neither work symbol nor its actual properties.
Also I prefer not to work the library of standard classes, especially during bug proofing in the API (because the library can interfere somehow).
Finally, your code doesn't contain price normalization, which is required if you're using API directly or via STL. You can omit it only if you're using other framework, which does this step internally for you (like it is in the algotrading book, for example).
Hi Stanislav,
Symbol can be any symbol (e.g. 'EURUSD'); to test the example it is required though to change the 'freezelevel' parameter to anything other than zero.
Normalization does not have any impact on the outcome nor the issue (I do agree that I should have included that in the example).
Lastly; yes I am using CTrade however, all that CTrade::OrderDelete function does is execute the request.action=TRADE_ACTION_REMOVE with the ticket number in request.order = order_ticket (so it is doing nothing different than what 'OrderSend' would normally execute, as per https://www.mql5.com/en/docs/constants/structures/mqltraderequest).
Any clue? Do you need more info to replicate the issue at hand?
Thanks for looking in to this!
- www.mql5.com
Normalization does not have any impact on the outcome nor the issue (I do agree that I should have included that in the example).
Lastly; yes I am using CTrade however, all that CTrade::OrderDelete function does is execute the request.action=TRADE_ACTION_REMOVE with the ticket number in request.order = order_ticket (so it is doing nothing different than what 'OrderSend' would normally execute, as per https://www.mql5.com/en/docs/constants/structures/mqltraderequest).
Any clue? Do you need more info to replicate the issue at hand?
Usually omitted normalization leads to exact the same error as you mentioned ("invalid stops"). Of course, [non]normalization issue applies only to the phase of setting an order, not deleting it, but in your original post you included this phase as well (or I misunderstood you), and provided the source code without normlization. Hence you literally invite the errors of this kind.
If you say that changing freeze level is available for you, then I suppose the question is specifically about tester, and not about online trading?
trade.OrderDelete(OrderGetTicket(0)); // Delete buy limit trade.OrderDelete(OrderGetTicket(1)); // Delete sell limit
I don't know much about MQL5 trading API, but this is very questionable code. Because it would be logical if deleting an order would change the indices of the remaining orders in the order list. I decided to test this by printing the tickets you pass to trade.OrderDelete(). I intentionally left all your code unchanged; I only added ticket printing.
#include <Trade/Trade.mqh> CTrade trade(); void OnStart() { trade.BuyLimit(1,SymbolInfoDouble(_Symbol,SYMBOL_ASK)-0.2,_Symbol,0,0); // place buy limit with SL=0 and TP=0 trade.SellLimit(1,SymbolInfoDouble(_Symbol,SYMBOL_BID)+0.2,_Symbol,0,0); // place sell limit with SL=0 and TP=0 deleteOrder(OrderGetTicket(0)); // Delete buy limit deleteOrder(OrderGetTicket(1)); // Delete sell limit } void deleteOrder(const ulong ticket) { Print("Attempting to delete order #", ticket); trade.OrderDelete(ticket); }

2025.10.20 08:58:14.119 Scripts script test2 (EURUSD,M1) loaded successfully 2025.10.20 08:58:14.120 Trades '93066966': buy limit 1 EURUSD at 0.96551 2025.10.20 08:58:14.222 Trades '93066966': accepted buy limit 1 EURUSD at 0.96551 2025.10.20 08:58:14.222 Trades '93066966': order #5166532419 buy limit 1 / 1 EURUSD at 0.96551 done in 102.336 ms 2025.10.20 08:58:14.223 Trades '93066966': sell limit 1 EURUSD at 1.36550 2025.10.20 08:58:14.319 Trades '93066966': accepted sell limit 1 EURUSD at 1.36550 2025.10.20 08:58:14.319 Trades '93066966': order #5166532432 sell limit 1 / 1 EURUSD at 1.36550 done in 96.268 ms 2025.10.20 08:58:14.319 Trades '93066966': cancel order #5166532419 buy limit 1 EURUSD at 0.96551 2025.10.20 08:58:14.389 Trades '93066966': accepted cancel order #5166532419 buy 0 at market 2025.10.20 08:58:14.389 Trades '93066966': cancel #5166532419 buy limit 1 EURUSD at market done in 70.107 ms 2025.10.20 08:58:14.389 Trades '93066966': failed cancel order #0 buy 0 at market [Invalid request] 2025.10.20 08:58:14.389 Scripts script test2 (EURUSD,M1) removed
Hi Stanislav,
Symbol can be any symbol (e.g. 'EURUSD'); to test the example it is required though to change the 'freezelevel' parameter to anything other than zero.
Normalization does not have any impact on the outcome nor the issue (I do agree that I should have included that in the example).
Lastly; yes I am using CTrade however, all that CTrade::OrderDelete function does is execute the request.action=TRADE_ACTION_REMOVE with the ticket number in request.order = order_ticket (so it is doing nothing different than what 'OrderSend' would normally execute, as per https://www.mql5.com/en/docs/constants/structures/mqltraderequest).
Any clue? Do you need more info to replicate the issue at hand?
Thanks for looking in to this!
Please see below for corrected code. It does not change the issue (I acknowledge the orderticket was a blunder).

#include <Trade/Trade.mqh> //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { Sleep(300000); // to start past 'market close' CTrade trade(); // initiate trade class double buyPrice = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK)-0.2,_Digits); double sellPrice = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID)+0.2,_Digits); trade.BuyLimit(1,buyPrice,_Symbol,0,0); // place buy limit with SL=0 and TP=0 trade.SellLimit(1,sellPrice,_Symbol,0,0); // place sell limit with SL=0 and TP=0 CancelAllPendingOrders(); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CancelAllPendingOrders() { int ord_total=OrdersTotal(); if(ord_total) { CTrade trade(); for(int i=ord_total-1; i>=0; i--) { ulong ticket=OrderGetTicket(i); trade.OrderDelete(ticket); } } }
Yes, I can confirm the bug (with a non-removable buy limit order far away from freeze level), at least for the tester, probably it will work normally online (I can't find a real symbol with freeze level specified).
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use