Need Help with Buy/Sell Stop Orders in MQL5

 

Hi all,

I'm having trouble with stop orders in my MQL5 script and need some advice.

  1. Buy Stop Orders Not Executing: I've set a buy stop order, but it's not executing. The price goes over the order price multiple times, but the order never gets filled.

  2. Sell Stop Orders Executing Too Soon: On the other hand, my sell stop orders are executing right away on the next tick, even when the market price is nowhere near the order price. Or it get's pending like the buy stop, but at market price, but never get's executed.

Here's what I'm doing:

  • TRADE_ACTION_PENDING for the action
  • Using ORDER_TYPE_SELL_STOP and ORDER_TYPE_BUY_STOP
  • type_filling is ORDER_FILLING_RETURN
  • I've tried different settings for type_time, but the one that worked for the buy_stop order is ORDER_TIME_DAY
  • I use a Hedging mode account, i filled the correct data in the strategy tester , which is the m1 timeframe, and I want to trade in the WINFUT market, so it's BRL.
  • I'm currently using only the demo account, and this issue is only in the strategy tester , since I did not tested it in the live mode.
  • I tested the one click trading, and it works perfectly, which leads me to believe I did something wrong in the Strategy Tester, or my broker (XP INVESTIMENTOS) has some rules that are leading to this issue.

I've checked my code but can't figure out why this is happening, as I'm quite new to mql5, so the code is quite simple as well. Can anyone spot what I might be doing wrong or give some tips? Here's my code (it's just a code to test sending different types of order, later I will improve it to manage orders/positions):



#define EXPERT_MAGIC 123456  

MqlTradeResult result = {};
MqlTradeCheckResult reqCheck = {};
MqlTradeRequest request = {};
bool blockPrint = false;
int numberOfCurrentOrders = 0;
int numberOfCurrentPositions = 0;
int BarsCount = 0;
double ask, bid;
input ENUM_TRADE_REQUEST_ACTIONS action = TRADE_ACTION_PENDING;
input ENUM_ORDER_TYPE orderType = ORDER_TYPE_BUY_STOP;
input ENUM_ORDER_TYPE_FILLING filling = ORDER_FILLING_RETURN;
input ENUM_ORDER_TYPE_TIME timeType = ORDER_TIME_DAY;
                           
#include <Trade\Trade.mqh>
#include <Trade\OrderInfo.mqh>
#include <Trade\HistoryOrderInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\DealInfo.mqh>

CTrade trade;  // Trade object for performing trade operations
COrderInfo         orderInfo;
CHistoryOrderInfo  historyOrderInfo;
CPositionInfo      positionInfo;
CDealInfo          dealInfo;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
//---
   BarsCount = Bars(_Symbol, PERIOD_CURRENT);
   ZeroMemory(request);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

   if((Bars(_Symbol, PERIOD_CURRENT) - BarsCount) == 0)
     {
      return;
     }
   
   if(!blockPrint){
    PlaceOrder();
   }
   
   getAndCheckTrades();
    
   Comment(StringFormat("Show prices\nAsk = %G\nBid = %G", ask, bid));
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void PlaceOrder()
  {
   int offset = 150;                                                   
   double price;                                                    
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);             
   int digits = SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);          
   
   if(orderType==ORDER_TYPE_BUY_STOP)
     {
      request.type =ORDER_TYPE_BUY_STOP;                                // order type
      price        =SymbolInfoDouble(Symbol(),SYMBOL_ASK)+offset*point; // price for opening 
      request.price=NormalizeDouble(price,digits);                      // normalized opening price 
     }
   else if(orderType==ORDER_TYPE_SELL_STOP)
     {
      request.type     =ORDER_TYPE_SELL_STOP;                           // order type
      price=SymbolInfoDouble(Symbol(),SYMBOL_ASK)-offset*point;         // price for opening 
      request.price    =NormalizeDouble(price,digits);                  // normalized opening price 
     }
     
   request.symbol = _Symbol;
   request.volume = 1.0;
   request.deviation = 30;
   request.type_filling = filling;
   request.type_time = timeType;
   request.action = action;
   
   if(!OrderSend(request, result)){
      PrintFormat("OrderSend error %d", GetLastError());
      return ;  
   }           
   PrintFormat("retcode=%u  deal=%I64u  order=%I64u", result.retcode, result.deal, result.order);
  }
  


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void getAndCheckTrades()
  {
   if(OrdersTotal() != numberOfCurrentOrders || PositionsTotal() != numberOfCurrentPositions)
     {
      blockPrint = false;
      numberOfCurrentOrders = OrdersTotal();
      numberOfCurrentPositions = PositionsTotal();
      Print("Change in position or orders detected!");
     }

   if(HasOpenTrades() && !blockPrint)
     {
      PrintPositions(positionInfo);
      PrintOrders(orderInfo);
      blockPrint = true;
     }
  } ;


