Индикатор из учебника

 

Здравствуйте. Взял индикатор из учебника, немного переделал. Теперь хочу сделать так чтобы он начинал свой расчет и отрисовывался от первого бара дня.

Сейчас он начинает считать от указанного количества баров истории.

Прошу помочь.

//--------------------------------------------------------------------
// separatewindow.mq4 
// Предназначен для использования в качестве примера в учебнике MQL4.
//--------------------------------------------------------------------
#property indicator_separate_window // Отображение в отдельном окне
#property indicator_buffers 2       // Количество буферов
#property indicator_color1 Blue     // Цвет первой линии
#property indicator_color2 Red      // Цвет второй линии
 
extern int History  =50;            // Колич.баров в расчётной истории
 
double Buf_0[],Buf_1[];                     // Объявление индикаторного массива
double Sum_H=0;                    
double Sum_L=0;
//--------------------------------------------------------------------
int init()                          // Специальная функция init()
  {
   SetIndexBuffer(0,Buf_0);         // Назначение массива буферу
   SetIndexStyle (0,DRAW_LINE,STYLE_SOLID,2);// Стиль линии
   SetIndexBuffer(1,Buf_1);         // Назначение массива буферу
   SetIndexStyle (1,DRAW_LINE,STYLE_SOLID,2);// Стиль линии
   return;                          // Выход из спец. ф-ии init()
  }
//--------------------------------------------------------------------
int start()                         // Специальная функция start()
  {
   int i,                           // Индекс бара                       
   Counted_bars;                    // Количество просчитанных баров 
//--------------------------------------------------------------------
   Counted_bars=IndicatorCounted(); // Количество просчитанных баров 
   i=Bars-Counted_bars-1;           // Индекс первого непосчитанного
   if (i>History-1)                 // Если много баров то ..
      i=History-1;                  // ..рассчитывать заданное колич.
   while(i>=0)                      // Цикл по непосчитанным барам
     {
                           
      if(Open[i]<Close[i])
        {
         Sum_H=Sum_H+(Close[i]-Open[i]);
         Sum_L=Sum_L;
        }
      if(Open[i]>Close[i])
        {
         Sum_L=Sum_L+(Open[i]-Close[i]);
         Sum_H=Sum_H;
        }
      Buf_0[i]=Sum_H;// Знач. 0 буфера на i-ом баре
      Buf_1[i]=Sum_L;// Знач. 1 буфера на i-ом баре
      i--;                          // Расчёт индекса следующего бара
     }
//--------------------------------------------------------------------
   return;                          // Выход из спец. ф-ии start()
  }
//--------------------------------------------------------------------
 
Нужно найти бар текущего ТФ, который является первым баром текущих суток. Делается это при помощи функции iBarShift. Полученное значение подставляется вместо переменной History.
 
Ihor Herasko:
Нужно найти бар текущего ТФ, который является первым баром текущих суток. Делается это при помощи функции iBarShift. Полученное значение подставляется вместо переменной History.

Спасибо большое. Сделал так. Вроде работает.

//--------------------------------------------------------------------
// separatewindow.mq4 
// Предназначен для использования в качестве примера в учебнике MQL4.
//--------------------------------------------------------------------
#property indicator_separate_window // Отображение в отдельном окне
#property indicator_buffers 2       // Количество буферов
#property indicator_color1 Blue     // Цвет первой линии
#property indicator_color2 Red      // Цвет второй линии
 
//extern int History  =50;            // Колич.баров в расчётной истории
datetime time=D'2021.03.30 00:00';
bool exact=false;
 
double Buf_0[],Buf_1[];                     // Объявление индикаторного массива
double Sum_H=0;                    
double Sum_L=0;
//--------------------------------------------------------------------
int init()                          // Специальная функция init()
  {
   SetIndexBuffer(0,Buf_0);         // Назначение массива буферу
   SetIndexStyle (0,DRAW_LINE,STYLE_SOLID,2);// Стиль линии
   SetIndexBuffer(1,Buf_1);         // Назначение массива буферу
   SetIndexStyle (1,DRAW_LINE,STYLE_SOLID,2);// Стиль линии
   return;                          // Выход из спец. ф-ии init()
  }
//--------------------------------------------------------------------
int start()                         // Специальная функция start()
  {
   int i,                           // Индекс бара                       
   Counted_bars;                    // Количество просчитанных баров 
//--------------------------------------------------------------------
   Counted_bars=IndicatorCounted(); // Количество просчитанных баров
   int bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time,exact); 
   i=Bars-Counted_bars-1;           // Индекс первого непосчитанного
   if (i>bar_index-1)                 // Если много баров то ..
      i=bar_index;                  // ..рассчитывать заданное колич.
   while(i>=0)                      // Цикл по непосчитанным барам
     {
                           
      if(Open[i]<Close[i])
        {
         Sum_H=Sum_H+(Close[i]-Open[i]);
         Sum_L=Sum_L;
        }
      if(Open[i]>Close[i])
        {
         Sum_L=Sum_L+(Open[i]-Close[i]);
         Sum_H=Sum_H;
        }
      Buf_0[i]=Sum_H;// Знач. 0 буфера на i-ом баре
      Buf_1[i]=Sum_L;// Знач. 1 буфера на i-ом баре
      i--;                          // Расчёт индекса следующего бара
     }
//--------------------------------------------------------------------
   return;                          // Выход из спец. ф-ии start()
  }
//--------------------------------------------------------------------
 

Еще пару вопросов, если позволите.

Сейчас время задаю статично.

datetime time=D'2021.03.30 00:00';

Как сделать так, чтобы время и число текущего дня само подставлялось в дату?

 

