Mt4 End of support. - page 20

 
Alexey Viktorov:
It is better not to start there. This is what scares you away. Even I, a supporter of OOP who knows it very poorly, stumbled because of this text... ...did not understand anything. That's why I'm trying to explain the difference at the lowest level.

It can also be simpler.

OOP - allows you to define a single interface. After that, all platform-specific things "hide" and do not interfere with the work.

Of course, you can do it in a purely procedural approach. But, supporting procedural variant will be more complicated, due to the fact that in each function we will have to deal with all platforms at once.

 

I apologise for the slight delay.

Here is the first version of the function. You can refine and develop it further. If anyone notices a mistake, please comment.

//+------------------------------------------------------------------+
//|                                                    Новый бар.mq4 |
//|                                                      Peter Konow |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Peter Konow"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//------------------------
datetime Время_последнего_бара;
//------------------------
//Счетчики
//------------------------
int Частота_таймера = 25;
int Минута;
int 5_Минут;
int 15_Минут;
int 30_Минут;
int 1_Час;
int 4_Часа;
int 1_День;
//------------------------
//Флаги
//------------------------
bool Новый_минутный_бар;
bool Новый_5_минутный_бар;
bool Новый_15_минутный_бар;
bool Новый_30_минутный_бар;
bool Новый_часовой_бар;
bool Новый_4_часовой_бар;
bool Новый_дневной_бар;
//--------------------------------------------
//Значения временных периодов в миллесекундах.
//--------------------------------------------
#define  M1    60000
#define  M5    300000
#define  M15   900000
#define  M30   1800000
#define  H1    3600000
#define  H4    14000000
#define  D1    84000000
//------------------------
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetMillisecondTimer(25);
   //-------------------------------------------------------------
   //Записываем время последнего бара на момент загрузки эксперта.  
   //Для корректного начала работы, робота нужно запустить на М1. 
   //-------------------------------------------------------------
   Время_последнего_бара = Time[0];
   //-------------------------------------------------------------
   
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
      
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
//---------------------------------------------------------------
//Считаем время в счетчиках. Для каждого таймфрейма свой счетчик.
//Как только значение счетчика достигает количество миллесекунд в 
//периоде таймфрейма, счетчик обнуляется и выставляется флаг нового
//бара этого таймфрейма. Этот флаг остается до тех пор, пока 
//один из вызовов функции Новый_бар() не снимет его. 
//Таким образом, флаг нового бара любого таймфрейма остается до тех
//пор, пока пользователь не узнает этот факт, вызвав функцию Новый_бар().
//---------------------------------------------------------------
void OnTimer()
{
 static bool Ведется_отсчет;
   //---------------------------
   if(!Ведется_отсчет && Time[0] != Время_последнего_бара) 
     {
      Ведется_отсчет = true;
     }   
   //---------------------------
   if(Ведется_отсчет)
     {
      Минута ++;
      5_Минут  ++;
      15_Минут ++;
      30_Минут ++;
      1_Час    ++;
      4_Часа   ++;
      1_День   ++;
      //--------------------------
      if(Минута*Частота_таймера >= M1)
        {
         Новый_минутный_бар = true;
         Минута = 0;
        } 
      //--------------------------
      if(5_Минут*Частота_таймера >= M5)
        {
         Новый_5_минутный_бар = true;
         5_Минут = 0;
        } 
      //--------------------------   
      if(15_Минут*Частота_таймера >= M15)
        {
         Новый_15_минутный_бар = true;
         15_Минут = 0;
        } 
      //--------------------------   
      if(30_Минут*Частота_таймера >= M30)
        {
         Новый_30_минутный_бар = true;
         30_Минут = 0;
        } 
      //--------------------------   
      if(1_Час*Частота_таймера >= H1)
        {
         Новый_часовой_бар = true;
         1_Час = 0;
        } 
      //--------------------------  
      if(4_Часа*Частота_таймера >= H4)
        {
         Новый_4_часовой_бар = true;
         4_Часа = 0;
        } 
      //--------------------------  
      if(1_День*Частота_таймера >= D1)
        {
         Новый_дневной_бар = true;
         1_День = 0;
        } 
   //-------------------------- 
   }          
}
//--------------------------





//--------------------------
bool Новый_бар(int Таймфрейм = M1)
{
 bool Новый_бар;
 //-----------------------
 switch(Таймфрейм)
   {
    case M1: 
          //-----------------------
          Новый_бар  = Новый_минутный_бар;
          if(Новый_бар)Новый_минутный_бар = false;
          return(Новый_бар);
          //-----------------------
          break;
    //-----------------------------      
    case M5: 
          //-----------------------
          Новый_бар  = Новый_5_минутный_бар;
          if(Новый_бар)Новый_5_минутный_бар = false;
          return(Новый_бар);
          //-----------------------
          break;
    //-----------------------------  
    case M15: 
          //-----------------------
          Новый_бар  = Новый_15_минутный_бар;
          if(Новый_бар)Новый_15_минутный_бар = false;
          return(Новый_бар);
          //-----------------------
          break;
    //-----------------------------  
    case M30: 
          //-----------------------
          Новый_бар  = Новый_30_минутный_бар;
          if(Новый_бар)Новый_30_минутный_бар = false;
          return(Новый_бар);
          //-----------------------
          break;
    //-----------------------------  
    case H1: 
          //-----------------------
          Новый_бар  = Новый_часовой_бар;
          if(Новый_бар)Новый_часовой_бар = false;
          return(Новый_бар);
          //-----------------------
          break;
    //-----------------------------      
    case H4: 
          //-----------------------
          Новый_бар  = Новый_4_часовой_бар;
          if(Новый_бар)Новый_4_часовой_бар = false;
          return(Новый_бар);
          //-----------------------
          break;
    //-----------------------------              
    case D1: 
          //-----------------------
          Новый_бар  = Новый_дневной_бар;
          if(Новый_бар)Новый_дневной_бар = false;
          return(Новый_бар);
          //-----------------------
          break;
    //-----------------------------     
   }
 //-----------------------
 return(false);
}
//--------------------------
//+------------------------------------------------------------------+
 
@Peter Konow even without OOP you can make it easier, think about it and try it.

Respectfully.
 
As soon as the user calls the New_bar() function, he will receive a response from it about the event of a new bar on the requested timeframe. At the same time, after the function is called, if a new bar event has occurred - the event flag is cleared. That is, the notification of a new bar of the desired timeframe can be received only once per bar. After receiving the notification of a new bar, this bar is no longer new.
 
Реter Konow:

Here is the first version of the function. You can refine and develop it further. If anyone notices a mistake, please comment.

At first glance, everything seems to be OK. I haven't dug very deeply.

I personally would probably just divide the previous and current time by the bar duration, and if the value has changed, a new bar would appear. But, it's also possible to do it this way.

As for the style - personally I'm a bit bothered by the fact that you can't tell what type of variable it is (I'm used to "Hungarian notation, when the prefix of any variable is an abbreviation of its type), but maybe that's unnecessary.

 
Andrey Kisselyov:
@Peter Konow even without OOP you can make it easier, think about it and try it.

Respectfully.
Sure, it's possible that you can. I had an hour to do it. You can think about it and cut something down. All this is possible.
 
Andrey Kisselyov:
@Peter Konow even without OOP you may make it simpler, think it over and try.

Sincerely.

As far as I understand it correctly. The aim is to make it work. If he had posted a protected file with this function, you would never have guessed that it was written this way.

 
George Merts:

At first glance, everything seems fine. I haven't dug deep enough.

Personally, I'd probably just divide the previous and current time by the duration of the bar, and if the value has changed, a new bar has arrived. But, it's also possible to do it this way.

As for the style - personally I'm a bit bothered by the fact that you can't tell what type of variable it is (I'm used to "Hungarian notation, when the prefix of any variable is an abbreviation of its type), but maybe that's unnecessary.

Well, perception of style is a matter of habit. I, too, find it hard to read codes given in branches. It just pisses me off sometimes.))

 
George Merts:

It can also be simpler.

OOP - allows you to define a single interface. After that, all platform-specific things "hide" and do not interfere with the work.

It can, of course, be done in purely procedural approach. But, supporting the procedural variant would be more difficult, due to the fact that in each function you would have to deal with all platforms at once.

It has already been discussed that a single interface is not applicable to programming any computational tasks... Putting nice things in the form of interfaces is purely a cosmetic procedure that is applicable only to the already completed code and which further hinders the support and refinement of the code...

 
Mickey Moose:

As far as I understand it correctly. The aim is to make it work. If he had posted a protected file with this function, we would never have guessed that it was written this way.

It is desirable that it not just work, but that it works quickly, accurately, without errors, has a structured form in the source and clearly written.

best regards.