Bug with placing orders in MT5 Build 2340 - both with CTrade and with OrderSend()

 

Hi there


Last night I dedcided to code up an EA after dinner. When I opened MT5 it asked to update to the newest release version (2340), and so I let it update.

I noticed that both CTrade.Buy() and OrderSend() were suddenly refusing to place orders in certain cases, they were complaining about either an invalid stop or an invalid target.

I decided to make sure that it wasn't a coding error on my side, and so I re-ran a backtest of an EA that I had successfully run a few days ago. This EA was also refusing to place orders.


I coded up some code to show this behaviour, it is below. What I noticed is that this only seems to happy with fairly tight stop levels e.g. 10 pips. I've attached the relevant log file from the Strategy Tester to show this behaviour, as well as a screenshot of EURUSD with these levels drawn in and a light-gray line over the bar I was testing on.

//+------------------------------------------------------------------+
//|                                        CTrade Issue Showcase.mq5 |
//|                                    Copyright 2020, Scott Edwards |
//|                                                scottedwards.tech |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, Scott Edwards"
#property link      "scottedwards.tech"
#property version   "1.00"

#include <Trade\Trade.mqh>

CTrade _cTrade;

bool _atLeastOneOrderPlaced = false;

int OnInit()
{
   if(_Symbol != "EURUSD" || _Period != PERIOD_H1)
   {
      Alert("Wrong symbol/period");
      return INIT_FAILED;
   }
   
   _cTrade.SetExpertMagicNumber(1234);
   _cTrade.SetDeviationInPoints(0);
   _cTrade.SetTypeFilling(ORDER_FILLING_IOC);
   _cTrade.SetAsyncMode(false);
   
   return INIT_SUCCEEDED;
}

void OnDeinit(const int reason)
{

}

void OnTick()
{
   if(_atLeastOneOrderPlaced)
   {
      return;
   }
   
   Print("\n");
   Print("Placing CTrade Orders...");
   PlaceAnOrderWithCTrade(10);
   PlaceAnOrderWithCTrade(20);
   PlaceAnOrderWithCTrade(30);
   PlaceAnOrderWithCTrade(40);
   PlaceAnOrderWithCTrade(50);
   
   Print("\n");
   Print("Placing OrderSend() Orders...");
   PlaceAnOrderWithOrderSend(10);
   PlaceAnOrderWithOrderSend(20);
   PlaceAnOrderWithOrderSend(30);
   PlaceAnOrderWithOrderSend(40);
   PlaceAnOrderWithOrderSend(50);
   
   _atLeastOneOrderPlaced = true;
}

void PlaceAnOrderWithCTrade(int pipRange)
{
   // This is just used for debugging purposes
   datetime now = TimeCurrent();
   
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   
   double pipsToOffetStopLossandTakeProfit = pipRange * 0.0001;
   
   double sl = ask - pipsToOffetStopLossandTakeProfit;
   double tp = ask + pipsToOffetStopLossandTakeProfit;
   
   // Normalize to make sure that this is not the root of the issue
   int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
   sl = NormalizeDouble(sl, digits);
   tp = NormalizeDouble(tp, digits);
   
   Print("\n");
   Print("Placing CTrade order for input of ", pipRange, " pips.");
   Print("Current datetime: ", now);
   Print("Ask: ", ask);
   Print("SL: ", sl);
   Print("TP: ", tp);
   
   // Note: this doesn't work with OrderSend() either
   _cTrade.Buy(0.01, _Symbol, 0, sl, tp, NULL);
}

void PlaceAnOrderWithOrderSend(int pipRange)
{
   // This is just used for debugging purposes
   datetime now = TimeCurrent();
   
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   
   double pipsToOffetStopLossandTakeProfit = pipRange * 0.0001;
   
   double sl = ask - pipsToOffetStopLossandTakeProfit;
   double tp = ask + pipsToOffetStopLossandTakeProfit;
   
   long digits = SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
   MqlTradeRequest mrequest;
   ZeroMemory(mrequest);
   mrequest.action = TRADE_ACTION_DEAL;
   mrequest.price = NormalizeDouble(ask, (int)digits);
   mrequest.type = ORDER_TYPE_BUY;
   mrequest.sl = sl;
   mrequest.tp = tp;
   mrequest.symbol = _Symbol;
   mrequest.volume = 0.01;
   mrequest.magic = 4321;
   mrequest.type_filling = ORDER_FILLING_IOC;
   mrequest.deviation=0;
   
   Print("\n");
   Print("Placing OrderSend() order for input of ", pipRange, " pips.");
   Print("Current datetime: ", now);
   Print("Ask: ", ask);
   Print("SL: ", sl);
   Print("TP: ", tp);
   
   MqlTradeResult mresult;
   bool result = OrderSend(mrequest, mresult);
}
 

Sorry, I hit the Post button by mistake in the original post, please find the logs attached and a screenshot below.

MT5 Screenshot

 

I drove your adviser on the MetaQuotes-Demo server - there are no errors.

I think your problem is here: you do not take into account the current spread, Freeze Level and Stops Level.

 

Hi Vladimir Karputov 

I just did the same, and also had no errors. I will look at the items you recommended I look at.

Thank you for your help!

 

As I said - you are not doing the necessary checks.

My code is:

void PlaceAnOrderWithCTrade(int pipRange)
  {
// This is just used for debugging purposes
   datetime now = TimeCurrent();

   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

   double point=SymbolInfoDouble(Symbol(), SYMBOL_POINT);
   double freeze_level=SymbolInfoInteger(Symbol(),SYMBOL_TRADE_FREEZE_LEVEL)*point;
   double stop_level=SymbolInfoInteger(Symbol(),SYMBOL_TRADE_STOPS_LEVEL)*point;

   Print("Point: ",point,", Freeze level: ",freeze_level,", Stops level: ",stop_level);



   double pipsToOffetStopLossandTakeProfit = pipRange * 0.0001;

result:

2019.02.01 00:00:00   Placing CTrade Orders...
2019.02.01 00:00:00   Point: 1e-05, Freeze level: 0.0, Stops level: 0.0012
2019.02.01 00:00:00   
2019.02.01 00:00:00   
2019.02.01 00:00:00   Placing CTrade order for input of 10 pips.
2019.02.01 00:00:00   Current datetime: 2019.02.01 00:00:00
2019.02.01 00:00:00   Ask: 1.14467
2019.02.01 00:00:00   SL: 1.14367
2019.02.01 00:00:00   TP: 1.14567
2019.02.01 00:00:00   failed market buy 0.01 EURUSD sl: 1.14367 tp: 1.14567 [Invalid stops]
2019.02.01 00:00:00   CTrade::OrderSend: market buy 0.01 EURUSD sl: 1.14367 tp: 1.14567 [invalid stops]


Ask (1.14467) - SL (1.14367) = 0.0001.

0.001 < Stops level (0.0012)


I use the function in all my codes FreezeStopsLevels(double &level)
 
It's very kind of you to post your code examples, thank you very much!
Reason: