Delay Between Orders - Expert Advisor

 

Hello, greetings to everyone.
I'm new to metatrader 5 and been testing/programming some EA's. My last EA is based on Buy Limit Orders, scrapped from other EA's in the Code Base. I've been struggling with things like this and I would really appreciate if someone could shed some light on this to me: I would like to limit one order to each bar or put some kind of timer between each of them. 

Here is the code if you wanna test for yourself:

MqlDateTime horaatual;
input int         horaInicioAbertura=9;      //Inicio das Transações
input int         minutoInicioAbertura=30;    //Inicio das Transações
input int         horaFimAbertura=17;         //Ultima abertura de Transações
input int         minutoFimAbertura=0;        //Última abertura de Transações
input int         horaInicioFechamento=17;    //Fechamento
input int         minutoInicioFechamento=20;  //Fechamento
//---
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>  
#include <Trade\OrderInfo.mqh>
CPositionInfo  m_position;                   // trade position object
CTrade         m_trade;                      // trading object
CSymbolInfo    m_symbol;                     // symbol info object
COrderInfo     m_order;                      // pending orders object
//--- input parameters
input double   InpProfitClose    = 5;        // Profit purpose (in money)
input bool     InpBuyStop        = true;     // Use Buy stop
input bool     InpSellStop       = true;     // Use Sell stop
input int      InpMaxOrders      = 15;       // Maximum pending orders
input ushort   InpStopLoss       = 0;        // StopLoss ("0" -> off)
input ushort   InpTakeProfit     = 0;        // TakeProfit ("0" -> off)
input ushort   InpDistance       = 100;      // Distance from current price
input double   InpLots           = 0.1;      // Lots
input double   InpLotRatio       = 1.5;      // Lot Ratio
input ulong    m_magic=72994760;             // magic number
//---
ulong          m_slippage=10;                // slippage

double         ExtStopLoss=0.0;
double         ExtTakeProfit=0.0;
//---
bool           m_bln_close_all=false;        // "true" -> you must close all positions
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(InpLotRatio<=0.0)
     {
      string text=__FUNCTION__+", ERROR: "+"The parameter \"Lot Ratio\" can not be less than or equal to zero";
      Print(text);
      Alert(text);
      return(INIT_PARAMETERS_INCORRECT);
     }
//---
   if(!m_symbol.Name(Symbol())) // sets symbol name
      return(INIT_FAILED);
   RefreshRates();

   string err_text="";
   if(!CheckVolumeValue(InpLots,err_text))
     {
      Print(__FUNCTION__,", ERROR: ",err_text);
      return(INIT_PARAMETERS_INCORRECT);
     }
//---
   m_trade.SetExpertMagicNumber(m_magic);
//---
   if(IsFillingTypeAllowed(SYMBOL_FILLING_FOK))
      m_trade.SetTypeFilling(ORDER_FILLING_FOK);
   else if(IsFillingTypeAllowed(SYMBOL_FILLING_IOC))
      m_trade.SetTypeFilling(ORDER_FILLING_IOC);
   else
      m_trade.SetTypeFilling(ORDER_FILLING_RETURN);
//---
   m_trade.SetDeviationInPoints(m_slippage);
//--- 
   ExtStopLoss=InpStopLoss*m_symbol.Point();
   ExtTakeProfit=InpTakeProfit*m_symbol.Point();
//---
   m_bln_close_all=false;                    // "true" -> you must close all positions
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(m_bln_close_all)
     {
      CloseAllPositions();
      DeleteAllOrders();
      if(CalculateAllPositions()==0.0 && CalculateAllPendingOrders()==0.0)
         m_bln_close_all=false;
     }
//---
   double Profit=0.0;
   for(int i=PositionsTotal()-1;i>=0;i--)
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
            Profit+=m_position.Commission()+m_position.Swap()+m_position.Profit();
//---
   if(Profit>=InpProfitClose) // close all
     {
      m_bln_close_all=true;
      return;
     }
//---
   if(CalculateAllPendingOrders()!=0)
      return;
//---
   if(!RefreshRates())
      return;
   int StopsLevel=m_symbol.StopsLevel();
   if(StopsLevel==0)
      StopsLevel=m_symbol.Spread()*3;

   for(int i=1; i<=InpMaxOrders; i++)
     {
      if(InpDistance*i>StopsLevel)
        {
         double Lot=(i==1)?InpLots:LotCheck(InpLots*(double)(i-1)*InpLotRatio);
         if(Lot!=0.0)
           {
            if(InpBuyStop==true && NegociationTime()==true)
              {
               double Price=m_symbol.NormalizePrice(m_symbol.Bid()+(double)InpDistance*(double)i*m_symbol.Point());
               double sl=(InpStopLoss==0)?0.0:m_symbol.NormalizePrice(Price+ExtStopLoss);
               double tp=(InpTakeProfit==0)?0.0:m_symbol.NormalizePrice(Price-ExtTakeProfit);
               m_trade.SellLimit(Lot,Price,m_symbol.Name(),sl,tp);
              }
            if(InpSellStop==true && NegociationTime()==true)
              {
               double Price=m_symbol.NormalizePrice(m_symbol.Ask()-(double)InpDistance*(double)i*m_symbol.Point());
               double sl=(InpStopLoss==0)?0.0:m_symbol.NormalizePrice(Price-ExtStopLoss);
               double tp=(InpTakeProfit==0)?0.0:m_symbol.NormalizePrice(Price+ExtTakeProfit);
               m_trade.BuyLimit(Lot,Price,m_symbol.Name(),sl,tp);
              }
           }
        }
     }
//---
      if(CloseTime()==true)
         CloseAllPositions();
  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//---

  }
//+------------------------------------------------------------------+
//| Refreshes the symbol quotes data                                 |
//+------------------------------------------------------------------+
bool RefreshRates(void)
  {
//--- refresh rates
   if(!m_symbol.RefreshRates())
     {
      Print("RefreshRates error");
      return(false);
     }
//--- protection against the return value of "zero"
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
      return(false);
//---
   return(true);
  }
//+------------------------------------------------------------------+
//| Check the correctness of the order volume                        |
//+------------------------------------------------------------------+
bool CheckVolumeValue(double volume,string &error_description)
  {
//--- minimal allowed volume for trade operations
   double min_volume=m_symbol.LotsMin();
   if(volume<min_volume)
     {
      error_description=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);
      return(false);
     }
//--- maximal allowed volume of trade operations
   double max_volume=m_symbol.LotsMax();
   if(volume>max_volume)
     {
      error_description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume);
      return(false);
     }
//--- get minimal step of volume changing
   double volume_step=m_symbol.LotsStep();
   int ratio=(int)MathRound(volume/volume_step);
   if(MathAbs(ratio*volume_step-volume)>0.0000001)
     {
      error_description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",
                                     volume_step,ratio*volume_step);
      return(false);
     }
   error_description="Correct volume value";
   return(true);
  }
//+------------------------------------------------------------------+ 
//| Checks if the specified filling mode is allowed                  | 
//+------------------------------------------------------------------+ 
bool IsFillingTypeAllowed(int fill_type)
  {
//--- Obtain the value of the property that describes allowed filling modes 
   int filling=m_symbol.TradeFillFlags();
//--- Return true, if mode fill_type is allowed 
   return((filling & fill_type)==fill_type);
  }
//+------------------------------------------------------------------+
//| Lot Check                                                        |
//+------------------------------------------------------------------+
double LotCheck(double lots)
  {
//--- calculate maximum volume
   double volume=NormalizeDouble(lots,2);
   double stepvol=m_symbol.LotsStep();
   if(stepvol>0.0)
      volume=stepvol*MathFloor(volume/stepvol);
//---
   double minvol=m_symbol.LotsMin();
   if(volume<minvol)
      volume=0.0;
//---
   double maxvol=m_symbol.LotsMax();
   if(volume>maxvol)
      volume=maxvol;
   return(volume);
  }
//+------------------------------------------------------------------+
//| Close all positions                                              |
//+------------------------------------------------------------------+
void CloseAllPositions()
  {
   for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of current positions
      if(m_position.SelectByIndex(i))     // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
            m_trade.PositionClose(m_position.Ticket()); // close a position by the specified symbol
  }
//+------------------------------------------------------------------+
//| Calculate all positions                                          |
//+------------------------------------------------------------------+
int CalculateAllPositions()
  {
   int total=0;

   for(int i=PositionsTotal()-1;i>=0;i--)
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
            total++;
//---
   return(total);
  }
//+------------------------------------------------------------------+
//| Calculate all pending orders for symbol                          |
//+------------------------------------------------------------------+
int CalculateAllPendingOrders()
  {
   int total=0;

   for(int i=OrdersTotal()-1;i>=0;i--) // returns the number of current orders
      if(m_order.SelectByIndex(i))     // selects the pending order by index for further access to its properties
         if(m_order.Symbol()==m_symbol.Name() && m_order.Magic()==m_magic)
            total++;
//---
   return(total);
  }
//+------------------------------------------------------------------+
//| Delete all pending orders                                                    |
//+------------------------------------------------------------------+
void DeleteAllOrders()
  {
   for(int i=OrdersTotal()-1;i>=0;i--) // returns the number of current orders
      if(m_order.SelectByIndex(i))     // selects the pending order by index for further access to its properties
         if(m_order.Symbol()==m_symbol.Name() && m_order.Magic()==m_magic)
            m_trade.OrderDelete(m_order.Ticket());
  }
//+------------------------------------------------------------------+
bool CloseTime()
   {
      TimeToStruct(TimeCurrent(), horaatual);
      if(horaatual.hour>=horaInicioFechamento)
      {
         if(horaatual.hour==horaInicioFechamento)
            {
               if(horaatual.min>=minutoInicioFechamento)
                {
                  return true;
                }
               else
                {
                  return false;
                }
            }
      return true;
      }
      return false;   
   }
   
bool NegociationTime(){
      TimeToStruct(TimeCurrent(), horaatual);
      if(horaatual.hour>=horaInicioAbertura && horaatual.hour<=horaFimAbertura)
      {
         if(horaatual.hour==horaInicioAbertura)
            {
               if(horaatual.min>=minutoInicioAbertura)
               {
               return true;
               }
               else
               {
               return false;
               }
            }
            
         if(horaatual.hour==horaFimAbertura)
         {
            if(horaatual.min<=minutoFimAbertura)
            {
               return true;
            }
            else
            {
               return false;
            }
         }
      
      return true;
      }
   return false;
}   


Anyway, thanks in advance.

Files:
imagem.jpg  81 kb
 

In order to have only one position on one bar, it is necessary to remember the time of opening the bar when a position appears. For example, a pending order worked -> a position appeared -> you need to remember the time the bar opened.

Then compare this time (from memory) with the opening time of the current bar.

This is how the code will look.

//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//--- get transaction type as enumeration value
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- if transaction is result of addition of the transaction in history
   if(type==TRADE_TRANSACTION_DEAL_ADD)
     {
      long     deal_ticket       =0;
      long     deal_order        =0;
      long     deal_time         =0;
      long     deal_time_msc     =0;
      long     deal_type         =-1;
      long     deal_entry        =-1;
      long     deal_magic        =0;
      long     deal_reason       =-1;
      long     deal_position_id  =0;
      double   deal_volume       =0.0;
      double   deal_price        =0.0;
      double   deal_commission   =0.0;
      double   deal_swap         =0.0;
      double   deal_profit       =0.0;
      string   deal_symbol       ="";
      string   deal_comment      ="";
      string   deal_external_id  ="";
      if(HistoryDealSelect(trans.deal))
        {
         deal_ticket       =HistoryDealGetInteger(trans.deal,DEAL_TICKET);
         deal_order        =HistoryDealGetInteger(trans.deal,DEAL_ORDER);
         deal_time         =HistoryDealGetInteger(trans.deal,DEAL_TIME);
         deal_time_msc     =HistoryDealGetInteger(trans.deal,DEAL_TIME_MSC);
         deal_type         =HistoryDealGetInteger(trans.deal,DEAL_TYPE);
         deal_entry        =HistoryDealGetInteger(trans.deal,DEAL_ENTRY);
         deal_magic        =HistoryDealGetInteger(trans.deal,DEAL_MAGIC);
         deal_reason       =HistoryDealGetInteger(trans.deal,DEAL_REASON);
         deal_position_id  =HistoryDealGetInteger(trans.deal,DEAL_POSITION_ID);

         deal_volume       =HistoryDealGetDouble(trans.deal,DEAL_VOLUME);
         deal_price        =HistoryDealGetDouble(trans.deal,DEAL_PRICE);
         deal_commission   =HistoryDealGetDouble(trans.deal,DEAL_COMMISSION);
         deal_swap         =HistoryDealGetDouble(trans.deal,DEAL_SWAP);
         deal_profit       =HistoryDealGetDouble(trans.deal,DEAL_PROFIT);

         deal_symbol       =HistoryDealGetString(trans.deal,DEAL_SYMBOL);
         deal_comment      =HistoryDealGetString(trans.deal,DEAL_COMMENT);
         deal_external_id  =HistoryDealGetString(trans.deal,DEAL_EXTERNAL_ID);
        }
      else
         return;
      ENUM_DEAL_ENTRY enum_deal_entry=(ENUM_DEAL_ENTRY)deal_entry;
      if(deal_symbol==m_symbol.Name() && deal_magic==InpMagic)
        {
         if(deal_type==DEAL_TYPE_BUY || deal_type==DEAL_TYPE_SELL)
           {
            if(deal_entry==DEAL_ENTRY_IN)
              {
               m_time_last_IN=iTime(m_symbol.Name(),Period(),0);
              }
           }
        }
     }
  }


and filter:

//---
   if(Profit>=InpProfitClose) // close all
     {
      m_bln_close_all=true;
      return;
     }
//---
   if(m_time_last_IN==iTime(m_symbol.Name(),Period(),0))
      return;
//---
   if(CalculateAllPendingOrders()!=0)
      return;
//---
   if(!RefreshRates())
      return;
 
Vladimir Karputov:

In order to have only one position on one bar, it is necessary to remember the time of opening the bar when a position appears. For example, a pending order worked -> a position appeared -> you need to remember the time the bar opened.

Then compare this time (from memory) with the opening time of the current bar.

This is how the code will look.


and filter:

Got it to work. Many thanks to you, Vladimir.
 
I really needed this. Thanks