Sleep timer causes different results...so why have it?

 

Hi all

Fairly new to this and I've been working on an EA, and I needed a trading-session piece of code, which I found in the forums and copied in, but it has a sleep timer in it of 2000ms (which actually backtests the highest/best results).

When I backtest and optimise that sleep timer value (from 0 to 5000 step 1000), I get different results from most of the metrics.  I added a Print output and noticed that it was, as expected, only running the trade decisions every 2 seconds (or whatever the optimised value is). 

The sleep code is immediately after the OnTick() and I'm trying to get my head around why you'd want that sleep timer in the EA...for either backtesting or for live trading.  Wondering what the implications are in a live environment...

Can anyone shed any thoughts?

void OnTick()
  {
     Sleep(2000);
... rest of code ...

Thanks

Tim 

Testing trading strategies on real ticks
Testing trading strategies on real ticks
  • www.mql5.com
The article provides the results of testing a simple trading strategy in three modes: "1 minute OHLC", "Every tick" and "Every tick based on real ticks" using actual historical data.
 
timelleston:

Hi all

Fairly new to this and I've been working on an EA, and I needed a trading-session piece of code, which I found in the forums and copied in, but it has a sleep timer in it of 2000ms (which actually backtests the highest/best results).

When I backtest and optimise that sleep timer value (from 0 to 5000 step 1000), I get different results from most of the metrics.  I added a Print output and noticed that it was, as expected, only running the trade decisions every 2 seconds (or whatever the optimised value is). 

The sleep code is immediately after the OnTick() and I'm trying to get my head around why you'd want that sleep timer in the EA...for either backtesting or for live trading.  Wondering what the implications are in a live environment...

Can anyone shed any thoughts?


Thanks

Tim 

The sleep alone inside OnTick you posted would do nothing other than make the test slower.

Post the full code.
 
Alexandre Borela #:

The sleep alone inside OnTick you posted would do nothing other than make the test slower.

Post the full code.

Thanks.   Full code is:

#include <Trade\Trade.mqh>
input int MagicNumber=92206;
input double Lots =0.1;
input double Risk = 1; // Equity Risk Percent
input int sleeptime=0; // Sleep time

input int EMAPeriod=200; // Long MA Length
input int FastPeriod=80; // Short Period

input string group1 = "Bear RSI Filters";//------------------------------------------------
input int BearRSIPeriod=7; // RSI Period
input int BearOB=85; // Bear Overbought Level
input int BearOS=10; // Bear Oversold Level

input string group3 = "Bear ATR Filters";//------------------------------------------------
input int BearATRPeriod=8; // ATR Period
input double BearATRSL = 6; // ATR SL
input double BearATRTP = 9; // ATR TP


input string group2 = "Bull RSI Filters";//------------------------------------------------
input int BullRSIPeriod=7; // RSI Period
input int BullOB=90; // Bull Overbought Level
input int BullOS=10; // Bull Oversold Level

input string group4 = "Bull ATR Filters";//------------------------------------------------
input int BullATRPeriod=10; // ATR Period
input double BullATRSL = 6; // ATR SL
input double BullATRTP = 9; // ATR TP



input int TrailingStop=0;

// Time Filters
input string   group6 = "Time Filters";//------------------------------------------------
input bool timefilter   = false; //Time Filter Activation
input string TimeStart1 = "03";
input string TimeEnd1 = "18";



//+------------------------------------------------------------------+
//    expert start function
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+


ENUM_MA_METHOD MethodMigrate(int method)
  {
   switch(method)
     {
      case 0:
         return(MODE_SMA);
      case 1:
         return(MODE_EMA);
      case 2:
         return(MODE_SMMA);
      case 3:
         return(MODE_LWMA);
      default:
         return(MODE_SMA);
     }
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
ENUM_STO_PRICE StoFieldMigrate(int field)
  {
   switch(field)
     {
      case 0:
         return(STO_LOWHIGH);
      case 1:
         return(STO_CLOSECLOSE);
      default:
         return(STO_LOWHIGH);
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
ENUM_APPLIED_PRICE PriceMigrate(int price)
  {
   switch(price)
     {
      case 1:
         return(PRICE_CLOSE);
      case 2:
         return(PRICE_OPEN);
      case 3:
         return(PRICE_HIGH);
      case 4:
         return(PRICE_LOW);
      case 5:
         return(PRICE_MEDIAN);
      case 6:
         return(PRICE_TYPICAL);
      case 7:
         return(PRICE_WEIGHTED);
      default:
         return(PRICE_CLOSE);
     }
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
ENUM_TIMEFRAMES TFMigrate(int tf)
  {
   switch(tf)
     {
      case 0:
         return(PERIOD_CURRENT);
      case 1:
         return(PERIOD_M1);
      case 5:
         return(PERIOD_M5);
      case 15:
         return(PERIOD_M15);
      case 30:
         return(PERIOD_M30);
      case 60:
         return(PERIOD_H1);
      case 240:
         return(PERIOD_H4);
      case 1440:
         return(PERIOD_D1);
      case 10080:
         return(PERIOD_W1);
      case 43200:
         return(PERIOD_MN1);

      case 2:
         return(PERIOD_M2);
      case 3:
         return(PERIOD_M3);
      case 4:
         return(PERIOD_M4);
      case 6:
         return(PERIOD_M6);
      case 10:
         return(PERIOD_M10);
      case 12:
         return(PERIOD_M12);
      case 16385:
         return(PERIOD_H1);
      case 16386:
         return(PERIOD_H2);
      case 16387:
         return(PERIOD_H3);
      case 16388:
         return(PERIOD_H4);
      case 16390:
         return(PERIOD_H6);
      case 16392:
         return(PERIOD_H8);
      case 16396:
         return(PERIOD_H12);
      case 16408:
         return(PERIOD_D1);
      case 32769:
         return(PERIOD_W1);
      case 49153:
         return(PERIOD_MN1);
      default:
         return(PERIOD_CURRENT);
     }
  }

#define MODE_MAIN 0
#define MODE_SIGNAL 1
#define MODE_PLUSDI 1
#define MODE_MINUSDI 2
#define MODE_OPEN 0
#define MODE_LOW 1
#define MODE_HIGH 2
#define MODE_CLOSE 3
#define MODE_VOLUME 4
#define MODE_REAL_VOLUME 5


#define OP_BUY 0           //Buy 
#define OP_SELL 1          //Sell 
#define OP_BUYLIMIT 2      //Pending order of BUY LIMIT type 
#define OP_SELLLIMIT 3     //Pending order of SELL LIMIT type 
#define OP_BUYSTOP 4       //Pending order of BUY STOP type 
#define OP_SELLSTOP 5      //Pending order of SELL STOP type 
//---
#define MODE_TRADES 0
#define MODE_HISTORY 1
#define SELECT_BY_POS 0
#define SELECT_BY_TICKET 1
//---
#define DOUBLE_VALUE 0
#define FLOAT_VALUE 1
#define LONG_VALUE INT_VALUE
//---
#define CHART_BAR 0
#define CHART_CANDLE 1
//---
#define MODE_ASCEND 0
#define MODE_DESCEND 1
//---

#define MODE_TIME 5
#define MODE_BID 9
#define MODE_ASK 10
#define MODE_POINT 11
#define MODE_DIGITS 12
#define MODE_SPREAD 13
#define MODE_STOPLEVEL 14
#define MODE_LOTSIZE 15
#define MODE_TICKVALUE 16
#define MODE_TICKSIZE 17
#define MODE_SWAPLONG 18
#define MODE_SWAPSHORT 19
#define MODE_STARTING 20
#define MODE_EXPIRATION 21
#define MODE_TRADEALLOWED 22
#define MODE_MINLOT 23
#define MODE_LOTSTEP 24
#define MODE_MAXLOT 25
#define MODE_SWAPTYPE 26
#define MODE_PROFITCALCMODE 27
#define MODE_MARGINCALCMODE 28
#define MODE_MARGININIT 29
#define MODE_MARGINMAINTENANCE 30
#define MODE_MARGINHEDGED 31
#define MODE_MARGINREQUIRED 32
#define MODE_FREEZELEVEL 33
//---
#define EMPTY -1
bool tradingallowed = false;




  

void OnTick()
  {

     Sleep(sleeptime);
     MqlDateTime dateTimeNowUtc;
      TimeGMT(dateTimeNowUtc);
      if(timefilter)
      {
         if (dateTimeNowUtc.hour >= TimeStart1 && dateTimeNowUtc.hour < TimeEnd1) {
            // stop trade operations (except close open positions)
            tradingallowed = false;
       
         }
         else {
            // restart trade operations
             tradingallowed = true;
               }
      }
      else
         {
         tradingallowed = true;
         }
   
   //Print("Trading Allowed: " + tradingallowed);

   CTrade trade;
   trade.SetExpertMagicNumber(MagicNumber);
   double Ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
   double Bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);
   double GBPBid=SymbolInfoDouble("GBPAUD",SYMBOL_BID);

   double MyPoint=_Point;
   if(_Digits==3 || _Digits==5)
      MyPoint=_Point*10;
      
   double TheStopLoss=0;
   double TheTakeProfit=0;
   double RiskValue = 0;
   double OrderVal = 0;
   double equity=AccountInfoDouble(ACCOUNT_EQUITY)/GBPBid/Bid;
   double StopLoss = 0;
   double TakeProfit = 0;
   double CurrentRSI = 0;
   double PreviousRSI = 0;
   double PreviousRSI1 = 0; 
   double ATR = 0;
   
   bool crossover = false;
   bool crossunder = false;
   bool exitlong = false;
   bool exitshort = false;
   
   // 200 DMA
   double myMovingAverageArray[];
   int movingAverageDefinition = iMA(_Symbol,PERIOD_D1,EMAPeriod,0,MODE_SMA,PRICE_CLOSE);
   ArraySetAsSeries(myMovingAverageArray,true);
   CopyBuffer(movingAverageDefinition,0,0,3,myMovingAverageArray);
   double CurrentEMA=myMovingAverageArray[0];
   
   // 50 DMA
   double myFastMovingAverageArray[];
   int FastmovingAverageDefinition = iMA(_Symbol,PERIOD_D1,FastPeriod,0,MODE_SMA,PRICE_CLOSE);
   ArraySetAsSeries(myFastMovingAverageArray,true);
   CopyBuffer(FastmovingAverageDefinition,0,0,3,myFastMovingAverageArray);
   double CurrentFastEMA=myFastMovingAverageArray[0];
   
   
   double NewOverbought = 0;
   double NewOversold = 0;
   string Market = "";
   string TheMessage = "";

   // Check EMA
   if ((Bid < CurrentEMA) && (CurrentEMA > CurrentFastEMA))
      {
         NewOverbought = BearOB;
         NewOversold = BearOS;
         Market = "Bear";
         CurrentRSI = iRSIMQL4(_Symbol,0,BearRSIPeriod,PRICE_CLOSE,0); 
         PreviousRSI = iRSIMQL4(_Symbol,0,BearRSIPeriod,PRICE_CLOSE,1);
         ATR = iATRMQL4(_Symbol,PERIOD_CURRENT,BearATRPeriod,0);
   
         StopLoss = ATR * BearATRSL; 
         TakeProfit= ATR * BearATRTP; 

         RiskValue = equity * (Risk/100) * Bid;
         OrderVal = int((RiskValue / (ATR * BearATRSL))/1000);
         OrderVal = OrderVal/100;
         
      }
   else
      {
         NewOverbought = BullOB;
         NewOversold = BullOS;
         Market = "Bull";
         CurrentRSI = iRSIMQL4(_Symbol,0,BullRSIPeriod,PRICE_CLOSE,0); 
         PreviousRSI = iRSIMQL4(_Symbol,0,BullRSIPeriod,PRICE_CLOSE,1);
         ATR = iATRMQL4(_Symbol,PERIOD_CURRENT,BullATRPeriod,0);
   
         StopLoss = ATR * BullATRSL; 
         TakeProfit= ATR * BullATRTP; 

         RiskValue = equity * (Risk/100) * Bid;
         OrderVal = int((RiskValue / (ATR * BullATRSL))/1000);
         OrderVal = OrderVal/100;
      }
      

 
   
   


   
 

   // Check for crossovers
   
   if ((CurrentRSI < NewOverbought) && (PreviousRSI > NewOverbought) ) // Go Short
      crossunder = true;
         
   if ((CurrentRSI > NewOversold) && (PreviousRSI < NewOversold) ) // Go Long 
      crossover = true;


      
   // Check for Exits
   if ((CurrentRSI > NewOverbought) ) // Exit Long
      exitlong = true;
      
   if ((CurrentRSI < NewOversold) ) // Exit Short
      exitshort = true;
           






   if(TotalOrdersCount()==0)
     {
      // Looking for BUY
      if(
         crossover
      )  // Here is your open buy rule
        {



         if(StopLoss>0)
            TheStopLoss=SymbolInfoDouble(_Symbol,SYMBOL_ASK)-StopLoss; //*MyPoint;
         if(TakeProfit>0)
            TheTakeProfit=SymbolInfoDouble(_Symbol,SYMBOL_ASK)+TakeProfit; //*MyPoint;
         if(tradingallowed)
            trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,OrderVal ,SymbolInfoDouble(_Symbol,SYMBOL_ASK),TheStopLoss,TheTakeProfit);
            TheMessage = "Open Long: " + _Symbol 
               + " Volume:" + DoubleToString(OrderVal,2) 
               + " Ask: " + DoubleToString(SymbolInfoDouble(_Symbol,SYMBOL_ASK),5)
               + " SL: " + DoubleToString(TheStopLoss,5)
               + " TP: " + DoubleToString(TheTakeProfit,5);
            SendMail("New Order",TheMessage);
         return;
        }

      // Looking for SHORT
      if(
         crossunder
      ) // Here is your open Sell rule
        {

         if(StopLoss>0)
            TheStopLoss=SymbolInfoDouble(_Symbol,SYMBOL_BID)+StopLoss; //*MyPoint;
         if(TakeProfit>0)
            TheTakeProfit=SymbolInfoDouble(_Symbol,SYMBOL_BID)-TakeProfit;//*MyPoint;

         if(tradingallowed)
            trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,OrderVal,SymbolInfoDouble(_Symbol,SYMBOL_BID),TheStopLoss,TheTakeProfit);
            TheMessage = "Open Short: " + _Symbol 
               + " Volume:" + DoubleToString(OrderVal,2) 
               + " Ask: " + DoubleToString(SymbolInfoDouble(_Symbol,SYMBOL_BID),5)
               + " SL: " + DoubleToString(TheStopLoss,5)
               + " TP: " + DoubleToString(TheTakeProfit,5);
            SendMail("New Order",TheMessage);
         return;
        }

     }

   int posTotal=PositionsTotal();
   for(int posIndex=posTotal-1; posIndex>=0; posIndex--)
     {
      ulong ticket=PositionGetTicket(posIndex);
      if(PositionSelectByTicket(ticket) && PositionGetInteger(POSITION_MAGIC)==MagicNumber)
        {
         if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
           {
            if(
               exitlong
            ) //here is your close buy rule
              {
               //if(tradingallowed)
                  trade.PositionClose(ticket);
                  SendMail("Long Position Closed","Long Closed");
               break;
              }

            if(TrailingStop>0)
              {
               if(SymbolInfoDouble(_Symbol,SYMBOL_BID)-PositionGetDouble(POSITION_PRICE_OPEN)>MyPoint*TrailingStop)
                 {
                  if(PositionGetDouble(POSITION_SL)<SymbolInfoDouble(_Symbol,SYMBOL_BID)-MyPoint*TrailingStop)
                    {
                     if(tradingallowed)
                        trade.PositionModify(ticket,SymbolInfoDouble(_Symbol,SYMBOL_BID)-MyPoint*TrailingStop,PositionGetDouble(POSITION_TP));
                     return;
                    }
                 }
              }
           }

         if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
           {
            if(
               exitshort
            ) // here is your close sell rule
              {
               //if(tradingallowed)
                  trade.PositionClose(ticket);
                  SendMail("Short Position Closed","Short Closed");
               break;
              }
            if(TrailingStop>0)
              {
               if(PositionGetDouble(POSITION_PRICE_OPEN)-SymbolInfoDouble(_Symbol,SYMBOL_ASK)>MyPoint*TrailingStop)
                 {
                  if(PositionGetDouble(POSITION_SL)>SymbolInfoDouble(_Symbol,SYMBOL_ASK)+MyPoint*TrailingStop)
                    {
                     if(tradingallowed)
                        trade.PositionModify(ticket,SymbolInfoDouble(_Symbol,SYMBOL_ASK)+MyPoint*TrailingStop,PositionGetDouble(POSITION_TP));
                     return;
                    }
                 }
              }
           }
        }
     }
   return;
  }


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int TotalOrdersCount()
  {
   int result=0;
   int posTotal=PositionsTotal();
   for(int posIndex=posTotal-1; posIndex>=0; posIndex--)
     {
      ulong ticket=PositionGetTicket(posIndex);
      if(PositionSelectByTicket(ticket) && PositionGetInteger(POSITION_MAGIC)==MagicNumber)
         result++;
     }
   return (result);
  }
//
... followed by functions
 
timelleston #:
I can think of 2 reasons:

1. The programmer might be trying to debounce the OnTick function to prevent the logic inside it to execute
too many times in 1 second as it could freeze metatrader, specially during news where it receives a ton of ticks,
but the way it's coded, it would not work.

2. Another reason could be that he does not trust the signal from the indicators if it does not stay that way for at
least N seconds, which could be a valid strategy when you searching for crosses or zones being reached.
 
Alexandre Borela #:
I can think of 2 reasons:

1. The programmer might be trying to debounce the OnTick function to prevent the logic inside it to execute
too many times in 1 second as it could freeze metatrader, specially during news where it receives a ton of ticks,
but the way it's coded, it would not work.

2. Another reason could be that he does not trust the signal from the indicators if it does not stay that way for at
least N seconds, which could be a valid strategy when you searching for crosses or zones being reached.

Yeah right ok, thanks.   They both seem to make sense from a  logic standpoint.

Reason: