Пользовательский индикатор. При попытке обращения к предыдущему значению буфера в цикле for, в терминале возникает ошибка "Array out of range". Прошу помощи в решении проблемы.

 

Добрый день, уважаемые форумчане!

Суть проблемы - при попытке обращения к предыдущему значению буфера в цикле for, в терминале возникает ошибка "Array out of range". Компилятор замечаний по этому поводу никаких не выдает. Причем, если не использовать в коде property strict, индикатор начинает работать через раз в терминале. Что все равно указывает на наличие проблемы или моего непонимания матчасти.

Для наглядности, приведу пример. Без сложной логики, пусть это будет простой интерпретатор RSI на основе зон перекупленности-перепроданности с двумя особенностями: вводим обратное пороговое значение; рисуем цветные символы на графике RSI для наглядности.

Логика такова - если RSI пересек верхний порог (70 например), рисуем красные символы до тех пор, пока он не опустится ниже "порог-возвратное значение" (60 например). С нижней границей - аналогично, меняем цвет на зеленый.

Пожалуйста, помогите решить эту проблему. Весь мозг сломал, перечитал гору доков, не помогло, увы. 

Недостающие комментарии:

int pvs; - переменная, которая должна показать сигнал индикатора на предыдущем баре (0 - нет, -1 - продажа, 1 - покупка).

 Buy_buf[i] = 95 - отрисовываю символы в подокне с RSI, на уровне 95 (там график редко бывает). Значение 0 - буфер не отрисовывается.

Проблема в терминале - возникает  ошибка "Array out of range", которая приводит к тому, что pvs всегда может быть только равным 0. Значения -1 и 1 получить не удаётся.

//+------------------------------------------------------------------+
//|                                        RSI interpreter test      |
//|                                                         behemoth |
//|                                             https://xxxxxxxxxxxx |
//+------------------------------------------------------------------+
#property copyright "behemoth"
#property link      "XXX"
#property version   "1.0"

#property strict
#property script_show_inputs

#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100

#property indicator_level1 70.0
#property indicator_level2 30.0
#property indicator_level3 40.0
#property indicator_level4 60.0
#property indicator_levelcolor Gray
#property indicator_levelwidth 1
#property indicator_levelstyle 0

#property indicator_buffers 3
#property indicator_color1 RoyalBlue
#property indicator_color2 Red
#property indicator_color3 Green


extern int RSI_per = 10; // Период RSI
extern double RSI_UT = 70; // Верхнее пороговое значение
extern double RSI_LT = 30; // Нижнее пороговое значение
extern double RSI_BT = 10; // Возвратное значение (delta)

double RSI_buf[];
double Sell_buf[];
double Buy_buf[];

int pvs;

// Initialization
int init() 
{
 SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 1);
 SetIndexStyle(1, DRAW_ARROW, STYLE_SOLID, 2, indicator_color2);
 SetIndexStyle(2, DRAW_ARROW, STYLE_SOLID, 2, indicator_color3);

 SetIndexArrow (1, 110);
 SetIndexArrow (2, 110);
 
 SetIndexBuffer(0, RSI_buf);
 SetIndexBuffer(1, Sell_buf);
 SetIndexBuffer(2, Buy_buf);

 SetIndexEmptyValue(1, 0);
 SetIndexEmptyValue(2, 0);

 
 IndicatorDigits(Digits);
 
 string IndName = "RSI-int("+RSI_per+")";
 IndicatorShortName(IndName);
 
 SetIndexLabel(0, "RSI");
  
 SetIndexDrawBegin(0, RSI_per);
 return (0);
}

// Calculation
int start() {

double
RSI;

int
counted_bars=IndicatorCounted(),
limit;

if(counted_bars>0) counted_bars--;
limit=Bars-counted_bars;

   for (int i=0;i<limit;i++)
   {
      RSI = iRSI(NULL, 0, RSI_per, PRICE_CLOSE, i);
      RSI_buf[i] = RSI;
      
      Sell_buf[i]=0;
      Buy_buf[i]=0;
   
      if (Sell_buf[i+1]>0) pvs = -1;
      else if (Buy_buf[i+1]>0) pvs = 1;
      else pvs = 0;
      
      switch (pvs)
         {
          case 0:
            if (RSI <= RSI_LT) Buy_buf[i] = 95;
            if (RSI >= RSI_UT) Sell_buf[i] = 95;
            break;
          case 1:
            if (RSI < RSI_LT+RSI_BT) Buy_buf[i] = 90;
            else Buy_buf[i] = 0;
            break;
          case -1:
            if (RSI > RSI_UT-RSI_BT) Sell_buf[i] = 90;
            else Sell_buf[i] = 0;
            break;
         }

   }
   return (0);
}
 
