Array out of range

 

Здравствуйте,

Понимаю, что я не первый, кто задает такой вопрос, но никак не могу разобраться с ошибкой array out of range. 

Смысл я ее понимаю, что я пытаюсь получить значение с бара, идентификатор которого выходит за установленные пределы. Вот и хочу понять как эти пределы правильно установить.

//+------------------------------------------------------------------+
//|                                          True Strength Index.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
input ushort noteMarker = 159; // Маркер примечания
input int ident = 20; // Отступ маркера от бара, пиксели

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1

#property indicator_type1   DRAW_ARROW
#property indicator_color1  clrAqua
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

// Буферы
double noteBuffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){

   //--- Буфер 0
   SetIndexBuffer(0, noteBuffer, INDICATOR_DATA);
   PlotIndexSetInteger(0, PLOT_ARROW, noteMarker);
   PlotIndexSetInteger(0, PLOT_ARROW_SHIFT, ident);
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0);
   
   return(0);
  }
//+------------------------------------------------------------------+
//| 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[]){

   int limit = rates_total - prev_calculated;
      
   // Проблема вот здесь...
   for (int i = limit; i >= 0; i--){

      // Если цена открытия текущего бара больше цены открытия предыдущего бара и предыдущего - больше ему предшествующего
      if (open[i] > open[i-1] && open[i-1] > open[i-2]){
         noteBuffer[i] = open[i];
      }else{
         noteBuffer[i] = 0;
      }
      
   }

   return(rates_total);
   
}
//+------------------------------------------------------------------+

Буду признателен за объяснение.

 
llaabbss:

Здравствуйте,

Понимаю, что я не первый, кто задает такой вопрос, но никак не могу разобраться с ошибкой array out of range. 

Смысл я ее понимаю, что я пытаюсь получить значение с бара, идентификатор которого выходит за установленные пределы. Вот и хочу понять как эти пределы правильно установить.

Буду признателен за объяснение.

Здесь open[i-2]

при нулевом значении i индекс массива будет -2

 
int   limit = (prev_calculated < 
1) ? rates_total - 3 : rates_total - prev_calculated;
 
Valeriy Korobeynik:

Ошибка не ушла

 
limit = rates_total - prev_calculated;

в первый момент будет rates_total, такого индекса тоже нет, последний rates_total-1

 
Vladimir Tkach:

Здесь open[i-2]

при нулевом значении i индекс массива будет -2

Я пробовал от лимита отнимать 2, но не сильно это помогает:

for (int i = limit - 2; i >= 0; i--){...}
 
llaabbss:

Ошибка не ушла

Да, там комплексная ошибка.

int limit = (prev_calculated<3) ?2 :prev_calculated;
      
   for (int i = limit; i <rates_total; i++){

      // Если цена открытия текущего бара больше цены открытия предыдущего бара и предыдущего - больше ему предшествующего
      if (open[i] > open[i-1] && open[i-1] > open[i-2]){
         noteBuffer[i] = open[i];
      }else{
         noteBuffer[i] = 0;
      }
      
   }

   return(rates_total);
 
Valeriy Korobeynik:

Да, там комплексная ошибка.

Супер, спасибо! Да, теперь все работает верно.

P.S. И второй бонус проявился: теперь не надо определять тиковое ли событие происходит, либо открытие новой свечи. Только новая свеча. Для меня это важнее.
 

Еще один вопрос в эту же тему. Если добавить другой индикатор (осциллятор Чайкина), то сталкиваюсь с той же ошибкой, но только уже в нем:

//+------------------------------------------------------------------+
//|                                          True Strength Index.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+

#property indicator_chart_window

double CHO_Arr[];

int handle_CHO;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){

   ArraySetAsSeries(CHO_Arr, true);
   
   handle_CHO = iChaikin(Symbol(), Period(), 3, 10, MODE_EMA, VOLUME_TICK);
   
   return(0);
  }
//+------------------------------------------------------------------+
//| 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[]){


   int limit = (prev_calculated < 6) ? 5 : prev_calculated;
   
   for (int i = limit; i < rates_total; i++){
      
      //Ошибка здесь была: вместо 5 надо было указывать гораздо больший диапазон (0...rates_total), чтобы из части [rates_total-5] были выбраны необходимые 5 баров
      CopyBuffer(handle_CHO, 0, 0, rates_total, CHO_Arr);
      
      Print("[", i, "][", time[i], "]",
            "  open:", open[i],
            "  open_B1:", open[i-1],
            "  open_B2:", open[i-2],
            "  open_B3:", open[i-3],
            "  open_B4:", open[i-4],
            "  open_B5:", open[i-5],
            
            "  CHO_Arr:", DoubleToString(CHO_Arr[i], 0),
            "  CHO_Arr_B1:", DoubleToString(CHO_Arr[i-1], 0),
            "  CHO_Arr_B2:", DoubleToString(CHO_Arr[i-2], 0),
            "  CHO_Arr_B3:", DoubleToString(CHO_Arr[i-3], 0),
            "  CHO_Arr_B4:", DoubleToString(CHO_Arr[i-4], 0),
            "  CHO_Arr_B5:", DoubleToString(CHO_Arr[i-5], 0)
            
      );
      
   }

   return(rates_total);
   
}
//+------------------------------------------------------------------+

Тут-то что не так?

P.S. Разобрался. Захватывал очень маленький диапазон данных. Расширил его до rates_total и все заработало как надо.

Chaikin Oscillator (CHO)
Chaikin Oscillator (CHO)
  • www.mql5.com
Commodity Channel Index (CCI) Технический индикатор Индекс Товарного Канала (Commodity Channel Index, CCI) измеряет отклонение цены инструмента от его среднестатистической цены. BW-ZoneTrade Индикатор "BW-ZoneTrade" показывает торговые зоны Билла Вильямса - окрашивает бары в зеленый, серый и красный цвета в соответствии с движущей силой...
 
llaabbss:

Еще один вопрос в эту же тему. Если добавить другой индикатор (осциллятор Чайкина), то сталкиваюсь с той же ошибкой, но только уже в нем:

Тут-то что не так?

P.S. Разобрался. Захватывал очень маленький диапазон данных. Расширил его до rates_total и все заработало как надо.

А Вы вообще отладчиком пользуетесь?

https://www.metatrader5.com/ru/metaeditor/help/development/debug

Отладка кода - Разработка программ - Справка по MetaEditor
Отладка кода - Разработка программ - Справка по MetaEditor
  • www.metatrader5.com
В MetaEditor встроен отладчик — инструмент, который позволяет проверить работу программы по шагам (по отдельным функциям). Вы расставляете в коде программы точки останова — места, в которых исполнение программы должно быть приостановлено. Затем запускаете программу на обычном графике или в тестере стратегий. Как только исполнение программы...
Причина обращения: