Индикатор ALMA RSI - перенос с Pine (TradingView) на MT5

 

Всем доброго времени суток. 

Имеется код индикатора - некоторого переработанного RSI (автор ): 

//@version=4
study(title="ALMA RSI", shorttitle="ALMA-RSI", format=format.price, precision=2)

src = input(close, "Source"),
len = input(14, "Length", minval=1)
offset = input(0.7, "ALMA Offset", step=0.05)
sigma = input(6, "ALMA Sigma")

up = alma(max(change(src), 0), len, offset, sigma)
down = alma(-min(change(src), 0), len, offset, sigma)
rsi = down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))

plot(rsi, color=color.lime)
band1 = hline(75)
band0 = hline(25)
fill(band1, band0, color=color.lime, transp=90)

Основное действие в этой строке:

alma(max(change(src), 0), len, offset, sigma)

Насколько понял функции Pine - берем исходный массив цен, вычисляем разность цен x[i+1] - x[i] в отдельный массив, выбираем максимальное значение в этом массиве, выполняем сглаживание скользящей средней Арно Легу. 

Для справки ALMA - Arnaud Legoux Moving Average, код из того же Pine: 

pine_alma(series, windowsize, offset, sigma) =>
    m = offset * (windowsize - 1)
    //m = floor(offset * (windowsize - 1)) // Used as m when floor=true
    s = windowsize / sigma
    norm = 0.0
    sum = 0.0
    for i = 0 to windowsize - 1
        weight = exp(-1 * pow(i - m, 2) / (2 * pow(s, 2)))
        norm := norm + weight
        sum := sum + series[windowsize - i - 1] * weight
    sum / norm

В MQL новичок, надеюсь здесь наведут на мысли как написать данный индикатор для терминала МТ5. Больше всего интересует строка, "alma(max(change(src), 0), len, offset, sigma) ", написать бы математически правильно её - получится и остальное. Пока что не работающее вот это:

#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
#property indicator_width1  2

#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID

#property indicator_level1  13
#property indicator_level2  87
//---- входные параметры индикатора
input int      ALMAPeriod = 14; //
input int      ALMASigma = 6; //
input double   ALMAOffset = 0.25; //

//---- объявление динамического массива, который будет в
// дальнейшем использован в качестве индикаторного буфера
double ExtLineBuffer[];
double Mass1[], Mass2[];
      
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//----+
//---- превращение динамического массива ExtLineBuffer в индикаторный буфер
   SetIndexBuffer(0, ExtLineBuffer, INDICATOR_DATA);
   
   SetIndexBuffer(1, Mass1, INDICATOR_CALCULATIONS);
   SetIndexBuffer(2, Mass2, INDICATOR_CALCULATIONS);
   
   ArrayInitialize(Mass1, 0);
   ArrayInitialize(Mass2, 0);

//----+
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(
   const int rates_total,    // количество истории в барах на текущем тике
   const int prev_calculated,// количество истории в барах на предыдущем тике
   const int begin,          // номер начала достоверного отсчёта баров
   const double &price[]     // ценовой массив для расчёта индикатора
)
  {
//----+
//---- проверка количества баров на достаточность для расчёта
   if(rates_total < ALMAPeriod - 1 + begin)
      return(0);

//---- объявления локальных переменных
   int first, bar, iii, i2;
   double m, s, sum1, sum2, norm, weight, A_RSI, up0, down0, up, down;

//---- расчёт стартового номера first для цикла пересчёта баров
   if(prev_calculated == 0)  // проверка на первый старт расчёта индикатора
      first = ALMAPeriod - 1 + begin; // стартовый номер для расчёта всех баров
   else
      first = prev_calculated - 1; // стартовый номер для расчёта новых баров

//---- основной цикл расчёта индикатора
   for(bar = first; bar < rates_total; bar++)
     {
      m = ALMAOffset * (ALMAPeriod - 1);
      s = ALMAPeriod / ALMASigma;
      norm = 0.0;
      sum1 = 0.0;
      sum2 = 0.0;
      int copied;
      for(iii = 0; iii < ALMAPeriod - 1; iii++)
        {
         copied = CopyBuffer(PRICE_CLOSE, 0, iii, ALMAPeriod, Mass1);
         for(i2 = 0; i2 < ALMAPeriod - 2; i2++)
           {
               Mass2[i2] = Mass1[i2 + 1] - Mass1[i2];
           }

         up0 = ArrayMaximum(Mass2, 0, 0);
         down0 = - ArrayMinimum(Mass2, 0, 0);
         weight = MathExp(-1 * MathPow(iii - m, 2) / (2 * MathPow(s, 2)));
         norm += weight;
         sum1 += up0 * weight;
         sum2 += down0 * weight;
        }
      up = up0/norm;
      down = down0/norm;
      A_RSI = down == 0 ? 100 : up == 0 ? 0: 100 - (100 / (1 + up/down));
      ExtLineBuffer[bar] = A_RSI;
     }
//----+
   return(rates_total);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
 
qadexys:

Основное действие в этой строке:

Насколько понял функции Pine - берем исходный массив цен, вычисляем разность цен x[i+1] - x[i] в отдельный массив, выбираем максимальное значение в этом массиве, выполняем сглаживание скользящей средней Арно Легу. 

max(change(src), 0), это не максимальное в массиве, а отбор положительных значений - вместо отрицательных берется ноль. Строкой ниже (-min(change(src), 0)) отбираются только отрицательные и у них убирается знак.