Когда вешаю индикатор на чарт, то всё нормально. Но поступают новые данные на 0 баре и начинает рисовать хрень. Почему?

Файлы:
 
ifitstrue:

Еще пару вопросов, если позволите.

Сейчас время задаю статично.

Как сделать так, чтобы время и число текущего дня само подставлялось в дату?

datetime time=D'2021.03.30 7:33';
// Если взять остаток о деления этого времени на количество секунд в периоде D1
time%PeriodSeconds(PERIOD_D1);
// то получим время биздаты
// Остаётся только получить дату с временем 00:00
// А это просто
iTime(_Simbol, PERIOD_D1, 0);
// и потом сложить эти значения.

Но! время можно задать как строку string strTime = "7:33"; и перевести в тип datrtime функцией StringToTime(). В результате будет время с сегодняшней датой.

 
Alexey Viktorov:

Но! время можно задать как строку string strTime = "7:33"; и перевести в тип datrtime функцией StringToTime(). В результате будет время с сегодняшней дато@ifitstrue

ifitstrue:

Еще пару вопросов, если позволите.

Сейчас время задаю статично.

Как сделать так, чтобы время и число текущего дня само подставлялось в дату?

если на словах - текущее время преобразуйте в структуру   MqlDateTime, в структуре обнулите всё кроме даты, и далее  конвертацию из переменной типа структуры MqlDateTime в значение типа datetime. Получите время открытия дня.

функции TimeToStruct, StructToTime

 
Alexey Viktorov:

Но! время можно задать как строку string strTime = "7:33"; и перевести в тип datrtime функцией StringToTime(). В результате будет время с сегодняшней датой.

Вот так?

//--------------------------------------------------------------------
// separatewindow.mq4 
// Предназначен для использования в качестве примера в учебнике MQL4.
//--------------------------------------------------------------------
#property indicator_separate_window // Отображение в отдельном окне
#property indicator_buffers 2       // Количество буферов
#property indicator_color1 Blue     // Цвет первой линии
#property indicator_color2 Red      // Цвет второй линии

string strTime = "00:00";
 
double Buf_0[],Buf_1[];                   
double Sum_H=0;                    
double Sum_L=0;
//--------------------------------------------------------------------
int init()                          // Специальная функция init()
  {
   SetIndexBuffer(0,Buf_0);         // Назначение массива буферу
   SetIndexStyle (0,DRAW_LINE,STYLE_SOLID,2);// Стиль линии
   SetIndexBuffer(1,Buf_1);         // Назначение массива буферу
   SetIndexStyle (1,DRAW_LINE,STYLE_SOLID,2);// Стиль линии
   return(0);                          // Выход из спец. ф-ии init()
  }
//--------------------------------------------------------------------
int start()                         // Специальная функция start()
  {
   int i,                           // Индекс бара                       
   Counted_bars;                    // Количество просчитанных баров 
//--------------------------------------------------------------------
   Counted_bars=IndicatorCounted(); // Количество просчитанных баров
   datetime time=StringToTime(strTime);
   int bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time,false); 
   i=Bars-Counted_bars-1;           // Индекс первого непосчитанного
   if (i>bar_index-1) i=bar_index;  
   while(i>=0)                      // Цикл по непосчитанным барам
     {
                           
      if(Open[i]<Close[i])
        {
         Sum_H=Sum_H+(Close[i]-Open[i]);
         Sum_L=Sum_L;
        }
      if(Open[i]>Close[i])
        {
         Sum_L=Sum_L+(Open[i]-Close[i]);
         Sum_H=Sum_H;
        }
      Buf_0[i]=Sum_H;// Знач. 0 буфера на i-ом баре
      Buf_1[i]=Sum_L;// Знач. 1 буфера на i-ом баре
      i--;                          // Расчёт индекса следующего бара
     }
//--------------------------------------------------------------------
   return(0);                          // Выход из спец. ф-ии start()
  }
//--------------------------------------------------------------------
 
ifitstrue:

Вот так?

Да. Только это преобразование будет производиться на каждом тике, что нежелательно. В самом простом случае лучше перенести его в OnInit(). Если же нужно корректировать день в процессе работы, то сделайте расчет один раз в сутки:

static datetime dtLastDay = 0;
if (iTime(NULL, PERIOD_D1, 0) != dtLastDay)
{
   dtLastDay = iTime(NULL, PERIOD_D1, 0);
   time = StringToTime(strTime);
}
 
Ihor Herasko:

Да. Только это преобразование будет производиться на каждом тике, что нежелательно. В самом простом случае лучше перенести его в OnInit(). Если же нужно корректировать день в процессе работы, то сделайте расчет один раз в сутки:

Спасибо!

А тут в чем косяк?

ifitstrue:

Когда вешаю индикатор на чарт, то всё нормально. Но поступают новые данные на 0 баре и начинает рисовать хрень. Почему?

 
ifitstrue:

Когда вешаю индикатор на чарт, то всё нормально. Но поступают новые данные на 0 баре и начинает рисовать хрень. Почему?

Проблемы алгоритма. Переменные SumL и SumH объявлены глобально. В момент загрузки индикатора их значения равны нулю. Происходит обработка данных на всей доступной истории и переменные получают уже ненулевые значения. Затем приходит новый тик и обрабатывается уже не вся история, а только текущий бар или два последних бара. А в переменных записаны значения уже с учетом этих баров.

Нужно что-то придумать с сохранением правильных значений SumL и SumH так, чтобы в случае обработки не всей истории в них были соответствующие данные. 

Я обычно решаю такие проблемы перерисовкой всей истории, если обнаружено появление более, чем одного бара. А для двух последних баров сохранить данные не представляет труда.

Причина обращения: