Индикатор Relative Strength Index

В данной статье будет подробно разобрана работа индикатора Relative Strength Index с точки зрения программирования на языке LCRYP.

Индикатор Relative Strength Index

Глобальные переменные

В первой строке объявлены глобальные переменные (Length, Shift, ApplyToPrice, LimitBars). В этих переменных будут храниться входные параметры, которые может задавать пользователь. Ими можно будет пользоваться во всех функциях программы. Но нужно помнить, что в каждой функции их нужно инициировать.

int Length,Shift,ApplyToPrice,LimitBars;

Рассмотрим функцию OnInit

В первых строках используется команда s_buff. С ее помощью создается один буфер с индексом 0 - для вывода информации RSI. Тип отображения данных буфера - под ценовым графиком, цвет - Green. В следующих строках используются команды t_ind_min и t_ind_max, они задают максимальное (100) и минимальное (0) пороговые значения для отображения. Команда t_ind_a_lev добавляет две линии на уровнях 30 и 70. В следующих строках используется команда s_par, которая устанавливает набор входных данных для пользователя. Входные данные индексируются от 0 до 3 (используется 4 входных параметра). Также команда s_par задает тип для каждого поля, название, которое будет отображаться, и значение по умолчанию. На этом работа данной части программы завершена. 

int OnInit()
  {
   s_buff(0,3,1,0,"Green","Green","Green");
   t_ind_min(0,0);
   t_ind_max(0,100);
   t_ind_a_lev(0,0,1,2,"Green",30);
   t_ind_a_lev(0,1,1,2,"Green",70);
   s_par(0,"int","Length",12);
   s_par(1,"int","Shift",0);
   s_par(2,"int","Apply to Price",1);
   s_par(3,"int","LimitBars",1000);
  }

Рассмотрим функцию OnBar

В начале функции нужно узнать входные параметры с помощью команды g_par и сохранить их в соответствующие глобальные переменные согласно индексов, описанных в функции OnInit. В следующих строках происходят некоторые проверки и коррекция входных значений.

   Length=g_par(0);
   Shift=g_par(1);
   ApplyToPrice=g_par(2);
   LimitBars=g_par(3);
   if(Length<1){Length=1;}
   if(Shift<0){Shift=0;}
   if(Shift>Count-1-Length){Shift=Count-1-Length;}
   if(ApplyToPrice<0){ApplyToPrice=0;}
   if(ApplyToPrice<6){ApplyToPrice=6;}
   ShowName();

После чего используется пользовательская функция ShowName, которая выводит название индикатора с параметрами на окно чарта, используя команды prt и prt_a.

int ShowName()
  {
   prt(0,"RSI [");
   prt_a(0,Length);prt_a(0,", ");
   prt_a(0,Shift);prt_a(0,", ");
   prt_a(0,ApplyToPrice);
   prt_a(0,"]");
  }

Дальше несколько дополнительных условий:

if(ReCount>LimitBars){ReCount=LimitBars;}

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

if(ReCount<1){return -1;}

Условие завершает работу функции, если нет новых баров для пересчета.

Следующими объявлены локальные переменные ExtPosBuffer, ExtNegBuffer, ExtRSIBuffer, в которых будут храниться текущие рассчитанные значения. Основная часть функции - цикл, который проходит по всем барам ценового графика.

   for(i=ReCount-1;i>=0;i=i-1)
     {
      ExtPosBuffer=avgdif(i, Length, Shift, Count, ApplyToPrice, 1);
      ExtNegBuffer=avgdif(i, Length, Shift, Count, ApplyToPrice, -1);
      if(ExtNegBuffer!=0.0)
        {
         ExtRSIBuffer=100.0-(100.0/(1+ExtPosBuffer/ExtNegBuffer));
        }
      else
        {
         if(ExtPosBuffer!=0.0)
           {
            ExtRSIBuffer=100.0;
           }
         else
           {
            ExtRSIBuffer=50.0;
           }
        }
      s_dbuff(0,i,ExtRSIBuffer,0,0,"",0);
     }

В цикле последовательно перебираются все бары и рассчитываются значения ExtPosBuffer и ExtNegBuffer, используя команду avgdif. Дальше нехитрый алгоритм производит манипуляции с полученными данными с результатом в переменной ExtRSIBuffer. С помощью команды s_dbuff значения переменной ExtRSIBuffer попадают в буфер с индексом 0 и отображаются под графиком.

Функция OnTick

Функция не используется, но сама функция должна присутствовать в теле программы.

int OnTick()
  {
  }

Как можно использовать эту функцию в контексте данного индикатора? Если функция OnBar учитывает нулевой бар, то отображаемый результат работы на нем будет не корректен, поскольку цена на нулевом баре не сформирована до конца. Тогда можно при пересчете баров или не учитывать нулевой бар, или на каждом тике делать перерасчет, чтобы постоянно корректировать значением индикатора на нулевом баре по мере формирования нулевого бара. 

Листинг программы Relative Strength Index:

//+------------------------------------------------------------------+
//|                                    Relative Strength Index.lcryp |
//|                                     Copyright 2017, TerminalCoin |
//|                                             www.terminalcoin.com |
//+------------------------------------------------------------------+
int Length,Shift,ApplyToPrice,LimitBars;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   s_buff(0,3,1,0,"Green","Green","Green");
   t_ind_min(0,0);
   t_ind_max(0,100);
   t_ind_a_lev(0,0,1,2,"Green",30);
   t_ind_a_lev(0,1,1,2,"Green",70);
   s_par(0,"int","Length",12);
   s_par(1,"int","Shift",0);
   s_par(2,"int","Apply to Price",1);
   s_par(3,"int","LimitBars",1000);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnBar()
  {
   Length=g_par(0);
   Shift=g_par(1);
   ApplyToPrice=g_par(2);
   LimitBars=g_par(3);
   if(Length<1){Length=1;}
   if(Shift<0){Shift=0;}
   if(Shift>Count-1-Length){Shift=Count-1-Length;}
   if(ApplyToPrice<0){ApplyToPrice=0;}
   if(ApplyToPrice<6){ApplyToPrice=6;}
   ShowName();
   if(ReCount>LimitBars)
     {
      ReCount=LimitBars;
     }
   if (ReCount<1){return -1;}
   double ExtPosBuffer,ExtNegBuffer,ExtRSIBuffer;
   int i,j;
   for(i=ReCount-1;i>=0;i=i-1)
     {
      ExtPosBuffer=avgdif(i, Length, Shift, Count, ApplyToPrice, 1);
      ExtNegBuffer=avgdif(i, Length, Shift, Count, ApplyToPrice, -1);
      if(ExtNegBuffer!=0.0)
        {
         ExtRSIBuffer=100.0-(100.0/(1+ExtPosBuffer/ExtNegBuffer));
        }
      else
        {
         if(ExtPosBuffer!=0.0)
           {
            ExtRSIBuffer=100.0;
           }
         else
           {
            ExtRSIBuffer=50.0;
           }
        }
      s_dbuff(0,i,ExtRSIBuffer,0,0,"",0);
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnTick()
  {
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int ShowName()
  {
   prt(0,"RSI [");
   prt_a(0,Length);prt_a(0,", ");
   prt_a(0,Shift);prt_a(0,", ");
   prt_a(0,ApplyToPrice);
   prt_a(0,"]");
  }
//+------------------------------------------------------------------+

Назад

TerminalCoin

2018-10-03 06:52:48