//+------------------------------------------------------------------+
bool HasOpenTrades()
  {
   return (PositionsTotal() > 0 || OrdersTotal() > 0);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void PrintPositions(CPositionInfo &positionInfo)
  {
   Print("=== Open Positions ===");
   for(int i = 0; i < PositionsTotal(); i++)
     {
      if(positionInfo.SelectByIndex(i))
        {
         Print("Position Ticket: ", positionInfo.Ticket());
         Print("Symbol: ", positionInfo.Symbol());
         Print("Type: ", positionInfo.TypeDescription());
         Print("Volume: ", positionInfo.Volume());
         Print("Open Price: ", positionInfo.PriceOpen());
         Print("Current Price: ", positionInfo.PriceCurrent());
         Print("Stop Loss: ", positionInfo.StopLoss());
         Print("Take Profit: ", positionInfo.TakeProfit());
         Print("Opening Time: ", TimeToString(positionInfo.Time()));
         Print("Last Update Time: ", TimeToString(positionInfo.TimeUpdate()));
         Print("Commission: ", positionInfo.Commission());
         Print("Swap: ", positionInfo.Swap());
         Print("Profit: ", positionInfo.Profit());
         Print("Magic Number: ", positionInfo.Magic());
         Print("Position Identifier: ", positionInfo.Identifier());
         Print("Comment: ", positionInfo.Comment());
         Print("-------------------------------");
        }
     }
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void PrintOrders(COrderInfo &orderInfo)
  {
   Print("=== Orders ===");
   for(int i = 0; i < OrdersTotal(); i++)
     {
      if(orderInfo.SelectByIndex(i))
        {
         Print("Order Ticket: ", orderInfo.Ticket());
         Print("Symbol: ", orderInfo.Symbol());
         Print("Order Type: ", EnumToString((ENUM_ORDER_TYPE)orderInfo.OrderType()));
         Print("State: ", orderInfo.StateDescription());
         Print("Initial Volume: ", orderInfo.VolumeInitial());
         Print("Current Volume: ", orderInfo.VolumeCurrent());
         Print("Open Price: ", orderInfo.PriceOpen());
         Print("Stop Loss: ", orderInfo.StopLoss());
         Print("Take Profit: ", orderInfo.TakeProfit());
         Print("Current Price: ", orderInfo.PriceCurrent());
         Print("Stop Limit Price: ", orderInfo.PriceStopLimit());
         Print("Order Placement Time: ", TimeToString(orderInfo.TimeSetup()));
         Print("Order Placement Time (ms): ", orderInfo.TimeSetupMsc());
         Print("Expiration Time: ", TimeToString(orderInfo.TimeExpiration()));
         Print("Execution/Cancellation Time: ", TimeToString(orderInfo.TimeDone()));
         Print("Execution/Cancellation Time (ms): ", orderInfo.TimeDoneMsc());
         Print("Type Filling: ", orderInfo.TypeFillingDescription());
         Print("Type Time: ", orderInfo.TypeTimeDescription());
         Print("Magic Number: ", orderInfo.Magic());
         Print("Position ID: ", orderInfo.PositionId());
         Print("Comment: ", orderInfo.Comment());
         Print("-------------------------------");
        }
     }
  }


Thanks for any help!

Files:
buystop1.png  67 kb
buystop2.png  93 kb
buystop3.png  6 kb
sellstop1.png  82 kb