Алексей Карасев:

Добрый день, уважаемые форумчане!

Суть проблемы - при попытке обращения к предыдущему значению буфера в цикле for, в терминале возникает ошибка "Array out of range". Компилятор замечаний по этому поводу никаких не выдает. Причем, если не использовать в коде property strict, индикатор начинает работать через раз в терминале. Что все равно указывает на наличие проблемы или моего непонимания матчасти.

Для наглядности, приведу пример. Без сложной логики, пусть это будет простой интерпретатор RSI на основе зон перекупленности-перепроданности с двумя особенностями: вводим обратное пороговое значение; рисуем цветные символы на графике RSI для наглядности.

Логика такова - если RSI пересек верхний порог (70 например), рисуем красные символы до тех пор, пока он не опустится ниже "порог-возвратное значение" (60 например). С нижней границей - аналогично, меняем цвет на зеленый.

Пожалуйста, помогите решить эту проблему. Весь мозг сломал, перечитал гору доков, не помогло, увы. 

Недостающие комментарии:

int pvs; - переменная, которая должна показать сигнал индикатора на предыдущем баре (0 - нет, -1 - продажа, 1 - покупка).

 Buy_buf[i] = 95 - отрисовываю символы в подокне с RSI, на уровне 95 (там график редко бывает). Значение 0 - буфер не отрисовывается.

Проблема в терминале - возникает  ошибка "Array out of range", которая приводит к тому, что pvs всегда может быть только равным 0. Значения -1 и 1 получить не удаётся.

//+------------------------------------------------------------------+
//|                                        RSI interpreter test      |
//|                                                         behemoth |
//|                                             https://xxxxxxxxxxxx |
//+------------------------------------------------------------------+
#property copyright "behemoth"
#property link      "XXX"
#property version   "1.0"

#property strict
#property script_show_inputs

#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100

#property indicator_level1 70.0
#property indicator_level2 30.0
#property indicator_level3 40.0
#property indicator_level4 60.0
#property indicator_levelcolor Gray
#property indicator_levelwidth 1
#property indicator_levelstyle 0

#property indicator_buffers 3
#property indicator_color1 RoyalBlue
#property indicator_color2 Red
#property indicator_color3 Green


extern int RSI_per=10; // Период RSI
extern double RSI_UT = 70; // Верхнее пороговое значение
extern double RSI_LT = 30; // Нижнее пороговое значение
extern double RSI_BT = 10; // Возвратное значение (delta)

double RSI_buf[];
double Sell_buf[];
double Buy_buf[];

int pvs;
// Initialization
int init()
  {
   SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,1);
   SetIndexStyle(1,DRAW_ARROW,STYLE_SOLID,2,indicator_color2);
   SetIndexStyle(2,DRAW_ARROW,STYLE_SOLID,2,indicator_color3);

   SetIndexArrow(1,110);
   SetIndexArrow(2,110);

   SetIndexBuffer(0,RSI_buf);
   SetIndexBuffer(1,Sell_buf);
   SetIndexBuffer(2,Buy_buf);

   SetIndexEmptyValue(1,0);
   SetIndexEmptyValue(2,0);

   IndicatorDigits(Digits);

   string IndName="RSI-int("+(string)RSI_per+")";
   IndicatorShortName(IndName);

   SetIndexLabel(0,"RSI");

   SetIndexDrawBegin(0,RSI_per);
   return (0);
  }
// Calculation
int start()
  {

   double
   RSI;

   int
   counted_bars=IndicatorCounted(),
   limit;

   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;

   for(int i=limit-1;i>=0;i--)
     {
      if(i+1>=limit)continue;
      RSI=iRSI(NULL,0,RSI_per,PRICE_CLOSE,i);
      RSI_buf[i]=RSI;

      Sell_buf[i]=0;
      Buy_buf[i]=0;
      if(Sell_buf[i+1]>0) pvs=-1;
      else if(Buy_buf[i+1]>0) pvs=1;
      else pvs=0;

      switch(pvs)
        {
         case 0:
            if(RSI <= RSI_LT) Buy_buf[i] = 95;
            if(RSI >= RSI_UT) Sell_buf[i] = 95;
            break;
         case 1:
            if(RSI<RSI_LT+RSI_BT) Buy_buf[i]=90;
            else Buy_buf[i]=0;
            break;
         case -1:
            if(RSI>RSI_UT-RSI_BT) Sell_buf[i]=90;
            else Sell_buf[i]=0;
            break;
        }

     }
   return (0);
  }
//+------------------------------------------------------------------+
 
Sergey Gritsay:
Спасибо Вам большое за помощь! Заодно поправили некорректное задание имени индикатора, очень признателен. Анализирую свою ошибку.