How to code an indicator properly

 
 

Build 5779
Давно заметил, тянется из билда в билд.

В момент каждого появления нового бара

(rates_total - prev_calculated) == 1

Есть пропуск отрисовки индикаторного буфера

пропуск


Воспроизведение:
запустить на М1
дождаться нового прихода бара

//+------------------------------------------------------------------+
//|                                                    TickIndicator |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

#property indicator_separate_window
#property indicator_plots 1
#property indicator_buffers 1


double buff[];

//+------------------------------------------------------------------+
//| функция OnInit()                                                 |
//+------------------------------------------------------------------+
void OnInit()
{
   SetIndexBuffer(0, buff, INDICATOR_DATA);
   PlotIndexSetInteger(0, PLOT_DRAW_TYPE,  DRAW_LINE);
   PlotIndexSetInteger(0, PLOT_LINE_STYLE, STYLE_SOLID);
   PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrRed);
   PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 1);
   PlotIndexSetString(0,  PLOT_LABEL,"Bid");
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);   
   IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
}

//+------------------------------------------------------------------+
//| функция OnCalculate()                                            |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   //сдвиг
   ArrayCopy(buff, buff, 0, 1, rates_total-1);
   
   //вставка последнего значения
   buff[rates_total-1] = SymbolInfoDouble(_Symbol, SYMBOL_BID);
 

   return(rates_total);
}
 
Roman #:

В момент каждого появления нового бара

Есть пропуск отрисовки индикаторного буфера


Воспроизведение:
запустить на М1
дождаться нового прихода бара

Для тиковой отрисовки сдвиг-то с помощью ArrayCopy должен делаться по условию не формирования нового бара! Когда индикаторный буфер автоматически наращивается новым баром, сдвиг не нужен.

Ваш код как раз копирует новый пустой бар из 0-го индекса в 1-ый.

 
Stanislav Korotky #:


Ваш код как раз копирует новый пустой бар из 0-го индекса в 1-ый.

Как новый бар может быть пустым?
Новый бар

(rates_total - prev_calculated) == 1

это первый его тик!

Отрисовка тиков, это всего лишь пример для наглядности проблемы в момент нового бара, раньше такой проблемы не было.

 
Roman #:

Как новый бар может быть пустым?
Новый бар, это первый его тик!

Отрисовка тиков, это всего лишь пример для наглядности проблемы в момент нового бара, раньше такой проблемы не было.

Именно так, новый бар добавляется пустым в индикаторный буфер - там может быть мусор или ноль, если повезет.

У меня есть опыт написания индикаторов, с произвольным таймингом элементов - отличным от баров таймфрейма, на который наброшен индикатор. Безусловный сдвиг в вашем коде - это ошибка. При новом баре сдвиг делает система за вас.

 
Stanislav Korotky #:

Именно так, новый бар добавляется пустым в индикаторный буфер - там может быть мусор или ноль, если повезет.


Это и есть ошибка.
Повторюсь, это появилось давно, но раньше было корректное поведение.
В момент нового бара, никаких пустот не было.

 
Roman #:

Это и есть ошибка.
Повторюсь, это появилось давно, но раньше было корректное поведение.
В момент нового бара, никаких пустот не было.

Что ошибка - добавление нового бара? Это не ошибка. Это стандартное поведение. Всегда так было.

 
Stanislav Korotky #:

Что ошибка - добавление нового бара? Это не ошибка. Это стандартное поведение. Всегда так было.

Добавляется пустым в индикаторный буфер - там может быть мусор или ноль, если повезет.
Это ошибка!
Новый бар (rates_total - prev_calculated) == 1, это первый его тик! У которого есть значения на момент открытия.
Зачем добавлять в буфер пустой мусорный бар?

Так было не всегда!
 
Roman #:

Это и есть ошибка.
Повторюсь, это появилось давно, но раньше было корректное поведение.
В момент нового бара, никаких пустот не было.

Всегда так было и это не ошибка. 

Вот, для примера  индикатор написан в 2022 году и там , на новом баре просто не делается сдвиг. 

Second Bars
Second Bars
  • 2024.04.01
  • www.mql5.com
Индикатор рисует на графике произвольный секундный таймфрейм.
 
Roman #:
Добавляется пустым в индикаторный буфер - там может быть мусор или ноль, если повезет.
Это ошибка!
Новый бар (rates_total - prev_calculated) == 1, это первый его тик! У которого есть значения на момент открытия.
Зачем добавлять в буфер пустой мусорный бар?

Так было не всегда!
Не мусорный бар, в баре всё есть, но вы то копируете свой же буфер, в котором на момент открытия нового бара происходит ресайз массива и в последнем индексе вашего буфера лежит мусор или ноль, если повезёт.
 
Aleksandr Slavskii #:
Не мусорный бар, в баре всё есть, но вы то копируете свой же буфер, в котором на момент открытия нового бара происходит ресайз массива и в последнем индексе вашего буфера лежит мусор или ноль, если повезёт.
После авто-ресайза массива в последний индекс буфера кладётся крайнее его актуальное значение!
Затем выход из функции и передача управления.
Какой может быть мусор в новом последнем элементе?
Это явная ошибка поведения.