English Deutsch 日本語
preview
Переосмысление индикаторов MQL5 и MetaTrader 5

Переосмысление индикаторов MQL5 и MetaTrader 5

MetaTrader 5Индикаторы |
387 1
Omega J Msigwa
Omega J Msigwa

Введение

MQL5 больше не является простым языком программирования, каким он был раньше для создания простых торговых роботов. Язык стал более совершенным, и в настоящее время вы можете создавать торговые программы большой сложности, развертывать и тестировать их гораздо более надежным и удобным способом.

Все мы в какой-то момент своего торгового пути использовали либо «нативные", либо "пользовательские индикаторы". MetaTrader5 имеет простой интерфейс для загрузки и прикрепления индикатора к графику, что позволяет трейдерам (в основном, трейдерам, работающим вручную) удобно анализировать рынки,  используя индикаторы, однако, когда дело доходит до алгоритмической торговли, важно не то, что вы видите на графике, а расчеты индикатора.

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

Когда дело доходит до алгоритмической торговли, чтобы использовать определенный индикатор, например Простую скользящую среднюю (SMA) за период 20, вам необходимо:

int sma_handle; //Declare an indicator handle
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   sma_handle = iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE); //Initialize the indicator inside the OnInit function

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

   double sma_buffer[];
   CopyBuffer(sma_handle, 0, 0, 1, sma_buffer); //Copy the indicator buffers inside the Ontick function
  }

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

Основываясь на этом подходе, утверждается, что индикатор скользящей средней (MA) должен применяться только к любой одной из ценовых констант, указанных в документации.

ID

Описание

PRICE_CLOSE

Цена закрытия

PRICE_OPEN

Цена открытия

PRICE_HIGH

Максимальная цена за период

PRICE_LOW

Минимальная цена за период

PRICE_MEDIAN

Средняя цена = (максимум + минимум)/2

PRICE_TYPICAL

Типичная цена (максимум + минимум + закрытия)/3

PRICE_WEIGHTED

Средняя цена (максимум + минимум + закрытия + закрытия)/4

Не говоря уже о том, что вы ограничены  методами сглаживания , описанными в документации.

ID

Описание

MODE_SMA

Простое усреднение

MODE_EMA

Экспоненциальное усреднение

MODE_SMMA

Сглаженное усреднение

MODE_LWMA

Линейно-взвешенное усреднение

Что происходит, когда вы хотите попробовать что-то нестандартное?  Например, если вы хотите рассчитать скользящую среднюю разницы между ценами максимума и минимума, это невозможно на основе текущего подхода, поскольку мы ограничены в том, что мы можем делать с индикаторами.

Я понимаю, что большинство индикаторов являются такими, какие они есть, исходя из того, как они были определены и выведены математически, но разве не было бы здорово, если бы мы могли передавать индикаторам различные входные данные и параметры для наблюдения за новыми паттернами на рынке?

Вдохновленный библиотекой технического анализа (TA-Lib)  на языке python, этот инновационный подход направлен на то, чтобы предоставить трейдерам и разработчикам алгоритмических систем больше контроля над тем, какая информация поступает в индикатор для немедленных расчетов.

В настоящей статье мы реализуем несколько индикаторов (наиболее часто используемых), используя этот подход "подключи и работай".

Группировка по категориям.

Индикаторы трендов

  • Индикатор Простая скользящая средняя
  • Индикатор Экспоненциальная скользящая средняя
  • Полосы Боллинджера
  • Индикатор Parabolic SAR
  • Стандартное отклонение

Осцилляторы

  • Схождение/расхождение скользящих средних (MACD)
  • Индекс относительной силы (RSI)
  • Стохастические осцилляторы
  • Средний истинный диапазон (ATR)
  • Индикатор Momentum

Билл Вильямс

  • Индикатор Accelerator Oscillator
  • Индикатор Awesome Oscillator


Простая скользящая средняя (SMA) Индикатор

Это один из наиболее часто используемых технических индикаторов. Он вычисляет среднее значение ценового ряда за определенный период времени.

Задаются формулой:

sma formula

Где:

  •  это цены (например (цены закрытия) за   период.
  •  это период SMA.

Мы можем легко реализовать эту формулу в векторизованной функции.

File:  ta-lib.mqh

vector CTrendIndicators::SMA(const vector &price, uint period, uint shift = 0)
  {
   uint size = (uint)price.Size();

   if(!CheckShiftPeriod(size, period, shift))
      return price;

//---

   vector ma(size);
   ma.Fill(NaN);

   for(uint i = shift + period - 1; i < size; i++) //Loop through all the prices considering the period and shift
     {
      double sum = 0;
      for(uint j = i - period + 1; j <= i; j++)
         sum += price[j]; //sum of the prices

      ma[i] = sum / period; //divided by period to find the mean of that period
     }

   return ma;
  }

Именно так рассчитывается индикатор простая скользящая средняя, без использования буферов, без проверки ошибок MQL5 при загрузке индикатора для определенного символа и т.д. что может быть утомительно.

Этот минималистский подход проверяет только корректность значений сдвига и периода, и если это так, функция продолжает вычисления индикатора, возвращая рассчитанные значения в векторной форме. Я решил использовать векторный формат, чтобы получить больше контроля и гибкости в отношении конечного результата.

Поскольку все функции в наших классах индикаторов являются статическими, мы можем легко получить доступ к значениям индикаторов в наших программах на MQL5, например, с помощью простого скрипта.

Файл: Custom Indicators test script.mq5

#include <ta-lib.mqh>
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
     vector prices = {1,2,3,4,5,6,7,8,9,10};
     int period = 3;
     
     Print("SMA values: ", CTrendIndicators::SMA(prices, period)); 
  }

Результаты

2025.01.21 09:57:35.727 Custom Indicators test script (EURUSD,H1)       SMA values: [nan,nan,2,3,4,5,6,7,8,9]

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


Экспоненциальная скользящая средняя (EMA) Индикатор

EMA рассчитывается как среднее значение ценового ряда за определенное количество периодов, точно так же, как и SMA, но он придает больший вес последним ценам, что делает его более чувствительным к изменениям цен по сравнению с простой скользящей средней (SMA).

Задается формулой.

 

Где:

  •  — это EMA в момент времени t.
  • Pt - это цена в момент времени t.
  •  — это EMA предыдущего периода. 
  •  является сглаживающим фактором (где  n - это период)

Мы можем это реализовать на MQL5 следующим образом:

Файл: ta-lib.mqh

vector CTrendIndicators::EMA(const vector &price, uint period, uint shift = 0)
  {
   uint size = (uint)price.Size();

   if(!CheckShiftPeriod(size, period, shift))
      return price;

//---

   double alpha = 2.0 / (period + 1.0);    // Smoothing factor

   vector res(size);
   res.Fill(NaN);

// Initialize the EMA with the SMA of the first period

   vector sma = SMA(price, period, shift);
   res[period - 1 + shift] = sma[period - 1 + shift];

// Calculate EMA for the rest of the prices

   for(ulong i = period + shift; i < size; i++)
      res[i] = alpha * price[i] + (1 - alpha) * res[i - 1];

   return res;
  }

Мы можем получить рассчитанные значения индикатора аналогично тому, как мы это делали для SMA.

Файл: Custom Indicators test script.mq5 

void OnStart()
  {
     vector prices = {1,2,3,4,5,6,7,8,9,10};
     int period = 3;
     
     Print("EMA values: ", CTrendIndicators::EMA(prices, period));
  }

Результаты

2025.01.21 10:19:54.291 Custom Indicators test script (EURUSD,H1)       EMA values: [nan,nan,2,3,4,5,6,7,8,9]

Мы рассчитали индикаторы «Простая скользящая средняя» (SMA) и «Экспоненциальная скользящая средняя» (EMA) отдельно, в отличие от того, как они рассчитываются внутри встроенного  индикатора IMA, который предоставляет возможность выбора метода сглаживания, который вы предпочитаете.

Такой раздельный подход требует написания дополнительных строк кода для реализации всех методов сглаживания индикаторов скользящей средней.

Функции для методов сглаживания, таких как  MODE_SMMA (Сглаженное усреднение) и (MODE_LWMA) Линейно-взвешенное усреднение , еще предстоит реализовать в библиотеке, поскольку я полагаю, что они не так широко используются, как их аналоги (методы сглаживания SMA и EMA).


Индикатор Bollinger Bands

Это индикатор волатильности, состоящий из трех полос.

  1. Средняя полоса  - это простая скользящая средняя (SMA) цен закрытия за определенный период.

  2. Верхняя полоса  - это средняя полоса плюс величина, кратная стандартному отклонению цен закрытия за тот же период.

    Нижняя полоса  - это средняя полоса, минус значение, кратное стандартному отклонению цен закрытия за тот же период.

    Где:

    •  обычно равно 2 (стандартное значение для полос Боллинджера),
    •  это период для расчета SMA и стандартного отклонения.

    Поскольку этот индикатор должен возвращать три (3) одномерных (1D) значения, известных как буферы при использовании встроенного индикатора Полосы Боллинджера, давайте сделаем так, чтобы эта функция возвращала структуру из 3 векторов.

    Файл: ta-lib.mqh

    struct BB_res_struct
      {
       vector            upper_band;
       vector            lower_band;
       vector            middle_band;
      };
    BB_res_struct CTrendIndicators::BollingerBands(const vector &price, uint period, uint shift = 0, double k = 2.0)
      {
       uint size = (uint)price.Size();
    
       BB_res_struct res;
    
    //--- Check for valid parameters
       if(!CheckShiftPeriod(size, period, shift))
          return res;
    
    //--- Initialize vectors
    
       res.upper_band.Resize(size);
       res.lower_band.Resize(size);
    
       res.upper_band.Fill(NaN);
       res.lower_band.Fill(NaN);
    
    //--- Calculate the middle band (SMA)
    
       res.middle_band = SMA(price, period, shift);
    
    //--- Calculate the upper and lower bands
    
       for(uint i = shift + period - 1; i < size; i++)
         {
          double sum_squared_diff = 0;
          for(uint j = i - period + 1; j <= i; j++)
            {
             sum_squared_diff += MathPow(price[j] - res.middle_band[i], 2);
            }
    
          double std_dev = MathSqrt(sum_squared_diff / period);
    
          res.upper_band[i] = res.middle_band[i] + (k * std_dev);
          res.lower_band[i] = res.middle_band[i] - (k * std_dev);
         }
    
       return res;
      }

    Ниже показано, как можно легко реализовывать индикатор Полосы Боллинджера и получать его значения.

    Файл: Custom Indicators test script.mq5 

    void OnStart()
      {
         vector prices = {1,2,3,4,5,6,7,8,9,10};
         int period = 3;
         
         BB_res_struct bb;
         bb = CTrendIndicators::BollingerBands(prices,period,0,2);
         
         Print("BB upper: ",bb.upper_band);
         Print("BB middle: ",bb.middle_band);
         Print("BB lower: ",bb.lower_band);
      }

    Результаты

    RL      0       11:39:21.000    Custom Indicators test script (EURUSD,H1)       BB upper: [nan,nan,3.632993161855452,4.632993161855453,5.632993161855453,6.632993161855453,7.632993161855453,8.632993161855453,9.632993161855453,10.63299316185545]
    RO      0       11:39:21.000    Custom Indicators test script (EURUSD,H1)       BB middle: [nan,nan,2,3,4,5,6,7,8,9]
    FF      0       11:39:21.000    Custom Indicators test script (EURUSD,H1)       BB lower: [nan,nan,0.3670068381445479,1.367006838144548,2.367006838144548,3.367006838144548,4.367006838144547,5.367006838144547,6.367006838144547,7.367006838144547]
    


    Индикатор Parabolic SAR (Стоп-переворот)

    Это следующий за трендом индикатор, используемый для выявления потенциальных разворотов на рынке. Он размещает точки выше или ниже цены в зависимости от направления тренда.

    Задается формулой.

    Для восходящего тренда

    Для нисходящего тренда

    Где:

    •  = Значение SAR за следующий период
    •  = Коэффициент ускорения (начинается со значения по умолчанию, например, 0,02 и увеличивается на 0,02 при каждом достижении нового максимума/минимума. До максимального значения 0,2)
    •  = Экстремальная точка (самый высокий максимум при восходящем тренде, самый низкий минимум при нисходящем тренде)

    В MQL5 этот индикатор можно реализовать следующим образом:

    Файл: ta-lib.mqh

    vector CTrendIndicators::ParabolicSAR(const vector &high,
                                          const vector &low,
                                          const vector &close,
                                          double step = 0.02,
                                          double max = 0.2)
      {
       uint size = (uint)close.Size();
       vector psar(size);
       psar.Fill(NaN);
    
    // Initialize variables
    
       double AF = step;    // Acceleration Factor
       double EP = high[0];      // Extreme Point
       double SAR = low[0];      // Initial SAR
       bool isUptrend = true;    // Assume uptrend at the start
    
    // Calculate Parabolic SAR
    
       for(uint i = 0; i < size; i++)
         {
          // Update SAR
          if(isUptrend)
             SAR = SAR + AF * (EP - SAR);
          else
             SAR = SAR + AF * (SAR - EP);
    
          // Determine if trend changes
          if(isUptrend && SAR > low[i])
            {
             // Switch to downtrend
             isUptrend = false;
             SAR = EP;            // Reset SAR to the most recent EP
             EP = low[i];         // Reset EP
             AF = step;      // Reset AF
            }
    
          else
             if(!isUptrend && SAR < high[i])
               {
                // Switch to uptrend
                isUptrend = true;
                SAR = EP;            // Reset SAR to the most recent EP
                EP = high[i];        // Reset EP
                AF = step;      // Reset AF
               }
    
          // Update EP and AF
          if(isUptrend)
            {
             if(high[i] > EP)
               {
                EP = high[i];
                AF = MathMin(AF + step, max);
               }
            }
          else
            {
             if(low[i] < EP)
               {
                EP = low[i];
                AF = MathMin(AF + step, max);
               }
            }
    
          // Store the SAR value
          psar[i] = SAR;
         }
    
       return psar;
      }

    В отличие от двух предыдущих индикаторов отслеживания тренда, которые могут получать один вектор в качестве входных данных для цены, parabolic SAR учитывает три (3) значения цены (максимум, минимум и цену закрытия). 

    Файл: Custom Indicators test script.mq5

    void OnStart()
      {  
         vector close = {1,2,3,4,5,6,7,8,9,10};
         vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5};
         vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5};
         
         Print("Parabolic SAR values: ", CTrendIndicators::ParabolicSAR(high,low,close,0.02,0.2)); 
      }

    Результаты

    2025.01.21 11:11:03.525 Custom Indicators test script (EURUSD,H1)       Parabolic SAR values: [1.5,0.5,0.54,0.6584000000000001,0.8888960000000001,1.25778432,1.782005888,2.46816518144,3.3126220560384,4.302602527072256]
    


    Индикатор Standard Deviation

    Этот индикатор измеряет величину отклонения или дисперсии цены от ее среднего значения. Этот показатель часто используется для оценки волатильности рынка.

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

    Задается формулой.

    Где:

    •  = Стандартное отклонение
    • n = Период
    •  = Ценовая отметка
    •  = Среднее значение точек данных 

    Мы можем это реализовать этот индикатор на MQL5 следующим образом:

    Файл: ta-lib.mqh

    vector CTrendIndicators::StandardDeviation(const vector &price, uint period, uint shift = 0)
      {
       uint size = (uint)price.Size();
    
    // Check if the period and shift are valid
       if(!CheckShiftPeriod(size, period, shift))
          return price;
    
    // Initialize standard deviation vector
       vector std_dev(size);
       std_dev.Fill(NaN);
    
    // Loop through the price data
       for(uint i = shift + period - 1; i < size; i++)
         {
          double sum = 0.0;
          double sum_sq_diff = 0.0;
    
          // Calculate mean
          for(uint j = i - period + 1; j <= i; j++)
             sum += price[j];
          double mean = sum / period;
    
          // Calculate squared differences
          for(uint j = i - period + 1; j <= i; j++)
             sum_sq_diff += MathPow(price[j] - mean, 2);
    
          // Calculate standard deviation
          std_dev[i] = MathSqrt(sum_sq_diff / period);
         }
    
       return std_dev;
      }
    

    Это еще один простой индикатор, который можно назвать следующим образом.

    Файл: Custom Indicators test script.mq5

    void OnStart()
      {
         vector prices = {1,2,3,4,5,6,7,8,9,10};
         int period = 3;
        
         Print("Stddev values: ", CTrendIndicators::StandardDeviation(prices, period));
      }

    Результаты

    2025.01.21 11:55:11.657 Custom Indicators test script (EURUSD,H1)       Stddev values: [nan,nan,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726]
    


    Схождение/расхождение скользящих средних (MACD)

    Этот осциллятор показывает взаимосвязь между двумя скользящими средними цены ценной бумаги. Он широко используется в качестве инструмента технического анализа.

    Задается формулой.

    Главная линия MACD

    Где:

    •  = Экспоненциальная скользящая средняя с более коротким периодом (например, 12)
    •  = Экспоненциальная скользящая средняя с более длинным периодом (например, 26)


    Сигнальная линия

    Это сглаженная ЕМА линии MACD, обычно со значением периода 9

    Гистограмма Macd

    Это разница между линией MACD и сигнальной линией.

    Аналогично тому, как мы возвращали рассчитанные значения нескольких полос Боллинджера, мы определяем структуру для возврата значений гистограммы MACD, основной и сигнальной линий.

    Файл: ta-lib.mqh 

    struct MACD_res_struct
      {
       vector            main;     // The MACD Line
       vector            signal;   // The Signal Line
       vector            histogram;    // The MACD Histogram
      };
    MACD_res_struct COscillatorIndicators::MACD(const vector &price, uint fast_ema = 12, uint slow_ema = 26, uint macd_sma = 9, uint shift = 0)
      {
       uint size = (uint)price.Size();
    
       MACD_res_struct res;
       if(!CheckShiftPeriod(size, slow_ema, shift))
          return res;
    
    //--- Calculate EMA(short), EMA(long), and MACD Line
    
       vector fast_ema_vector = CTrendIndicators::EMA(price, fast_ema, shift);
       vector slow_ema_vector = CTrendIndicators::EMA(price, slow_ema, shift);
    
       res.main.Resize(size);
       res.main.Fill(NaN);
    
       for(uint i = 0; i < size; i++)
          res.main[i] = fast_ema_vector[i] - slow_ema_vector[i];
    
    //--- Calculate Signal Line (SMA of MACD Line)
    
       res.signal = CTrendIndicators::SMA(price, macd_sma, shift);
    
    //--- Calculate MACD Histogram
    
       res.histogram.Resize(size);
       res.histogram.Fill(NaN);
    
       for(uint i = 0; i < size; i++)
          res.histogram[i] = res.main[i] - res.signal[i];
    
       return res;
      }

    Мы можем легко получить расчетные значения осциллятора MACD внутри тестового скрипта следующим образом.

    Файл: Custom Indicators test script.mq5 

    void OnStart()
      {
         vector prices = {1,2,3,4,5,6,7,8,9,10};
    
         MACD_res_struct macd;
         
         macd = COscillatorIndicators::MACD(prices,2,3,4);
         
         Print("MACD main: ", macd.main); 
         Print("MACD signal: ", macd.signal); 
      }

    Результаты

    RD      0       12:28:51.368    Custom Indicators test script (EURUSD,H1)       MACD main: [nan,nan,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5]
    HO      0       12:28:51.368    Custom Indicators test script (EURUSD,H1)       MACD signal: [nan,nan,nan,2.5,3.5,4.5,5.5,6.5,7.5,8.5]
    


    Индикатор относительной силы (RSI)

    Это импульсный осциллятор, измеряющий скорость и величину движения цены. Он колеблется между 0 и 100, трейдеры используют его для определения условий перекупленности и перепроданности на рынке.

    Расчет индикатора RSI включает в себя следующие этапы:

    01: Определение средней прибыли и средних убытков за определенный период

    02: Расчет относительной силы (RS)

    03: Вычисление RSI

    Реализация на MQL5

    vector COscillatorIndicators::RSI(const vector &price, uint period, uint shift = 0)
      {
       uint size = (uint)price.Size();
    
    //--- Check for valid parameters
       if(!CheckShiftPeriod(size, period, shift))
          return price;
    
    //--- Initialize vectors
       vector rsi(size), gains(size), losses(size);
       rsi.Fill(NaN);
       gains.Fill(0.0);
       losses.Fill(0.0);
    
    //--- Calculate gains and losses
       for(uint i = shift + 1; i < size; i++)
         {
          double change = price[i] - price[i - 1];
          gains[i] = (change > 0) ? change : 0;
          losses[i] = (change < 0) ? -change : 0;
         }
    
    //--- Initialize first average gain and loss (simple average for the first period)
       double avg_gain = 0, avg_loss = 0;
       for(uint i = shift + 1; i < shift + 1 + period; i++)
         {
          avg_gain += gains[i];
          avg_loss += losses[i];
         }
       avg_gain /= period;
       avg_loss /= period;
    
    //--- Compute RSI for the rest of the periods
       for(uint i = shift + period; i < size; i++)
         {
          // Apply smoothing for average gain and loss
          avg_gain = ((avg_gain * (period - 1)) + gains[i]) / period;
          avg_loss = ((avg_loss * (period - 1)) + losses[i]) / period;
    
          // Calculate RSI
          double rs = (avg_loss == 0) ? 0 : avg_gain / avg_loss;
          rsi[i] = (avg_loss == 0) ? 100 : (100 - (100 / (1 + rs)));
         }
    
       return rsi;
      }

    Ниже показано, как вы можете получить значения из индикатора RSI.

    void OnStart()
      {
         vector prices = {1,2,3,4,5,6,7,8,9,10};
         int period = 3;
         
         Print("RSI values: ", COscillatorIndicators::RSI(prices,period)); 
      }

    Результаты

    2025.01.21 12:51:29.640 Custom Indicators test script (EURUSD,H1)       RSI values: [nan,nan,nan,100,100,100,100,100,100,100]
    


    Индикатор Stochastic Odcillator

    Это импульсный индикатор, сравнивающий цену закрытия ценной бумаги с ее ценовым диапазоном за указанный период. 

    Формула расчета этого индикатора состоит из:

    Линия %K

    Где:

    •  это текущая цена закрытия
    •  это самая низкая цена за весь ретроспективный период
    •  это самая высокая цена за весь ретроспективный период

    Линия %D

    Это скользящая средняя линии %K, обычно использующая простую скользящую среднюю SMA за 3 периода

    Ниже показано, как реализовать этот индикатор на MQL5.

    Stochastic_struct COscillatorIndicators::StochasticOscillator(const vector &high, const vector &low, const vector &close, uint k_period = 5, uint d_period = 3, uint period = 3, uint shift = 0)
      {
       uint size = (uint)close.Size();
    
       Stochastic_struct res;
    
    // Check for valid parameters
       if(!CheckShiftPeriod(size, period, shift))
          return res;
    
    // Initialize vectors for %K and %D
       vector K(size), D(size);
       K.Fill(NaN);
       D.Fill(NaN);
    
    // Calculate %K
       for(uint i = shift + period - 1; i < size; i++)
         {
          double H_max = -DBL_MAX, L_min = DBL_MAX;
    
          // Find the highest high and the lowest low over the lookback period
          for(uint j = i - period + 1; j <= i; j++)
            {
             H_max = MathMax(H_max, high[j]);
             L_min = MathMin(L_min, low[j]);
            }
    
          // Calculate %K
          double K_value = (H_max - L_min != 0) ? ((close[i] - L_min) / (H_max - L_min)) * 100 : 0;
          K[i] = K_value;
         }
    
    // Smooth %K with a simple moving average (k_period)
       vector smoothedK(size);
       smoothedK.Fill(NaN);
    
       for(uint i = shift + k_period - 1; i < size; i++)
         {
          double sum = 0;
          for(uint j = i - k_period + 1; j <= i; j++)
            {
             sum += K[j];
            }
          smoothedK[i] = sum / k_period;
         }
    
    // Calculate %D (3-period moving average of %K)
    
       D = CTrendIndicators::SMA(smoothedK, period, shift);
    
       res.main = K;
       res.signal = D;
    
       return res;
      }
    

    Мы возвращаем сигнал и основную линию в виде структуры.

    void OnStart()
      {  
         vector close = {1,2,3,4,5,6,7,8,9,10};
         vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5};
         vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5};
         
         Stochastic_struct stoch;
         stoch = COscillatorIndicators::StochasticOscillator(high,low,close,5,3,3);
         
         Print("Stoch main: ", stoch.main); 
         Print("Stoch signal: ", stoch.signal); 
      }


    Индикатор Средний истинный диапазон (ATR)

    Это полезный индикатор для понимания волатильности рынка. Он измеряет средний диапазон между высокими и низкими ценами за определенный период.

    Задается формулой.

    01: Расчет Истинного диапазона (TR)

    Где:

    • H - максимум текущего периода.
    •  это минимум теущего периода.
    •  это цена закрытия предыдущего периода.

    02: Расчет индикатора Средний истинный диапазон (ATR)

    ATR - это скользящая средняя истинного диапазона за определенный период.

     SMA это Простая скользящая средняя.

    Мы можем это реализовать этот индикатор на MQL5 следующим образом:

    vector COscillatorIndicators::ATR(const vector &high, const vector &low, const vector &close, uint period = 14, uint shift = 0)
      {
       uint size = (uint)close.Size();
    
    // Check for valid parameters
       if(!CheckShiftPeriod(size, period, shift))
          return close;
    
    // Initialize the True Range (TR) and ATR vectors
       vector TR(size);
       TR.Fill(NaN);
    
    // Calculate the True Range for each period
       for(uint i = shift + 1; i < size; i++)
         {
          double H = high[i];
          double L = low[i];
          double C_prev = close[i - 1];
    
          // Calculate the three possible True Range values
          double TR1 = H - L;
          double TR2 = MathAbs(H - C_prev);
          double TR3 = MathAbs(L - C_prev);
    
          // True Range is the maximum of the three
          TR[i] = MathMax(TR1, MathMax(TR2, TR3));
         }
    
    //--- Smooth the True Range using a simple moving average (SMA) over the specified period
    
       return CTrendIndicators::SMA(TR, period, shift);
      }

    Ниже показано, как можно получить значения для этого индикатора.

    void OnStart()
      {  
         vector close = {1,2,3,4,5,6,7,8,9,10};
         vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5};
         vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5};
         
         Print("ATR values: ", COscillatorIndicators::ATR(high,low,close,3)); 
      }

    Результаты

    2025.01.21 13:57:59.943 Custom Indicators test script (EURUSD,H1)       ATR values: [nan,nan,nan,1.5,1.5,1.5,1.5,1.5,1.5,1.5]
    


    Индикатор Momentum

    Это простой индикатор, используемый для измерения скорости, с которой меняется цена актива в течение определенного периода. Он помогает определять тренды и потенциальные точки разворота трендов.

    Задается простой формулой.

    Где:

    • Momentum(t) = значение импульса в период времени t
    • Price(t) = текущая цена
    • Price(t - n) = Цена на n периодов назад
    • n = период, за который рассчитывается импульс

    В некоторых вариантах для расчета импульса используется соотношение.

    Мы реализуем индикатор momentum, используя этот вариант.

    Реализация на MQL5

    vector COscillatorIndicators::MomentumIndicator(const vector &price, uint period, uint shift = 0)
      {
       uint size = (uint)price.Size();
    
    // Check for valid input
       if(!CheckShiftPeriod(size, period, shift))
          return price;
    
    // Initialize the momentum vector
       vector momentum(size);
       momentum.Fill(NaN);
    
    // Calculate Momentum
       for(uint i = shift + period; i < size; i++)
         {
          //momentum[i] = price[i] - price[i - period]; // Momentum difference formula
    
          // using the ratio formula:
          momentum[i] = (price[i] / price[i - period]) * 100;
         }
    
       return momentum;
      }


    Индикатор Awesome Oscillator

    Это импульсный индикатор, вычисляющий разницу между двумя простыми скользящими средними (SMA) средней цены.

    Задается формулой:

    Где:

    •  = SMA с более коротким периодом (обычно 5)
    •  = SMA с более длинным периодом (обычно 34)

    Ниже представлена реализация на MQL5.

    vector CBillWilliamsIndicators::AwesomeOscillator(const vector &high, const vector &low, uint fast_period = 5, uint slow_period = 34, uint shift = 0)
      {
       uint size = (uint)high.Size();
       if(size != low.Size())
          return vector::Zeros(0); // Ensure high and low vectors are of the same size
    
       if(!CheckShiftPeriod(size, slow_period, shift))
          return vector::Zeros(0); // Validate shift and slow period
    
    // Initialize vectors
       vector ao(size), median_price(size);
       ao.Fill(NaN);
       median_price.Fill(NaN);
    
    // Calculate Median Price
       for(uint i = 0; i < size; i++)
          median_price[i] = (high[i] + low[i]) / 2;
    
    // Calculate Fast and Slow SMAs of the Median Price
       vector sma_fast = CTrendIndicators::SMA(median_price, fast_period, shift);
       vector sma_slow = CTrendIndicators::SMA(median_price, slow_period, shift);
    
    // Calculate AO
       for(uint i = 0; i < size; i++)
          ao[i] = sma_fast[i] - sma_slow[i];
    
       return ao;
      }

    Поскольку у нас есть очень простые векторы для высоких и низких цен, мы можем установить быстрый период равным 3, а медленный - 5.

    void OnStart()
      {  
         vector close = {1,2,3,4,5,6,7,8,9,10};
         vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5};
         vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5};
         
         Print("AO values: ", CBillWilliamsIndicators::AwesomeOscillator(high,low,3,5)); 
      }

    Результаты.

    2025.01.21 14:25:50.590 Custom Indicators test script (EURUSD,H1)       AO values: [nan,nan,nan,nan,1,1,1,1,1,1]
    


    Индикатор Accelerator Oscillator

    Индикатор Accelerator Oscillator (AC) это инструмент технического анализа, отслеживающий скорость изменения ценового импульса. Он показывает, ускоряется или замедляется движущая сила рынка, помогая трейдерам предвидеть возможные развороты.

    Он рассчитывается как разница между Awesome Oscillator и 5-периодной простой скользящей средней (SMA) АО.

    Задается приведенной ниже формулой.

    Мы можем это реализовать этот индикатор на MQL5 следующим образом:

    vector CBillWilliamsIndicators::AcceleratorOscillator(const vector &high,
          const vector &low,
          uint ao_period_fast = 5, // Fast period for AO
          uint ao_period_slow = 34, // Slow period for AO
          uint ac_period = 5 // Period for AC SMA
                                                         )
      {
       uint size = (uint)high.Size();
       if(size != low.Size())
          return vector::Zeros(0); // Ensure high and low vectors are of the same size
    
    
    // Validate shift and period
       if(!CheckShiftPeriod(size, ao_period_slow, 0))
          return vector::Zeros(0);
    
    // Calculate AO (Awesome Oscillator)
    
       vector ao = AwesomeOscillator(high, low, ao_period_fast, ao_period_slow);
    
    // Calculate AC (Accelerator Oscillator)
    
       vector ac(size);
       ac.Fill(NaN);
    
       vector ao_sma_ac = CTrendIndicators::SMA(ao, ac_period);
    
       for(uint i = 0; i < size; i++)
          ac[i] = ao[i] - ao_sma_ac[i];
    
       return ac;
      }

    Поскольку Accelerator Oscillator очень похож на Awesome Oscillator, мы можем вызвать его функцию с аналогичными аргументами.

    void OnStart()
      {  
         vector close = {1,2,3,4,5,6,7,8,9,10};
         vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5};
         vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5};
         
    //--- Bill williams indicator
    
         Print("AO values: ", CBillWilliamsIndicators::AwesomeOscillator(high,low,3,5)); 
         Print("AC values: ", CBillWilliamsIndicators::AcceleratorOscillator(high,low,3,5)); 
      }

    Результаты

    MQ      0       14:40:36.296    Custom Indicators test script (EURUSD,H1)       AO values: [nan,nan,nan,nan,1,1,1,1,1,1]
    EL      0       14:40:36.296    Custom Indicators test script (EURUSD,H1)       AC values: [nan,nan,nan,nan,nan,nan,nan,nan,0,0]
    


    Упрощенный сбор данных по индикаторам

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

    Начинаем с получения значений OHLC.

    int size = 1000;
    
    vector open, high, low, close;
    
    open.CopyRates(Symbol(), Period(), COPY_RATES_OPEN, 1, size);
    high.CopyRates(Symbol(), Period(), COPY_RATES_HIGH, 1, size);
    low.CopyRates(Symbol(), Period(), COPY_RATES_LOW, 1, size);
    close.CopyRates(Symbol(), Period(), COPY_RATES_CLOSE, 1, size);

    Начиная с простой скользящей средней за период 20, примененной к ценам открытия.

    vector sma_open = CTrendIndicators::SMA(open, 20); 

    Мы можем без особых усилий собирать различные индикаторы SMA для разных периодов и по разным ценам.

    vector sma_open = CTrendIndicators::SMA(open, 20); 
    vector sma_high = CTrendIndicators::SMA(high, 50);
    vector sma_low = CTrendIndicators::SMA(low, 100);
    vector sma_close = CTrendIndicators::SMA(close, 20);

    Давайте вместо этого поместим их в матрицу и будем наблюдать за ними в целом.

    matrix Indicators(size, 4);
        
    Indicators.Col(CTrendIndicators::SMA(open, 20), 0);
    Indicators.Col(CTrendIndicators::SMA(high, 50), 1);
    Indicators.Col(CTrendIndicators::SMA(low, 100), 2);
    Indicators.Col(CTrendIndicators::SMA(close, 20), 3);
        
    Print("Indicators matrix\n",Indicators);

    Результаты

    NK      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0485715,1.0484514,nan,1.048488]
    LL      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0484425,1.0485544,nan,1.0484265]
    RP      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.048381,1.0486754,nan,1.048299]
    QG      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0483055,1.0488004,nan,1.048152]
    KK      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0481585,1.0489198,nan,1.048296]
    HL      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.048303,1.049033,nan,1.0485255]
    DS      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.048533,1.0491756,nan,1.0487015]
    OK      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.048658,1.0493158,1.0475226,1.0488295]
    KD      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0487895,1.0494628,1.047473,1.0488985]
    JR      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0488575,1.0494916,1.0474256,1.0489465]
    FR      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0489055,1.049475,1.0473723,1.0490045]
    LL      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.048964,1.0494814,1.0473137,1.049052]
    HK      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0490075,1.0494728,1.0472494,1.0491065]
    CF      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.049062,1.0494618,1.0471845,1.049044]
    RE      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0489995,1.0494452,1.047114,1.048892]
    FQ      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.048848,1.0494558,1.047044,1.0487065]
    CL      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0486625,1.0495002,1.0469762,1.0486305]
    DK      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.048586,1.0496014,1.0469234,1.048582]
    EE      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0485375,1.0496714,1.0468866,1.048646]
    RE      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0486015,1.0497982,1.046857200000001,1.04877]
    IP      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0487245,1.0498646,1.0468378,1.0490025]
    DO      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0489565,1.0499466,1.046833500000001,1.0492415]
    GN      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0491975,1.050113,1.046846700000001,1.0497525]
    CK      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0497085,1.0502838,1.046881000000001,1.0502025]
    IJ      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.050159,1.0503826,1.046898100000001,1.0506915]
    PF      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0506475,1.0504916,1.046935200000001,1.051158…]

    Допустим, я хочу измерить динамику этих переменных, которые у меня есть, создав на их основе индикатор динамики.

    Indicators.Col(COscillatorIndicators::MomentumIndicator(open, 20), 4);
    Indicators.Col(COscillatorIndicators::MomentumIndicator(high, 50), 5);
    Indicators.Col(COscillatorIndicators::MomentumIndicator(low, 100), 6);
    Indicators.Col(COscillatorIndicators::MomentumIndicator(close, 20), 7);

    Результаты

    IN      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0441885,nan,nan,1.0438975,99.43679181343492,nan,nan,99.44502817843157]
    LN      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0438975,1.0495116,nan,1.043593,99.44407828753189,nan,nan,99.41864350150351]
    QS      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0435925,1.0492638,nan,1.0433225,99.4176888931316,98.82473464044848,nan,99.4833645288208]
    HG      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0436275,1.049148199999999,nan,1.043363,100.0668474731655,99.45161810609009,nan,100.0773424743863]
    EH      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0436685,1.0490618,nan,1.043385,100.0782973197491,99.59030385797199,nan,100.0420047732697]
    KO      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0436925,1.0489454,nan,1.0434175,100.0458251389074,99.4479854313681,nan,100.0620536907626]
    JQ      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0437225,1.048834,nan,1.043484,100.0572803299347,99.47183265534476,nan,100.1270939444036]
    JE      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.043788,1.048718,nan,1.0435725,100.1251839535195,99.45010144680205,nan,100.1690625149243]
    LE      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.043877,1.048595199999999,nan,1.0435315,100.1700192943244,99.41799844546816,nan,99.92180198737388]
    MI      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0438365,1.048457,nan,1.0437085,99.92275488503829,99.34503611305946,nan,100.3389538390831]
    HN      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.044013,1.0483164,nan,1.044095,100.3379931060896,99.33386396801032,nan,100.7431263218612]
    KS      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0443985,1.048186,nan,1.044364,100.7411964891704,99.38227742565063,nan,100.5158345877638]
    EE      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0446665,1.0480502,nan,1.044532,100.5139219145509,99.35649569733499,nan,100.3225558712848…]


    Построение графиков индикаторов, созданных с помощью пользовательских функций

    Давайте попытаемся сделать полученные из этой библиотеки расчеты индикаторов видимыми для человеческого глаза.

    Несмотря на то, что этот подход направлен скорее на сбор данных, чем на визуализацию, давайте визуализируем расчеты индикатора в пользовательском индикаторе MetaTrader 5.

    Визуализация индикатора SMA (20).

    #property indicator_chart_window
    #property indicator_buffers 1
    #property indicator_plots 1
    
    #property indicator_color1 clrDodgerBlue
    #property indicator_type1 DRAW_LINE
    #property indicator_style1 STYLE_SOLID
    
    #include <ta-lib.mqh>
    
    input int period_ = 20; //SMA period
    
    double buffer[];
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function                         |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- indicator buffers mapping
       
       SetIndexBuffer(0, buffer, INDICATOR_DATA);
       PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0);   
       
       PlotIndexSetString(0,PLOT_LABEL,"SMA("+string(period_)+")");
       PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,period_+1);
       
    //---
       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[])
      {
    //---
    
       if (prev_calculated==0) //Initial indicator calculation, For Plotting the entire past 
         {        
           vector buffer_vector = CTrendIndicators::SMA(close, period_);
           
           VectorToArray(buffer_vector, buffer); //We assign the calculations into an array format
         }
        else //For plotting the current value
         {
           for (int i=prev_calculated-1; i<rates_total; i++) //Loop from the prev_calculated bars -1 to the total bars present 
            {
               double temp_close[]; //For storing temporary close values
               int size = period_*2; //We are going to copy an equivalent of period x 2 to leave a room for NaN values
               
               if (ArrayCopy(temp_close, close, 0, i - size, size) < 0)
                { 
                   printf("Failed to copy closing price values to a temporary array, err = %d",GetLastError());
                   continue;
                }
               
               vector indicator_values = CTrendIndicators::SMA(temp_close, period_); 
               ulong last_index = indicator_values.Size() - 1; //The last value in the vector is the recent calculated indicator value
               
               buffer[i] = indicator_values[last_index]; //Assing the last indicator value to the last value in the buffer
            }
         }
       
    //--- return value of prev_calculated for next call
       return(rates_total);
      }
    //+------------------------------------------------------------------+
    //|      A crude way to convert a vector into Array                  |
    //+------------------------------------------------------------------+
    template <typename T>
    void VectorToArray(const vector<T> &v, T &arr[])
     {
       ArrayResize(arr, (uint)v.Size());
       
       for (uint i=0; i<(uint)v.Size(); i++)
           arr[i] = v[i];
     }
    

    Результаты

    SMA 20


    Заключительные мысли

    Такой подход к индивидуальному сбору значений показателей удобен, когда речь заходит о сборе данных, а не о какой-либо другой конкретной задаче, он хорошо подходит для аналитики данных и энтузиастов, ищущих инновационные способы сбора данных индикаторов для целей анализа.

    Я часто сталкивался с необходимостью быстрого получения нескольких значений индикаторов без необходимости инициализировать индикатор и выполнять все те скучные действия, которые часто приводят к ошибкам MetaTrader5. В связи с растущим спросом на данные в MQL5, обусловленным его новой способностью работать со сложными моделями ИИ и машинного обучения (ML), нам нужны различные и эффективные способы извлечения и визуализации данных индикаторов для целей анализа и обучения ML.

    Всем добра.


    Таблица вложений

    Имя файла Описание/назначение
    Include\ta-lib.mqh Библиотека MQL5 со всеми индикаторами, описанными в этой статье.
    Indicators\Trend Indicators Redefined.mq5  Индикатор, содержащий индикатор простой скользящей средней, реализованный в демонстрационных целях. 
     Scripts\Custom Indicators test script.mq5 Простой скрипт, созданный для тестирования и отладки кода индикаторов. 


    Источники и ссылки

      Перевод с английского произведен MetaQuotes Ltd.
      Оригинальная статья: https://www.mql5.com/en/articles/16931

      Прикрепленные файлы |
      Attachments.zip (7.42 KB)
      Последние комментарии | Перейти к обсуждению на форуме трейдеров (1)
      Zhuo Kai Chen
      Zhuo Kai Chen | 25 янв. 2025 в 03:14
      Очень интересная статья! Мне нравится инновационный подход, который вы представили.
      Компоненты View и Controller для таблиц в парадигме MVC на MQL5: Контейнеры Компоненты View и Controller для таблиц в парадигме MVC на MQL5: Контейнеры
      В статье рассмотрим создание элемента управления "Контейнер" с возможностью прокрутки его содержимого. В процессе будут доработаны уже готовые классы элементов управления графической библиотеки.
      Исследуем регрессионные модели для причинно-следственного вывода и трейдинга Исследуем регрессионные модели для причинно-следственного вывода и трейдинга
      В данной статье проведено исследование на тему возможности применения регрессионных моделей в алгоритмической торговле. Регрессионные модели, в отличие от бинарной классификации, дают возможность создавать более гибкие торговые стратегии за счет количественной оценки прогнозируемых ценовых изменений.
      Возможности Мастера MQL5, которые вам нужно знать (Часть 49): Обучение с подкреплением и проксимальной оптимизацией политики Возможности Мастера MQL5, которые вам нужно знать (Часть 49): Обучение с подкреплением и проксимальной оптимизацией политики
      Проксимальная оптимизация политики (Proximal Policy Optimization) — еще один алгоритм обучения с подкреплением, который обновляет политику, часто в сетевой форме, очень маленькими шагами, чтобы обеспечить стабильность модели. Как обычно, мы рассмотрим, как этот алгоритм можно применить в советнике, собранном с помощью Мастера.
      Нейросети в трейдинге: Вероятностное прогнозирование временных рядов (Энкодер) Нейросети в трейдинге: Вероятностное прогнозирование временных рядов (Энкодер)
      Предлагаем познакомиться с новым подходом, который объединяет классические методы и современные нейросети для анализа временных рядов. В статье подробно раскрыта архитектура и принципы работы модели K²VAE.