English 中文 Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
Новый индикатор технического анализа Moving Mini-Max и его реализация в MQL5

Новый индикатор технического анализа Moving Mini-Max и его реализация в MQL5

MetaTrader 5Примеры | 21 января 2011, 10:25
9 778 14
investeo
investeo

Введение

Применение методов теоретической физики и современной математики к анализу ценовых рядов (Quantitative Finance) позволяет изучать модели ценообразования и динамику финансовых рынков.

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

Оригинальная работа "Moving Mini-Max – a new indicator for technical analysis" [2] написана физиком З.К. Силагадзе, который работает в Институте Ядерной Физики им. Г.И. Будкера Сибирского Отделения РАН и Новосибирском Государственном Университете. Ссылки на эту статью и исходные коды на MQL5 вы найдете в конце статьи.


Индикатор

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

В основном нам нужно найти:

  • ценовые уровни поддержки и сопротивления
  • направление долгосрочного и краткосрочного трендов
  • вершины и впадины трендов

Оригинальная идея индикатора "Moving Mini-Max" заключается в нахождении вершин и впадин графика, используя квантовую аналогию для альфа-частицы, пытающейся покинуть ядро. Это задача теории альфа-распада, разработанной Г. Гамовым [1].

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

 Fig.1 Imaginary quantum ball on timeseries chart

Рисунок 1. Воображаемый квантовый мяч на графике валютной пары

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

Эта задача аналогична задаче о нахождении локального минимума на ценовом графике. В работе З.К. Силагадзе [2] предполагается, что для упрощения расчетов вместо решения реальной квантовомеханической задачи достаточно имитировать квантовое поведение. Здесь мы рассмотрим математические основы подхода, представленного в оригинальной статье [2] и затем приведем реализацию решения данной задачи на MQL5.

Пусть   - временной ряд цен за некоторый период времени. Moving Mini-Max - это нелинейное преобразование временного ряда вида:

uSi

где  и для  определяются следующим образом:

 

Как видно, это рекуррентное соотношение, и каждый i-й элемент зависит от элемента i-1. Полученный преобразованием Moving Mini-Max удовлетворяет условию нормировки, сумма всех элементов равна единице:

 

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


где

 

Параметр m - это ширина окна сглаживания, этот параметр имеет смысл величины, обратной массе мяча, он позволяет управлять его "проникающей способностью". Можно убедиться в том, что при увеличении m график mini-max станет более гладким.

В дополнение к u(si) введем d(si), соответствующий локальным минимумам, отличие для штрихованных Q заключается в знаке минус выражения в аргументе функции exp():

 

 

Реализация

Ознакомившись с математическими основами, мы можем реализовать все это в MQL5. Лучше начать с последнего выражения. Если обратить внимание на переменные m и n, мы увидим что для построения индикатора требуется массив из n+2m элементов ценового ряда для одного mini-max окна длиной m баров. Переменная i  пробегает значения от 1 до n , а k пробегает значения от 1 to m, поэтому для начала нам потребуется буфер размером n+2m.

Ценовые данные можно получить так:

double S[];
ArrayResize(S,n+2*m);
CopyClose(Symbol(),0,0,n+2*m,S);

Здесь мы объявили массив чисел типа double, установили его размер n+2m и скопировали цены закрытия последних n+2m баров текущего символа, начиная с последнего бара графика.

Следующим шагом является вычисления значений Q. Согласно определению, для вычисления i-го элемента анализируемого ценового ряда нам требуется вычисление суммы m экспонент с аргументами ценового ряда.

Поэтому для расчета всех значений Q нам требуется реализовать цикл от 1 до n:

void calcQii()
  {
   int i,k;

   for(i=0; i<n; i++)
     {
      double sqiip1=0;
      double sqiim1=0;
      double dqiip1=0;
      double dqiim1=0;

      for(k=0; k<m; k++)
        {

         sqiip1 += MathExp(2*(S[m-1+i+k]-S[i])/(S[m-1+i+k]+S[i]));
         sqiim1 += MathExp(2*(S[m-1+i-k]-S[i])/(S[m-1+i-k]+S[i]));

         dqiip1 += MathExp(-2*(S[m-1+i+k]-S[i])/(S[m-1+i+k]+S[i]));
         dqiim1 += MathExp(-2*(S[m-1+i-k]-S[i])/(S[m-1+i-k]+S[i]));
       
        }
      sQiip1[i] = sqiip1;
      sQiim1[i] = sqiim1;
      dQiip1[i] = dqiip1;
      dQiim1[i] = dqiim1;

     }
  }

Как видите, функция calcQii вычисляет значения i элементов Q и Q` рассматриваемого ценового окна размером n. Массив S хранит значения цен, а sQiip1, sQiim1, dQiip1, dQiim1 используются при промежуточных расчетах величин Q и Q`.

Вероятности вычисляются при помощи переменных Q и Q`, поэтому мы можем сделать другую функцию с циклом от 1 до n при помощи массивов sQii и dQii:

void calcPii()
  {
   int i;

   for(i=0; i<n; i++)
     {
      sPiip1[i] = sQiip1[i] / (sQiip1[i] + sQiim1[i]);
      sPiim1[i] = sQiim1[i] / (sQiip1[i] + sQiim1[i]);
      dPiip1[i] = dQiip1[i] / (dQiip1[i] + dQiim1[i]);
      dPiim1[i] = dQiim1[i] / (dQiip1[i] + dQiim1[i]);

     }
  }

Осталось вычислить элементы uSi, а затем dSi и поместить результаты в массивы uSi and dSi:

void calcui()
  {
   int i;
   sui[0] = 1;
   dui[0] = 1;

   for(i=1; i<n; i++) 
     {
      sui[i] = (sPiim1[i]/sPiip1[i])*sui[i-1];
      dui[i] = (dPiim1[i]/dPiip1[i])*dui[i-1];
     }

   double uSum = 0;
   double dSum = 0;

   ArrayInitialize(uSi, 0.0);
   ArrayInitialize(dSi, 0.0);
   
   for(i=0; i<n; i++) { uSum+=sui[i]; dSum+=dui[i]; }
   for(i=0; i<n; i++) { uSi[n-1-i] = sui[i] / uSum; dSi[n-1-i] = dui[i] / dSum; }
   }

Для проверки выполнения условия нормировки, добавим следующие строки:

   double result=0;
   for(i=0; i<n; i++) { /* Print("i = "+i+" uSi = "+uSi[i]); */ result+=uSi[i]; }

   Print("Result = "+ DoubleToString(result));

После того, как с расчетами разобрались, нам требуется реализовать отображение результатов в окне индикатора. Для этого мы должны объявить как минимум два индикаторных буфера: один для uSi, второй для dSi и задать тип отображения индикатора как DRAW_LINE.

    #property indicator_separate_window

    #property indicator_buffers 2
    #property indicator_plots 2
    #property indicator_type1 DRAW_LINE
    #property indicator_type2 DRAW_LINE
    #property indicator_color1 SeaGreen
    #property indicator_color2 BlueViolet

Затем при помощи функции SetIndexBuffer() мы связываем массивы uSi и dSi с отображаемыми индикаторными буферами (INDICATOR_DATA):

   SetIndexBuffer(0,uSi,INDICATOR_DATA);
   SetIndexBuffer(1,dSi,INDICATOR_DATA);

   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);

   PlotIndexSetInteger(0,PLOT_SHIFT,-(m-1));
   PlotIndexSetInteger(1,PLOT_SHIFT,-(m-1));

Fig.2 Moving mini-max indicator

Рисунок 2. Индикатор Moving Mini-Max

Возможными приложениями индикатора, описанного в статье, является выявление уровней поддержки и сопротивления и распознавания индикаторных паттернов. Что касается линий поддержки и сопротивления, они формируются при пересечении индикаторов mini-max и их скользящих средних.

Если цена идет через локальный максимум и пересекает скользящую среднюю, мы имеем уровень сопротивления. После реализации данного подхода я заметил, что этот метод дает ряд ложных сигналов, тем не менее, приведу здесь этот код, который демонстрирует размещение этих линий на MQL5 при помощи библиотеки ChartObjectsLines.mqh:

void SR()
{
   // отображаем линию сопротивления если произошло пересечение локальных максимумов (анализ uSi) со скользящей средней
   int i, cnt=0;
   int rCnt=CopyClose(Symbol(),0,0,n+2*m,S);
      
   for (i=n-2; i>=0; i--)
      if (uSi[i]<uSi_MA[i] && uSi[i+1]>=uSi_MA[i+1]) 
      {
      Print("Resistance at " + i);
      CChartObjectHLine *line=new CChartObjectHLine();
      line.Create(0, "MiniMaxResistanceLine:"+IntegerToString(cnt), 0, S[i]);
      line.Color(LightSkyBlue);
      line.Width(1);
      line.Background(true);
      line.Selectable(false);
      cnt++;
      }
   // отображаем линию поддержки если произошло пересечение локальных минимумов (анализ dSi) и пересекла скользящую среднюю
   for (i=n-2; i>=0; i--)
      if (dSi[i]<dSi_MA[i] && dSi[i+1]>=dSi_MA[i+1]) 
      {
      Print("Support at " + i);
      CChartObjectHLine *line=new CChartObjectHLine();
      line.Create(0, "MiniMaxSupportLine:"+IntegerToString(cnt), 0, S[i]);
      line.Color(Tomato);
      line.Width(1);
      line.Background(true);
      line.Selectable(false);
      cnt++;
      }
}

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

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

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

Для использования разноцветной гистограммы нам потребуется использование 2 буферов данных и один буфер для индексов цвета. Рассмотрим реализацию отображения. Всего у нас 5 буферов, три из них задаются для разноцветной гистограммы.

//+------------------------------------------------------------------+
//|                                                MovingMiniMax.mq5 |
//|                                      Copyright 2011, Investeo.pl |
//|                                               http://Investeo.pl |
//+------------------------------------------------------------------+
#property copyright   "Copyright 2011, Investeo.pl"
#property link        "http://Investeo.pl"

#property description "Moving Mini-Max indicator"
#property description "proposed by Z.K. Silagadze"
#property description "from Budker Institute of Nuclear Physics"
#property description "and Novosibirsk State University"
#property description "Original paper can be downloaded from:"
#property description "http://arxiv.org/abs/0802.0984"

#property version     "0.6"
#property indicator_separate_window

#property indicator_buffers 5
#property indicator_plots 3

#property indicator_type1 DRAW_COLOR_HISTOGRAM2
#property indicator_type2 DRAW_ARROW
#property indicator_type3 DRAW_ARROW

#property indicator_color1 Chartreuse, OrangeRed, Yellow
#property indicator_color2 RoyalBlue
#property indicator_color3 RoyalBlue

#property indicator_width1 5
#property indicator_width2 4
#property indicator_width3 4

Обратите внимание на то, что для построения гистограммы используются два буфера данных (INDICATOR_DATA) и один буфер цветовых индексов (INDICATOR_COLOR_INDEX). Буферы должны быть установлены в определенном порядке, сначала задаются буферы данных, затем определяется буфер индексов цвета.

   SetIndexBuffer(0,uSi,INDICATOR_DATA);
   SetIndexBuffer(1,dSi,INDICATOR_DATA);
   SetIndexBuffer(2,trend,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(3,upArrows,INDICATOR_DATA);
   SetIndexBuffer(4,dnArrows,INDICATOR_DATA);
   
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,0.0);
   
   PlotIndexSetInteger(1,PLOT_ARROW,234);
   PlotIndexSetInteger(2,PLOT_ARROW,233); 

Буферы 0,1,2 используются для цветовой гистограммы, буферы 3 и 4 используются для отображения стрелок.

Алгоритм раскраски следующий:

   if (upind<dnind) 
    { 
      for (i=0; i<upind; i++) trend[i]=0;
      for (i=upind; i<dnind; i++) trend[i]=1;
      for (i=dnind; i<n; i++) trend[i]=0 ;
    } else
    {
      for (i=0; i<dnind; i++) trend[i]=1;
      for (i=dnind; i<upind; i++) trend[i]=0;
      for (i=upind; i<n; i++) trend[i]=1;
   }
   
   trend[upind] = 2;
   trend[dnind] = 2;

Приведем скриншот полученного результата:

Figure 2. Final version of Moving Mini-Max indicator

Рисунок 3. Окончательная версия индикатора Moving Mini-Max

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

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


Выводы

Я представил математические основы нового индикатора технического анализа и его реализацию на MQL5. Оригинальная статья З.К. Силагадзе доступна по адресу: http://arxiv.org/abs/0802.0984.

Исходный код индикатора можно скачать в приложении к статье.

В будущем я надеюсь представить более интересные технические индикаторы и их реализацию на MQL5.


Литература:

1. Г.А. Гамов Теория радоактивного распада (УФН, т. X, 1930).
2. Z.K. Silagadze. Moving Mini-Max -- a new indicator for technical analysis

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

Прикрепленные файлы |
movingminimax.mq5 (7.34 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (14)
i778
i778 | 16 мая 2015 в 02:15
интересно было бы использовать тот же принцип на опережение
[Удален] | 17 янв. 2016 в 21:36
Мне графика понравилась. Делал человек со вкусом. И на МТ4 хотелось бы это дело себе повесить. )
Limited Liability Company "AB TRUST"
Alexey Bacherov | 22 мая 2018 в 09:48

Задумка понравилась, но что-то не так. Индикатор по реализации просто в рассматриваемом окне находит лок макс и мин. Гармоники вроде могут что-то сказать о фазе рынка (флет или тренд) но не явно. Нужно смотреть в динамике этот индикатор. Пока мне кажется, что он бесполезен.

График с индюком и разными фреймами

Yury Zaikouski
Yury Zaikouski | 18 янв. 2019 в 15:31
Очень хорошо ловит точки разворота рынка. Жди сигнала он покажет приближение к уровням поддержки и сопротивления... только определи току входа и ты получил прибыль...
Yevgeniy Koshtenko
Yevgeniy Koshtenko | 24 окт. 2022 в 07:51
Yury Zaikouski #:
Очень хорошо ловит точки разворота рынка. Жди сигнала он покажет приближение к уровням поддержки и сопротивления... только определи току входа и ты получил прибыль...

Ничего он не ловит, он рисует как Репин)

Торговые события в MetaTrader 5 Торговые события в MetaTrader 5
Мониторинг текущего состояния торгового счета подразумевает контроль над открытыми позициями и ордерами. Прежде чем торговый сигнал станет сделкой, он должен быть отправлен из клиентского терминала в виде запроса торговому серверу, где он будет помещен в очередь запросов и ждать своей обработки. Принятие запроса сервером, удаление его по времени истечения или проведение на его основе сделки - все это сопровождается торговыми событиями, о которых сервер сообщает терминалу.
Мастер MQL5: Как написать свой модуль сопровождения открытых позиций Мастер MQL5: Как написать свой модуль сопровождения открытых позиций
Генератор торговых стратегий Мастера MQL5 значительно упрощает проверку торговых идей. В статье рассказывается о том, как написать и подключить в Мастер MQL5 свой собственный модуль управления открытыми позициями, устанавливающий уровень Stop Loss в безубыток при движении цены в благоприятном направлении, что позволяет защитить прибыль и уменьшить потери. Рассматривается структура и формат описания созданного класса для Мастера MQL5.
Курс Монетки и основанный на нем Индикатор Трендовости Курс Монетки и основанный на нем Индикатор Трендовости
Модели случайных блужданий даётся название "Курс Монетки". Приводятся свойства курса монетки с точки зрения трейдера. Предлагается создать симулятор курса на основе курса монетки с трендом. Для отличия реального курса от курса монетки создан индикатор трендовости. Рассматривается трендовость реального курса.
Подключение нейросетей от NeuroSolutions Подключение нейросетей от NeuroSolutions
Программный пакет NeuroSolutions позволяет не только создавать нейронные сети, но и экспортировать их в DLL. В статье описан процесс создания нейросети, генерации DLL и ее подключения к советнику для торговли в MetaTrader.