Не меняется цвет индикаторного буфера на нулевом баре

 

Сделал индикаторный буфер с цветовыми индексами для указания направления движения цены. Для этого в своём пробном индикаторе я использую два цвета, синий и красный. Если движение вверх, линия закрашивается в синий, если вниз, то цвет линии красный.

#property indicator_chart_window

#property indicator_buffers 2
#property indicator_plots 1

#property indicator_type1 DRAW_COLOR_LINE
#property indicator_color1 Blue, Red
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1

double _close[], cl_close[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){
  SetIndexBuffer(0,_close,INDICATOR_DATA);
  ArraySetAsSeries(_close,true);
  SetIndexBuffer(1,cl_close,INDICATOR_COLOR_INDEX);
  ArraySetAsSeries(cl_close,true);
  
  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[]){
//---
  ArraySetAsSeries(close, true);
  int count = (int)fmin(rates_total, rates_total - prev_calculated + 1);
  
  for(int i = count - 1; i >= 0; i--){
    _close[i] = close[i];
  }
  
  for(int i = count - 2; i >= 0; i--){
    
    if(_close[i] > _close[i + 1]){
      cl_close[i] = 0;
    }
    else{
      cl_close[i] = 1;
    }
      
  }
  
  return(rates_total);
}
//+------------------------------------------------------------------+
Но, проблема заключается в том, что если линия изначально была синей и _close[0] ушло ниже _close[1], на следующем тике, то линия так и остаётся синей, вместо того, чтобы перекраситься в красный. С красным аналогичная ситуация. Таким образом, цвет никогда не изменяется на нулевом баре. В чём причина столь странного поведения индикатора и как с ней бороться?
 
Mihail Matkovskij:

Сделал индикаторный буфер с цветовыми индексами для указания направления движения цены. Для этого в своём пробном индикаторе я использую два цвета, синий и красный. Если движение вверх, линия закрашивается в синий, если вниз, то цвет линии красный.

#property indicator_chart_window

#property indicator_buffers 2
#property indicator_plots 1

#property indicator_type1 DRAW_COLOR_LINE
#property indicator_color1 Blue, Red
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1

double _close[], cl_close[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){
  SetIndexBuffer(0,_close,INDICATOR_DATA);
  ArraySetAsSeries(_close,true);
  SetIndexBuffer(1,cl_close,INDICATOR_COLOR_INDEX);
  ArraySetAsSeries(cl_close,true);
  
  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[]){
//---
  ArraySetAsSeries(close, true);
  int count = (int)fmin(rates_total, rates_total - prev_calculated + 1);
  
  for(int i = count - 1; i >= 0; i--){
    _close[i] = close[i];
  }
  
  for(int i = count - 2; i >= 0; i--){
    
    if(_close[i] > _close[i + 1]){
      cl_close[i] = 0;
    }
    else{
      cl_close[i] = 1;
    }
      
  }
  
  return(rates_total);
}
//+------------------------------------------------------------------+
Но, проблема заключается в том, что если линия изначально была синей и _close[0] ушло ниже _close[1], на следующем тике, то линия так и остаётся синей, вместо того, чтобы перекраситься в красный. С красным аналогичная ситуация. Таким образом, цвет никогда не изменяется на нулевом баре. В чём причина столь странного поведения индикатора и как с ней бороться?

Условие надо поменять на

if(_close[i] > open[i])

Да и всё в один цикл лучше поставить.
 
Alexey Viktorov:

Условие надо поменять на

if(_close[i] > open[i])

Да и всё в один цикл лучше поставить.

Не знаю, зачем: if(_close[i] > open[i])? Но поставил всё в один цикл и ничего не изменилось. Линия всё равно не хочет менять свой цвет на нулевом баре.

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[]){
//---
  ArraySetAsSeries(close, true);
  int count = (int)fmin(rates_total, rates_total - prev_calculated + 1);
  
  for(int i = count - 1; i >= 0; i--){
    _close[i] = close[i];
    if(i > count - 2) continue;
    if(_close[i] > _close[i + 1]){
      cl_close[i] = 0;
    }
    else{
      cl_close[i] = 1;
    }
      
  }
  
  return(rates_total);
}
 

А так?

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[])
  {
//---
   ArraySetAsSeries(close,true);
   int count=(int)fmin(rates_total-2,rates_total-prev_calculated);
   for(int i=count; i>=0; i--)
     {
      _close[i]=close[i];

      if(_close[i]>_close[i+1])
         cl_close[i]=0;
      else
         cl_close[i]=1;
     }
   return(rates_total);
  }
 
Andrey Voytenko:

А так?

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[])
  {
//---
   ArraySetAsSeries(close,true);
   int count=(int)fmin(rates_total-2,rates_total-prev_calculated);
   for(int i=count; i>=0; i--)
     {
      _close[i]=close[i];

      if(_close[i]>_close[i+1])
         cl_close[i]=0;
      else
         cl_close[i]=1;
     }
   return(rates_total);
  }

Значит, вместо одного бара нужно пересчитывать два последних. В индикаторах на MQL4 (где, в данном случае, нужно было бы 2 линии разных цветов) я использовал i, а так же i + 1 для закрытия пробела, в одном такте. То есть, если 1 бар был не подсчитан, то использовался всего один такт, не используемый цвет просто обнулялся. Большое спасибо Вам Андрей за решение!

 
Mihail Matkovskij:

Не знаю, зачем: if(_close[i] > open[i])? Но поставил всё в один цикл и ничего не изменилось. Линия всё равно не хочет менять свой цвет на нулевом баре.

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[]){
//---
  ArraySetAsSeries(close, true);
  int count = (int)fmin(rates_total, rates_total - prev_calculated + 1);
  
  for(int i = count - 1; i >= 0; i--){
    _close[i] = close[i];
    if(i > count - 2) continue;
    if(_close[i] > _close[i + 1]){
      cl_close[i] = 0;
    }
    else{
      cl_close[i] = 1;
    }
      
  }
  
  return(rates_total);
}

Сначала я сделал вариант ArraySetAsSeries( , true), но потом поменял и проверив закрыл. Поэтому того варианта нет, а писать новый нет желания. В любом случае работает и так, и так.

Условие if(_close[i]  > open[i]) нужно для того чтобы определить тип бара. Бычий или медвежий. А если написать if(_close[i] > close[i+1] то сравнение идёт с предыдущим баром и не всегда может правильно определить тип бара. А точней, очень редко.

Вот полный код рабочего варианта

/********************************************************************\
|                                                         New 00.mq5 |
|                                                           Viktorov |
|                                                  v4forex@yandex.ru |
\********************************************************************/

#property copyright "Viktorov"
#property link      "v4forex@yandex.ru"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots   1
#property indicator_type1 DRAW_COLOR_LINE
#property indicator_color1  Blue, Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

double dataBuffer[];
double colorBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0, dataBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, colorBuffer, INDICATOR_COLOR_INDEX);
  
   //ArraySetAsSeries(dataBuffer, true);
   //ArraySetAsSeries(colorBuffer, true);
   //PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0);
//---
   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[])
  {
//---
   for(int i = 0; i <= rates_total-1; i++)
    {
     if(i < rates_total-101)         // я так хочу
      {
       dataBuffer[i] = EMPTY_VALUE;  //
       continue;                     // могут быть и другие варианты.
      }
     dataBuffer[i] = close[i];
     colorBuffer[i] = (close[i] > open[i]) ? 0 : 1;
    }
   return(rates_total);
  }
//+------------------------------------------------------------------+
Причина обращения: