Pending Orders Issue

 

I have an EA which is supposed to place a pending order with the push of a button, & an execution price at the open of the current bar.

The button functions works perfectly, the parameters within the pending order work flawlessly, the dynamic pricing displayed in button which changed on every tick is perfect. 

However, when I push the button to initiate a pending order, sometimes nothing happens. It prints a "success" message into the Journal, but no Pending order appears in the ledger. Other times, it places a pending order with no problem.

Whenever I use this on a new chart, the prices are not updated either. The execution prices is some random price. I even changed the chart from the EURUSD to the EURJPY - completely different pricing structure, and it as telling me that the entry price on the pending order for the EURJPY was a price formatted to a 5 decimal place price.  I have tried refresh rates, but to no avail. See illustration for case in point.

  Incorrect Pricing in Ledger

Here is my coding, and I have also attached the files if you wanted to recreate this as well.

What am I missing here, what's needed to ensure that I can place a pending order without fail (providing it's within the brokers parametsrs).

//+------------------------------------------------------------------+
//|                                                         demo.mq4 |
//|                        Copyright 2022, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

#include <manStat.mqh>
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int      pendingExpiration          = Period() * 60;
double   candleOpenPrice            = iOpen(NULL,0,0);
double   pendingOrderExecPrice      = NormalizeDouble(candleOpenPrice,Digits); 
datetime candleOpenTime             = Time[0];
string   pendingError               = IntegerToString(GetLastError(),0);


int OnInit()
  {

   return(INIT_SUCCEEDED);
  }

void OnTick()
  {

   manualStaticButtons();


   
  }
  
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam){

   lastErrorCode = IntegerToString(GetLastError());
            
      if(id == CHARTEVENT_OBJECT_CLICK){
      
         if(sparam == "manBuy"){
         
            RefreshRates();
         
            if(!OrderSend(Symbol(),OP_BUYSTOP,1,pendingOrderExecPrice,0,0,0,NULL,1,candleOpenTime + pendingExpiration,clrNONE)){
                  
               Print("Error "+pendingError); 

            }
               
            else {
                     
               Print("Success");

            }
            
         }
         
         if(sparam == "manSell"){
         
            RefreshRates();
            
               if(!OrderSend(Symbol(),OP_SELLSTOP,LotSize,pendingOrderExecPrice,0,0,0,NULL,1,candleOpenTime + pendingExpiration,clrNONE)){
                                                                  
                  Print("Error "+pendingError);  
               
               } else {
                   
                   Print("Success");      
   
               }

         }
         
         
      }
  
}
//+------------------------------------------------------------------+
//|                                                      manStat.mqh |
//|                        Copyright 2022, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property strict

#include <global_declarations.mqh> 


void manualStaticButtons(){

double currentBid     =  MarketInfo(Symbol(),MODE_BID);
double currentAsk     =  MarketInfo(Symbol(),MODE_ASK);
double currentSpread  =  sqrt(MathPow((currentBid - currentAsk)/Point,2)); 

ObjectCreate(0,"manBuy",OBJ_BUTTON,0,0,0); 
        
   ObjectSetInteger(0,"manBuy",OBJPROP_XDISTANCE,880);
   
      ObjectSetInteger(0,"manBuy",OBJPROP_YDISTANCE,580);
      
         ObjectSetInteger(0,"manBuy", OBJPROP_YSIZE, 40);
         
            ObjectSetInteger(0,"manBuy", OBJPROP_XSIZE, 200);
      
               ObjectSetInteger(0,"manBuy", OBJPROP_CORNER,CORNER_LEFT_UPPER);
      
                  ObjectSetInteger(0,"manBuy", OBJPROP_COLOR,clrWhite);
                                                            
                     ObjectSetInteger(0,"manBuy", OBJPROP_FONTSIZE,10);
               
                        ObjectSetInteger(0,"manBuy", OBJPROP_BGCOLOR,clrGreen);
                        
                           ObjectSetString(0,"manBuy", OBJPROP_TEXT,"Market Order "+DoubleToString(currentBid,Digits)); 
                           
                              ObjectSetInteger(0,"manBuy",OBJPROP_STATE,false); 
                        
                           
                     
                     
ObjectCreate(0,"manSell",OBJ_BUTTON,0,0,0); 
        
   ObjectSetInteger(0,"manSell",OBJPROP_XDISTANCE,1150);
   
      ObjectSetInteger(0,"manSell",OBJPROP_YDISTANCE,580);
      
         ObjectSetInteger(0,"manSell", OBJPROP_YSIZE, 40);
         
            ObjectSetInteger(0,"manSell", OBJPROP_XSIZE, 200);
      
               ObjectSetInteger(0,"manSell", OBJPROP_CORNER,CORNER_LEFT_UPPER);
      
                  ObjectSetInteger(0,"manSell", OBJPROP_COLOR,clrWhite);
                                                            
                     ObjectSetInteger(0,"manSell", OBJPROP_FONTSIZE,10);
               
                        ObjectSetInteger(0,"manSell", OBJPROP_BGCOLOR,clrRed);
                        
                           ObjectSetString(0,"manSell", OBJPROP_TEXT,"Market Order "+DoubleToString(currentAsk,Digits));
                           
                              ObjectSetInteger(0,"manSell",OBJPROP_STATE,false); 
                               
                                              
ObjectCreate(0,"spread",OBJ_LABEL,0,0,0); 
        
   ObjectSetInteger(0,"spread",OBJPROP_XDISTANCE,1105);
   
      ObjectSetInteger(0,"spread",OBJPROP_YDISTANCE,585);
      
         ObjectSetInteger(0,"spread", OBJPROP_YSIZE, 40);
         
            ObjectSetInteger(0,"spread", OBJPROP_XSIZE, 60);
      
               ObjectSetInteger(0,"spread", OBJPROP_CORNER,CORNER_LEFT_UPPER);
      
                  ObjectSetInteger(0,"spread", OBJPROP_COLOR,clrBlack);
                                                            
                     ObjectSetInteger(0,"spread", OBJPROP_FONTSIZE,20);
               
                        ObjectSetString(0,"spread", OBJPROP_TEXT,DoubleToString(currentSpread,0)); 

}
Files:
demo.mq4  3 kb
demo.ex4  25 kb
manStat.mqh  4 kb
 

As I said...you should print your entry price to see if is correct

You have this price that you want to use for entry:

double   candleOpenPrice            = iOpen(NULL,0,0);
double   pendingOrderExecPrice      = NormalizeDouble(candleOpenPrice,Digits);

You initalize that price on the global area.

But I cannot see where do you update this price every candle?

Also, I would move this into OnInit()
manualStaticButtons()
 
Daniel Cioca #:

As I said...you should print your entry price to see if is correct

You have this price that you want to use for entry:

You initalize that price on the global area.

But I cannot see where do you update this price every candle?

Also, I would move this into OnInit()

Whatever you say. Please don't comment on my posts again. You're not helping.

 
TheHonestPrussian #: Whatever you say. Please don't comment on my posts again. You're not helping.

But he was helping and most of his post was valid. There was only one minor inconsistency but that is because your code makes it difficult to spot, but most of his suggestions were dead on.

So, I will only add details about the "inconsistency":

Your "manualStaticButtons" both creates the buttons and sets their text to the current market price.

Instead, create and set the properties of buttons only once, either on the fist tick or in OnInit() as already suggested. Then only update the buttons text, on a new tick.

So, before proceeding with further analysing your code, please consider making the changes already suggested first.

 
Fernando Carreiro #:

But he was helping and most of his post was valid. There was only one minor inconsistency but that is because your code makes it difficult to spot, but most of his suggestions were dead on.

So, I will only add details about the "inconsistency":

Your "manualStaticButtons" both creates the buttons and sets their text to the current market price.

Instead, create and set the properties of buttons only once, either on the fist tick or in OnInit() as already suggested. Then only update the buttons text, on a new tick.

So, before proceeding with further analysing your code, please consider making the changes already suggested first.

The buttons were not the focus of the question, it the lack of pending orders that was the focus of the question, he was also rambling on about why I was using pending orders in the first place. Sorry, but I'm not going to sit there all day and debate with someone over the justifiable uses of pending orders. I was getting pissed off enough as it was without someone questioning my rationale. If I wanted his opinion, I would have paid for his time as a consultant on the matter.    

In addition, I have hired a freelancer on here and the issue has now been sorted. 

 
TheHonestPrussian #: The buttons were not the focus of the question, it the lack of pending orders that was the focus of the question, he was also rambling on about why I was using pending orders in the first place. Sorry, but I'm not going to sit there all day and debate with someone over the justifiable uses of pending orders. I was getting pissed off enough as it was without someone questioning my rationale. If I wanted his opinion, I would have paid for his time as a consultant on the matter.  In addition, I have hired a freelancer on here and the issue has now been sorted. 
OK! As you wish!
 
TheHonestPrussian #:

The buttons were not the focus of the question, it the lack of pending orders that was the focus of the question, he was also rambling on about why I was using pending orders in the first place. Sorry, but I'm not going to sit there all day and debate with someone over the justifiable uses of pending orders. I was getting pissed off enough as it was without someone questioning my rationale. If I wanted his opinion, I would have paid for his time as a consultant on the matter.    

In addition, I have hired a freelancer on here and the issue has now been sorted. 

You asked for help here mate. That is what I tried  to do … that is what anybody is doing here… you choose whatever you need from all the answers … but is better that you know your limits so you hired somebody… Goodluck 

Also… this is NOT your post… it is a public forum… 


P.S.  By the way, is not like you are not getting any errors. You are getting errors when your orders are not placed, but you dont know how to show them. 
 
int      pendingExpiration          = Period() * 60;
double   candleOpenPrice            = iOpen(NULL,0,0);
double   pendingOrderExecPrice      = NormalizeDouble(candleOpenPrice,Digits); 
datetime candleOpenTime             = Time[0];
string   pendingError               = IntegerToString(GetLastError(),0);

Those are not assignments; they are initialization of a common (globally declared), or static variable with a constant. They work exactly the same way in MT4/MT5/C/C++.

  1. They are initialized once on program load.

  2. They don't update unless you assign to them.

  3. In C/C++ you can only initialize them with constants, and they default to zero. In MTx you should only initialize them with constants. There is no default in MT5, or MT4 with strict (which you should always use).

    MT4/MT5 actually compiles with non-constants, but the order that they are initialized is unspecified and Don't try to use any price (or indicator) or server related functions in OnInit (or on load or in OnTimer before you've received a tick), as there may be no connection/chart yet:

    1. Terminal starts.
    2. Indicators/EAs are loaded. Static and globally declared variables are initialized. (Do not depend on a specific order.)
    3. OnInit is called.
    4. For indicators OnCalculate is called with any existing history.
    5. Human may have to enter password, connection to server begins.
    6. New history is received, OnCalculate called again.
    7. A new tick is received, OnCalculate/OnTick is called. Now TickValue, TimeCurrent, account information and prices are valid.

  4. Unlike indicators, EAs are not reloaded on chart change, so you must reinitialize them, if necessary.
              external static variable - MQL4 programming forum #2 (2013)

Reason: