Русский 中文 Español Deutsch 日本語 Português
A Pause between Trades

A Pause between Trades

MetaTrader 4Examples | 8 August 2006, 09:54
10 430 6
Andrey Khatimlianskii
Andrey Khatimlianskii


1. A Must or a Goodwill?

In the МetaТrader 3 Client Terminal, it was impossible to perform 2 trades at an interval under 10 seconds. Developing its МТ4, the MetaQuotes Software Corporation met the wishes of traders to remove this limitation. Indeed, there are situations where it is quite acceptable to perform a number of trades one after another (moving of StopLoss levels for several positions, removing of pending orders, etc.). But some traders took it in a wrong way and set about writing "killer" experts that could open positions one-by-one without a break. This resulted in blocked accounts or, at least, in the broker's unfriendly attitude.

This article is not for the above writers. It is for those who would like to make their trading comfortable for both themselves and their broker.


2. One Expert or Several Experts: What Is the Difference?

If you have only one terminal launched and only one expert working on it, it is simplicity itself to arrange a pause between trades: it is sufficient to create a global variable (a variable declared at global level, not to be confused with the terminal's Global Variables) and store the time for the last operation in it. And, of course, you should check before performing of each trade operation, whether the time elapsed after the last attempt to trade is sufficient.

This will look like this:

datetime LastTradeTime = 0;
int start()
 {
  // check whether we should enter the market
  ...
  // calculate the levels of StopLoss and TakeProfit and the lot size
  ...
  // check whether sufficient time has elapsed after the last trade
  if(LocalTime() - LastTradeTime < 10)
   {
    Comment("Less than 10 seconds have elapsed after the last trade!",
            " The expert won't trade!"); 
    return(-1);
   }
 
  // open a position
  if(OrderSend(...) < 0)
   {
    Alert( "Error opening position # ", GetLastError() );
    return(-2);
   }
    
  // memorize the time of the last trade
  LastTradeTime = LocalTime();
 
  return(0);
 }

This example is suitable for one expert working on one terminal. If one or several more experts are launched simultaneously, they will not keep the 10-second pause. They will not just be aware of when another expert was trading. Every expert will have its own, local LastTradeTime variable. The way out of this is obvious: You should create a Global Variable and store the time of the trade in it. Here we mean the terminal's Global Variable, all experts will be able to access to it.


3. The _PauseBeforeTrade() Function

Since the code realizing the pause will be the same for all experts, it will be more reasonable to arrange it as a function. This will provide maximum usability and minimum volume of the expert code.

Prior to writing the code, let as define our task more concretely - this will save our time and efforts. Thus, this is what the function must do:

  • check whether a global variable has been created and, if not, create it. It would be more logical and saving to do it from the expert's init() function, but then the would be a probability that the user will delete it and all experts working at the time will stop keeping the pause between trades. So we will place it in the function to be created;
  • memorize the current time in the global variable in order for other experts to keep the pause;
  • check whether enough time has elapsed after the last trade. For usability, it is also necessary to add an external variable that would set the necessary duration of the pause. Its value can be changed for each expert separately;
  • display information about the process and about all the errors occurred during the work;
  • return different values depending on the performance results.

If the function detects that not enough time has elapsed after the last trade, it must wait. The Sleep() function will provide both waiting and checking of the IsStopped(). I.e., if you delete the expert from the chart during it "sleeps", it will not hang up or be stopped forcedly.

But, for more self-descriptiveness, let us (every second during the "sleep") display information about how long it still remains to wait.

This is what we have to get as a result:

extern int PauseBeforeTrade = 10; // pause between trades (in seconds)
 
/////////////////////////////////////////////////////////////////////////////////
// int _PauseBeforeTrade()
//
// The function sets the local time value for the global variable LastTradeTime.
// If the local time value at the moment of launch is less than LastTradeTime + 
// PauseBeforeTrade value, the function will wait.
// If there is no global variable LastTradeTime at all, the function will create it.
// Return codes:
//  1 - successful completion
// -1 - the expert was interrupted by the user (the expert was deleted from the chart, 
//      the terminal was closed, the chart symbol or period was changed, etc.)
/////////////////////////////////////////////////////////////////////////////////
int _PauseBeforeTrade()
 {
  // there is no reason to keep the pause during testing - just terminate the function
  if(IsTesting()) 
    return(1); 
  int _GetLastError = 0;
  int _LastTradeTime, RealPauseBeforeTrade;
 
  //+------------------------------------------------------------------+
  //| Check whether the global variable exists and, if not, create it  |
  //+------------------------------------------------------------------+
  while(true)
   {
    // if the expert was interrupted by the user, stop working
    if(IsStopped()) 
     { 
      Print("The expert was stopped by the user!"); 
      return(-1); 
     }
    // check whether a global variable exists
    // if yes, exit this loop
    if(GlobalVariableCheck("LastTradeTime")) 
      break;
    else
     // if the GlobalVariableCheck returns FALSE, it means that either global variable does not exist, or 
     // an error occurred during checking
     {
      _GetLastError = GetLastError();
      // if it is still an error, display information, wait during 0.1 sec, and start to 
      // recheck
      if(_GetLastError != 0)
       {
        Print("_PauseBeforeTrade()-GlobalVariableCheck(\"LastTradeTime\")-Error #",
              _GetLastError );
        Sleep(100);
        continue;
       }
     }
    // if no error occurs, it just means that there is no global variable, try to create it
    // if GlobalVariableSet > 0, it means that the global variable has been successfully created. 
    // Exit the function
    if(GlobalVariableSet("LastTradeTime", LocalTime() ) > 0) 
      return(1);
    else
     // if GlobalVariableSet returns a value <= 0, it means that an error occurred during creation 
     // of the variable
     {
      _GetLastError = GetLastError();
      // display information, wait 0.1 sec, and restart the attempt 
      if(_GetLastError != 0)
       {
        Print("_PauseBeforeTrade()-GlobalVariableSet(\"LastTradeTime\", ", 
              LocalTime(), ") - Error #", _GetLastError );
        Sleep(100);
        continue;
       }
     }
   }
  //+--------------------------------------------------------------------------------+
  //| If the function performance has reached this point, it means that the global   |
  //| variable exists.                                                                    |
  //| Wait until LocalTime() becomes > LastTradeTime + PauseBeforeTrade               |
  //+--------------------------------------------------------------------------------+
  while(true)
   {
    // if the expert was stopped by the user, stop working
    if(IsStopped()) 
     { 
      Print("The expert was stopped by the user!"); 
      return(-1); 
     }
    // get the value of the global variable
    _LastTradeTime = GlobalVariableGet("LastTradeTime");
    // if an error occurs at this, display information, wait 0.1 sec, and try 
    // again
    _GetLastError = GetLastError();
    if(_GetLastError != 0)
     {
      Print("_PauseBeforeTrade()-GlobalVariableGet(\"LastTradeTime\")-Error #", 
            _GetLastError );
      continue;
     }
    // count how many seconds have been elapsed since the last trade
    RealPauseBeforeTrade = LocalTime() - _LastTradeTime;
    // if less than PauseBeforeTrade seconds have elapsed,
    if(RealPauseBeforeTrade < PauseBeforeTrade)
     {
      // display information, wait one second, and check again
      Comment("Pause between trades. Remaining time: ", 
               PauseBeforeTrade - RealPauseBeforeTrade, " sec" );
      Sleep(1000);
      continue;
     }
    // if the time elapsed exceeds PauseBeforeTrade seconds, stop the loop
    else
      break;
   }
  //+--------------------------------------------------------------------------------+
  //| If the function performance has reached this point, it means that the global   |
  //| variable exists and the local time exceeds LastTradeTime + PauseBeforeTrade    |
  //| Set the local time value for the global variable LastTradeTime                 |
  //+--------------------------------------------------------------------------------+
  while(true)
   {
    // if the expert was stopped by the user, stop working
    if(IsStopped()) 
     { 
      Print("The expert was stopped by the user!"); 
      return(-1);
     }

    // Set the local time value for the global variable LastTradeTime.
    // In case it succeeds - exit
    if(GlobalVariableSet( "LastTradeTime", LocalTime() ) > 0) 
     { 
      Comment(""); 
      return(1); 
     }
    else
    // if the GlobalVariableSet returns a value <= 0, it means that an error occurred
     {
      _GetLastError = GetLastError();
      // display the information, wait 0.1 sec, and restart attempt
      if(_GetLastError != 0)
       {
        Print("_PauseBeforeTrade()-GlobalVariableSet(\"LastTradeTime\", ", 
              LocalTime(), " ) - Error #", _GetLastError );
        Sleep(100);
        continue;
       }
     }
   }
 }


4. Integration into Experts and How to Use It

To check operability of the function, we created a diagnostic expert that had to trade keeping pauses between trades. The _PauseBeforeTrade() function was preliminarily placed into the PauseBeforeTrade.mq4 file included into the expert using the #include directive.

Attention! This expert is only dedicated for checking the function operability! It may not be used for trading!

#include <PauseBeforeTrade.mq4>
 
int ticket = 0;
int start()
 {
  // if there is no position opened by this expert
  if(ticket <= 0)
   {
    // keep a pause between trades, if an error has occurred, exit
    if(_PauseBeforeTrade() < 0) 
      return(-1);
    // update the market information
    RefreshRates();
 
    // and try to open a position
    ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 5, 0.0, 0.0, "PauseTest", 123, 0, 
                       Lime);
    if(ticket < 0)
      Alert("Error OrderSend № ", GetLastError());
   }
  // if there is a position opened by this expert
  else
   {
    // keep the pause between trades (if an error has occurred, exit)
    if(_PauseBeforeTrade() < 0)
      return(-1);
    // update the market information
    RefreshRates();


 
    // and try to close the position
    if (!OrderClose( ticket, 0.1, Bid, 5, Lime ))
      Alert("Error OrderClose № ", GetLastError());
    else
      ticket = 0;
   }
  return(0);
 }

After that, one expert was attached to the EURUSD-M1 chart and another one, absolutely identical, to the GBPUSD-M1 chart. The result did not keep one waiting long: Both experts started trading keeping the prescribed 10-second pause between trades:





5. Possible Problems

When several experts work with one global variable, error can occur. To avoid this, we must delimit access to the variable. A working algorithm of such "delimitation" is described in details in the article named "Error 146 ("Trade context busy") and How to Deal with It". It is this algorithm that we will use.

The final version of the expert will look like this:

#include <PauseBeforeTrade.mq4>
#include <TradeContext.mq4>
 
int ticket = 0;
int start()
 {
  // if there is no a position opened by this expert
  if(ticket <= 0)
   {
    // wait until the trade is not busy and occupy it (if an error has occurred, 
    // exit)
    if(TradeIsBusy() < 0)
      return(-1);
    // keep the pause between trades
    if(_PauseBeforeTrade() < 0)
     {
      // if an error has occurred, free the trade and exit
      TradeIsNotBusy();
      return(-1);
     }
    // update the market information
    RefreshRates();
 
    // and try to open a position
    ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 5, 0.0, 0.0, "PauseTest", 123, 0, 
                       Lime);
    if (ticket < 0)
      Alert("Error OrderSend № ", GetLastError());
    // free the trade
    TradeIsNotBusy();
   }
  // if there is a position opened by this expert
  else
   {
    // wait until the trade is not busy and occupy it (if an error has occurred, 
    // exit)
    if(TradeIsBusy() < 0)
      return(-1);
    // keep the pause between trades
    if(_PauseBeforeTrade() < 0)
     {
      // if an error occurs, free the trade and exit
      TradeIsNotBusy();
      return(-1);
     }
    // update the market information
    RefreshRates();
 
    // and try to close the position
    if(!OrderClose( ticket, 0.1, Bid, 5, Lime))
      Alert("Error OrderClose № ", GetLastError());
    else
      ticket = 0;
 
    // free the trade
    TradeIsNotBusy();
   }
  return(0);
 }

Translated from Russian by MetaQuotes Ltd.
Original article: https://www.mql5.com/ru/articles/1355

Attached files |
TradeContext.mq4 (9.27 KB)
Last comments | Go to discussion (6)
Andrey Khatimlianskii
Andrey Khatimlianskii | 26 Nov 2020 at 09:17
Mancoba Message Malaza:
How to install this 

The article was written 14 years ago. You don't need this pause in 2020.

Mancoba Message Malaza
Mancoba Message Malaza | 9 Dec 2020 at 01:13
Andrey Khatimlianskii:

The article was written 14 years ago. You don't need this pause in 2020.

Why not?
Andrey Khatimlianskii
Andrey Khatimlianskii | 9 Dec 2020 at 08:33
Mancoba Message Malaza:
Why not?

Because MT server can accept a lot of orders every second.

If you need implement pause to your trading algorithm, it is not hard. But you don't need this article.

[Deleted] | 24 Dec 2020 at 15:48
Andrey Khatimlianskii:

Because MT server can accept a lot of orders every second.

If you need implement pause to your trading algorithm, it is not hard. But you don't need this article.

How can we implement this pause pls
Andrey Khatimlianskii
Andrey Khatimlianskii | 24 Dec 2020 at 21:17
cosse:
How can we implement this pause pls

You don't need this pause nowadays.

Considering Orders in a Large Program Considering Orders in a Large Program
General principles of considering orders in a large and complex program are discussed.
MagicNumber: "Magic" Identifier of the Order MagicNumber: "Magic" Identifier of the Order
The article deals with the problem of conflict-free trading of several experts on the same МТ 4 Client Terminal. It "teaches" the expert to manage only "its own" orders without modifying or closing "someone else's" positions (opened manually or by other experts). The article was written for users who have basic skills of working with the terminal and programming in MQL 4.
My First "Grail" My First "Grail"
Examined are the most frequent mistakes that lead the first-time programmers to creation of a "super-moneymaking" (when tested) trading systems. Exemplary experts that show fantastic results in tester, but result in losses during real trading are presented.
How to Use Crashlogs to Debug Your Own DLLs How to Use Crashlogs to Debug Your Own DLLs
25 to 30% of all crashlogs received from users appear due to errors occurring when functions imported from custom dlls are executed.