Issue with setting specific Buy and Sell time

 

Hi! 


So I have been trying to implement a simple strategy, which I plan to develop further. The first step should work as follows:

- buy at 23:30 and close at 00:05.


I used a simple "if" function with "Hour", "minute" and "seconds", however it does not open any positions.


Could you please help me with this?


Thanks ! 

int OnInit() 
   {
   Print("Version 1.0");

   return(INIT_SUCCEEDED);
   }        
 
void CheckForOpen()
{
   int res;
   Print ("InsideCheckForOpen");   
   if(Volume[0]>1) return;
   if(Hour()==23 && Minute()==30 && Seconds()==0)
   {
      res=OrderSend(Symbol(),OP_BUY,1,Ask,3,Ask-5000*Point,Ask+100000*Point,"SEMA",0,0,Blue);
      CloseSellPositions();
   }                          
   if(Hour()==0 && Minute()==05 && Seconds()==0)   
   {  
      res=OrderSend(Symbol(),OP_SELL,1,Bid,3,Ask+5000*Point,Ask-100000*Point,"SEMA",0,0,Blue);
      CloseBuyPositions();
   }
}      
void CloseBuyPositions()   
{ 
   int res;  
   for (int i=OrdersTotal()-1; i >= 0; i--)
   {    
      res=OrderSelect(i,SELECT_BY_POS,MODE_TRADES);      
      string CurrencyPair=OrderSymbol();
      if ((OrderType ()==OP_BUY)&& (_Symbol== CurrencyPair))       
      {
         res=OrderClose(OrderTicket(), OrderLots(),Bid,3,NULL);
         Print ("Pozycje Buy Zamknięte");
      }
   }
}  
void CloseSellPositions()   
{ 
   int res;  
   for (int i=OrdersTotal()-1; i >= 0; i--)
   {
      res=OrderSelect(i,SELECT_BY_POS,MODE_TRADES);      
      string CurrencyPair=OrderSymbol();   
      if ((OrderType ()==OP_SELL)&& (_Symbol== CurrencyPair))    
      {
         res=OrderClose(OrderTicket(), OrderLots(),Ask,3,NULL);
         Print ("Pozycje Sell Zamknięte");   
      } 
   }
} 

 
Sebastian Woźniczka:

Hi! 


So I have been trying to implement a simple strategy, which I plan to develop further. The first step should work as follows:

- buy at 23:30 and close at 00:05.


I used a simple "if" function with "Hour", "minute" and "seconds", however it does not open any positions.


Could you please help me with this?


Thanks ! 

Would be good if you post the complete code including the OnTick() so we can see how you are calling these and debug if necessary 
 
Due to the rest of the code missing I can only suggest going back to basics:

void OnTick()
  {
   if(Hour()==23 && Minute()==30 && Seconds()==0)
      {
      Print("It Works!")
      }
   }

If that works, it means the problem is somewhere in the OnTick function. Also Check if thee console doesn't print out any additional errors.
 
  1.    if(Volume[0]>1) return;

    For a new bar test, Bars is unreliable (a refresh/reconnect can change number of bars on chart), volume is unreliable (miss ticks), Price is unreliable (duplicate prices and The == operand. - MQL4 programming forum.) Always use time.
              MT4: New candle - MQL4 programming forum #3 (2014)
              MT5: Accessing variables - MQL4 programming forum #3 (2022)

    I disagree with making a new bar function, because it can only be called once per tick (second call returns false). A variable can be tested multiple times.
              Running EA once at the start of each bar - MQL4 programming forum (2011)

  2. res=OrderSend(Symbol(),OP_BUY,1,Ask,3,Ask-5000*Point,Ask+100000*Point,"SEMA",0,0,Blue);

    You buy at the Ask and sell at the Bid. Pending Buy Stop orders become market orders when hit by the Ask.

    1. Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid / OrderClosePrice reaches it. Using Ask±n, makes your SL shorter and your TP longer, by the spread. Don't you want the specified amount used in either direction?

    2. Your sell order's TP/SL (or Buy Stop's/Buy Limit's entry) will be triggered when the Ask / OrderClosePrice reaches it. To trigger close to a specific Bid price, add the average spread.
                MODE_SPREAD (Paul) - MQL4 programming forum - Page 3 #25

    3. The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools → Options (control+O) → charts → Show ask line.)
      Most brokers with variable spreads widen considerably at end of day (5 PM ET) ± 30 minutes. My GBPJPY shows average spread = 26 points, but average maximum spread = 134 (your broker will be similar).

  3.    if(Hour()==23 && Minute()==30 && Seconds()==0)
    What if there are no ticks during that specific second? Code fails. There can be minutes between ticks during the Asian session, use time.
    datetime tBegin = StringToTime("23:30"),
             tEnd   = StringToTime("00:05"),
             tNow   = TimeCurrent();
    if(     tNow >= tBegin){ trade(); }
    else if(tNow >= tEnd){   closeTrades(); }

  4. When dealing with time, a lot of people use strings; they can not be optimized. Using (int) seconds or (double) hours and minutes can be.

    See also Dealing with Time (Part 1): The Basics - MQL5 Articles (2021.10.01)
    Dealing with Time (Part 2): The Functions - MQL5 Articles (2021.10.08)

    int tBegin = 23*3600+30*60, // 23:30
        tEnd   =         05*,   // 00:05
        tNow   = time();
              date/time (2017)
              Find bar of the same time one day ago - MQL4 programming forum (2017)

 
William Roeder #:
  1. For a new bar test, Bars is unreliable (a refresh/reconnect can change number of bars on chart), volume is unreliable (miss ticks), Price is unreliable (duplicate prices and The == operand. - MQL4 programming forum.) Always use time.
              MT4: New candle - MQL4 programming forum #3 (2014)
              MT5: Accessing variables - MQL4 programming forum #3 (2022)

    I disagree with making a new bar function, because it can only be called once per tick (second call returns false). A variable can be tested multiple times.
              Running EA once at the start of each bar - MQL4 programming forum (2011)

  2. You buy at the Ask and sell at the Bid. Pending Buy Stop orders become market orders when hit by the Ask.

    1. Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid / OrderClosePrice reaches it. Using Ask±n, makes your SL shorter and your TP longer, by the spread. Don't you want the specified amount used in either direction?

    2. Your sell order's TP/SL (or Buy Stop's/Buy Limit's entry) will be triggered when the Ask / OrderClosePrice reaches it. To trigger close to a specific Bid price, add the average spread.
                MODE_SPREAD (Paul) - MQL4 programming forum - Page 3 #25

    3. The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools → Options (control+O) → charts → Show ask line.)
      Most brokers with variable spreads widen considerably at end of day (5 PM ET) ± 30 minutes. My GBPJPY shows average spread = 26 points, but average maximum spread = 134 (your broker will be similar).

  3. What if there are no ticks during that specific second? Code fails. There can be minutes between ticks during the Asian session, use time.
  4. When dealing with time, a lot of people use strings; they can not be optimized. Using (int) seconds or (double) hours and minutes can be.

    See also Dealing with Time (Part 1): The Basics - MQL5 Articles (2021.10.01)
    Dealing with Time (Part 2): The Functions - MQL5 Articles (2021.10.08)

              date/time (2017)
              Find bar of the same time one day ago - MQL4 programming forum (2017)

Thank you for your help! I implemented your advices and most of the code works correctly. It opens an order exactly at 23:30, however it does not modify the order at 00:05 as instructed. Instead the order is modified most of the times between 23:30 and 04:00.

Suprisingly, if I try to modify the order between midnight on the same day, like 23:55, it executes it perfectly. Am I missing something? 

double TakeProfit;
double LastHigh; 
double LastLow;

int OnInit() 
   {
   Print("Version 1.0");

   return(INIT_SUCCEEDED);
   }
   
int start()
  {  
  LastHigh = iHigh (NULL,0,1);
  LastLow = iLow(NULL,0,1);
  
  Print("Previous High/Low =" ,  iTime(NULL,0,1),",",
                                 iHigh(NULL, 0,1),",",
                                 iLow(NULL,0,1));
                                
   CheckForOpen();
   Print ("InsideStartAfterCheckForOpen");
   return (0);
   }

void CheckForOpen()
{
   int res;
   Print ("InsideCheckForOpen");   
   
   

datetime tBegin = StringToTime("23:30"),
         tEnd   = StringToTime("00:05"),
         tNow   = TimeCurrent();

   if (( tNow >= tBegin) && (OrdersTotal() < 1 ))
      {res=OrderSend(Symbol(),OP_BUY,1,Ask,3,Ask-5000*Point,TakeProfit,"SEMA",0,0,Blue); }

      for (int b= OrdersTotal()-1; b >= 0; b--)
      if(tNow >= tEnd)
      if (OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
      if (OrderSymbol() == Symbol())
      if (OrderType() == OP_BUY)
      if (tNow >= tEnd)
      {
         OrderModify (OrderTicket(),OrderOpenPrice(),OrderOpenPrice() - (1*_Point),OrderTakeProfit(),0,CLR_NONE);
         Print ("SL Przesuniety");
      }
 
         {
      if(Hour()==0 && Minute()==05 && Seconds()==0)
      {
      Print("It Works!");
      }
         }     
}
 
Sebastian Woźniczka #: Instead the order is modified most of the times between 23:30 and 04:00. Am I missing something? 
I wrote
if(     tNow >= tBegin){ trade(); }
else if(tNow >= tEnd){   closeTrades(); }
You wrote
if(     tNow >= tBegin){ trade(); 
                         closeTrades(); 
}
 
William Roeder #:
I wrote
You wrote

I think this answer is related to my first code, not the second one. In the second version I did not write "closeTrades". Instead, I followed your suggestiong with:

if(     tNow >= tBegin){ trade(); } (tBegin : 23:30)

then I wrote that if 

tNow >= tEnd) (tEnd : 00:05)

and if the open position is Long, then modify SL for this position.


The problem is, that whenever I choose to modify position after 00:00, it does not follow the instructions. If i set the modification time at 23:55, everything works perfectly. I apologise as it is certainly as rookie issue, but I do not know where the mistake in my code is, as everything seems to be coded corectly. 

 
Sebastian Woźniczka #:

The problem is, that whenever I choose to modify position after 00:00, it does not follow the instructions. If i set the modification time at 23:55, everything works perfectly. I apologise as it is certainly as rookie issue, but I do not know where the mistake in my code is, as everything seems to be coded corectly. 

Think about it.

tBegin=23:30

tEnd=00:05

So you are coding

if now >=23:30

  open orders

if now >=00:05

  modify orders

So at 23:30, it opens orders

Well, if the time is 23:30 then it is also >=00:05 so it will immediately modify the orders.

 
Keith Watford #:

Think about it.

tBegin=23:30

tEnd=00:05

So you are coding

if now >=23:30

  open orders

if now >=00:05

  modify orders

So at 23:30, it opens orders

Well, if the time is 23:30 then it is also >=00:05 so it will immediately modify the orders.

Ohhh yes it absolutely makes sense, thank you!

 
Sebastian Woźniczka #:

Ohhh yes it absolutely makes sense, thank you!

Hey guys! 

The code works, it opens a position between 00:05 - 00:10 am and modifies SL and TP between 1:05 - 1:10. 

However, in backtesting results i see, that sometimes it does not execute these rules properly (screenshot below in the "error" image).


Although first orders were executed properly (#1-3), #4 order was opened on "2022.01.11 at 00:05" but modified over a month later, on 02.21 at 01:05. 

Then again, #7 was opened and modified properly, buy #10 never modified SL. 


During these days when the strategy does not modify the position, I receive "error 130" notification. From what I have read online, it shows that the SL or TP price are too close to the currenct price of a security. Do not understand how this is possible, taking into the consideration the distance between where #7 was bought and when it hit SL at #8.


void CheckForOpen()
{
   int res;
   Print ("InsideCheckForOpen");   
datetime tStartBuy = StringToTime("00:05"),
         tEndBuy = StringToTime ("00:10"),
         tStartModify = StringToTime ("01:05"),
         tEndModify = StringToTime ("01:10"),
         tNow   = TimeCurrent();
   
if (( tNow >= tStartBuy) && (tNow <= tEndBuy) && (OrdersTotal() < 1 ))
      {res=OrderSend(Symbol(),OP_BUY,1,Ask,5,Ask-5000*Point,TakeProfit,"SEMA",0,0,Blue); }
      for (int b= OrdersTotal()-1; b >= 0; b--)
   if((tNow >= tStartModify) && (tNow <= tEndModify))     
      if (OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
      if (OrderSymbol() == Symbol())
      if (OrderType() == OP_BUY)
      {
         OrderModify (OrderTicket(),OrderOpenPrice(),OrderOpenPrice() - (100*_Point),OrderOpenPrice() - (1*_Point),0,CLR_NONE);
         Print ("SL Przesuniety");
      }
         {
      if(Hour()==0 && Minute()==05 && Seconds()==0)
      {
      Print("It Works!");
      }
         }     
}


 

Files:
error.PNG  59 kb
 
Sebastian Woźniczka #: I receive "error 130" notification. From what I have read online, it shows that the SL or TP price are too close to the currenct price of a security. Do not understand how this is possible, t
         OrderModify (OrderTicket(),OrderOpenPrice(),OrderOpenPrice() - (100*_Point),OrderOpenPrice() - (1*_Point),0,CLR_NONE);

You are setting the TP to be below the buy open price. That can only be done when the market (the Bid) is (2 … 99) points below the OOP. What don't you understand?

Reason: