Неправильная работа индикатора

 

Приветствую всех.

Ниже код индикатора который используя DRAW_COLOR_CANDLES строит в отдельном под окне нестандартный график с заданным периодом 

//+------------------------------------------------------------------+
//|                                                 Candles Cart.mq5 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp." 
#property link      "https://www.mql5.com" 
#property version   "1.00" 
    
#property indicator_separate_window 
#property indicator_buffers 5 
#property indicator_plots   1 
#property indicator_type1   DRAW_COLOR_CANDLES 
//--- зададим 3 цвета для раскраски свечей 
#property indicator_color1  clrGreen, clrDodgerBlue, clrCrimson 
#property indicator_style1  STYLE_SOLID 
#property indicator_width1  2 

enum PT
{
   ticks,   // тики
   seconds, // секунды
   minutes  // минуты
};  
//--- input параметры 
input PT       Type_Period   = seconds;
input int      Period_Candle = 6;   // Period 
input int      Candle_Chart  = 500; // Свечей на графике 

//--- структура
struct data_candles
{
   double Open;
   double High;
   double Low;
   double Close;
   double Color;
};
//--- массив структуры
data_candles arr_st[];
//--- массивы которые будут использоваться в качестве индикаторных буферов 
double OpenBuffer[]; 
double HighBuffer[]; 
double LowBuffer[]; 
double CloseBuffer[]; 
double ColorBuffer[]; 
//--- 
double Bid;
string symbol;
int count_tick; 
long prev_msc;
datetime prev_time;
bool flag_start;
//+------------------------------------------------------------------+ 
//| Custom indicator initialization function                         | 
//+------------------------------------------------------------------+ 
int OnInit() 
{ 
//--- Связываем индикаторные буфера с массивами
   SetIndexBuffer(0,OpenBuffer,INDICATOR_DATA); 
   SetIndexBuffer(1,HighBuffer,INDICATOR_DATA); 
   SetIndexBuffer(2,LowBuffer,INDICATOR_DATA); 
   SetIndexBuffer(3,CloseBuffer,INDICATOR_DATA); 
   SetIndexBuffer(4,ColorBuffer,INDICATOR_COLOR_INDEX); 
//--- развернём порядок индексации индикаторных буферов
   ArraySetAsSeries(OpenBuffer, true);
   ArraySetAsSeries(HighBuffer, true);
   ArraySetAsSeries(LowBuffer, true);
   ArraySetAsSeries(CloseBuffer, true);
   ArraySetAsSeries(ColorBuffer, true);
//--- пустое значение 
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE, 0.0); 
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE, 0.0); 
   PlotIndexSetDouble(2,PLOT_EMPTY_VALUE, 0.0); 
   PlotIndexSetDouble(3,PLOT_EMPTY_VALUE, 0.0); 
   PlotIndexSetDouble(4,PLOT_EMPTY_VALUE, 0.0); 
//--- 
   IndicatorSetString(INDICATOR_SHORTNAME, "Candles Chart (period: " + (string)Period_Candle + " " + EnumToString(Type_Period) + ")"); 
//---
   if(Candle_Chart <= 0)
   {
      Print("Значение 'Candle_Chart' должно быть больше 0.");
      return(INIT_FAILED);
   }
   ArrayResize(arr_st, Candle_Chart);
   Bid = 0.0;
   symbol = _Symbol;
   prev_msc = 0;
   prev_time = 0;
   flag_start = false;
//---
   if(Period_Candle <= 0)
   {
      Print("Значение 'Period_Candle' должно быть больше 0.");
      return(INIT_FAILED);
   }
   int timer_sec = Period_Candle;
   if(Type_Period == minutes) timer_sec = Period_Candle * 60;
   EventSetTimer(timer_sec);
   OnTimer();
//---
   return(INIT_SUCCEEDED); 
} 
//+------------------------------------------------------------------+ 
//| Custom indicator iteration function                              | 
//+------------------------------------------------------------------+ 
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[]) 
{ 
   MqlTick last_tick;
   SymbolInfoTick(symbol, last_tick);
//--- получим цену Bid
   Bid = last_tick.bid;
//--- Время последнего обновления цен в миллисекундах
   long msc = last_tick.time_msc;
//---
   if(prev_msc != msc)
   {
      prev_msc = msc;
//--- если Type_Period = ticks, увеличиваем счётчик тиков на 1
      if(Type_Period == ticks)count_tick++;
//--- если пришёл первый тик заполняем массив структуры на нулевом баре
      if(!flag_start)
      {
         arr_st[0].Close = arr_st[0].Open = arr_st[0].High = arr_st[0].Low = Bid;
         arr_st[0].Color = 0.0;
         flag_start = true;
      }
//--- формируем данные нулевой свечи на каждом тике
      arr_st[0].Close = Bid;
      if(arr_st[0].High < Bid)arr_st[0].High = Bid;
      if(arr_st[0].Low > Bid)arr_st[0].Low = Bid;
//--- отрисовка нулевой свечи на каждом тике   
      OpenBuffer[0] = arr_st[0].Open; 
      HighBuffer[0] = arr_st[0].High; 
      LowBuffer[0] = arr_st[0].Low; 
      CloseBuffer[0] = arr_st[0].Close;
//--- устанавливаем цвет свечи на каждом тике   
      if(arr_st[0].Open == arr_st[0].Close) arr_st[0].Color = ColorBuffer[0] = 0.0;
      if(arr_st[0].Open < arr_st[0].Close) arr_st[0].Color = ColorBuffer[0] = 1.0;
      if(arr_st[0].Open > arr_st[0].Close) arr_st[0].Color = ColorBuffer[0] = 2.0;
//--- если накопилось достаточное число тиков сдвигаем график влево на одну свечу(если Type_Period = ticks)
      if(Type_Period == ticks && count_tick >= Period_Candle) 
      { 
         Shift_Chart(Bid, Candle_Chart);
//--- сбрасываем счетчик тиков в 0
         count_tick = 0; 
      }
   } 
   return(rates_total); 
} 
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
{
//--- сдвигаем график влево на одну свечу(если Type_Period = seconds/minutes)
   if(flag_start && Type_Period != ticks) Shift_Chart(Bid, Candle_Chart);
}
//+------------------------------------------------------------------+ 


//+------------------------------------------------------------------+
//|              сдвиг графика влево на одну свечу                   |
//+------------------------------------------------------------------+
void Shift_Chart(double price, int limit_candle)
{
   ArrayCopy(OpenBuffer, OpenBuffer, 1, 0, limit_candle);
   ArrayCopy(HighBuffer, HighBuffer, 1, 0, limit_candle);
   ArrayCopy(LowBuffer, LowBuffer, 1, 0, limit_candle);
   ArrayCopy(CloseBuffer, CloseBuffer, 1, 0, limit_candle);
   ArrayCopy(ColorBuffer, ColorBuffer, 1, 0, limit_candle);
   OpenBuffer[0] = HighBuffer[0] = LowBuffer[0] = CloseBuffer[0] = price; 
   ColorBuffer[0] = 0.0;
   ArrayCopy(arr_st, arr_st, 1, 0, limit_candle);
   arr_st[0].High = arr_st[0].Low = arr_st[0].Open = arr_st[0].Close = price;
   arr_st[0].Color = 0.0;
// если достигли числа свечей limit_candle, то все последующие свечи не отрисовываем      
   if(OpenBuffer[limit_candle - 1] != 0.0)
   {
      int bars = Bars(NULL, 0);
      ArrayFill(OpenBuffer, 0, bars - limit_candle, 0.0);
      ArrayFill(CloseBuffer, 0, bars - limit_candle, 0.0);
      ArrayFill(HighBuffer, 0, bars - limit_candle, 0.0);
      ArrayFill(LowBuffer, 0, bars - limit_candle, 0.0);
      ArrayFill(ColorBuffer, 0, bars - limit_candle, clrNONE);
   }
}

индикатор работает нормально до определённого момента: в момент когда на графике к которому прикреплён индикатор появляется новая свеча индикатор тоже рисует новую свечу, которая не предусмотрена алгоритмом индикатора.

На примере: 

период графика к которому прикреплён индикатор - М1

input PT       Type_Period   = seconds;
input int      Period_Candle = 60;

т.е. период формирования свечи при таких настройках равен 60 секунд.

Допустим мы запустили индикатор в 10:50:58 т.е. до конца формирования свечи на М1 остаётся 2 секунды. В момент запуска индикатор рисует 1-ю свечу в под окне, но через 2 секунды появляется ещё одна свеча(как я понял её уже рисует подсистема терминала), т.к. на М1 сформировался новый бар. Но т.к. 1-я свеча индикатора ещё не сформирована до конца(прошло 2 секунды), то индикатор рисует ещё одну свечу и т.д. В результате получается лишние свечи в окне индикатора и искажение данных:


Прошу откликнутся тех у кого есть опыт решения такой проблемы.

P.S. можно конечно открыть D1 или выше и не париться, но это крайне неудобно..

 

У вас есть функция Shift_Chart. Нужна подобная, но со сдвигом в другую сторону, как появляется новый бар так сдвинуть. 

Еще лучше делать свои расчеты в обычные массивы, или в массив структур, а потом перекидывать со своих массивов в индикаторные буферы для отображения.

 
Dmitry Fedoseev:

У вас есть функция Shift_Chart. Нужна подобная, но со сдвигом в другую сторону, как появляется новый бар так сдвинуть. 

Тоже думал об этом, но это был как крайний вариант.
Еще лучше делать свои расчеты в обычные массивы, или в массив структур, а потом перекидывать со своих массивов в индикаторные буферы для отображения.

В данном случае лучший вариант похоже.. сейчас проверю.

Спасибо за помощь.