Поиск экстремумов индикатора ZigZag

 

Уважаемые трейдеры, представляю Вашему вниманию и делюсь - функция от И. Кима , переделанная мною с MQL4 для MQL5: Поиск экстремумов ZigZag.

//+-----------------------------------------------------------------------------------------------------------------------------------------------+
//|  Возвращает экстремум ЗигЗага по его номеру.                                                                                                  |
//|  Параметры:                                                                                                                                   |
//|   symbol          - наименование инструмента    ("" - текущий символ)                                                                         |
//|   timeframe       - таймфрейм                   ( 0 - текущий ТФ)                                                                             |
//|   extremum_number - номер экстремума            ( 0 - текущий)                                                                                |
//|   depth           - ExtDepth                                                                                                                  |
//|   deviation       - ExtDeviation                                                                                                              |
//|   backstep        - ExtBackstep                                                                                                               |
//+-----------------------------------------------------------------------------------------------------------------------------------------------+
double GetExtremumZigZagPrice(string symbol="", ENUM_TIMEFRAMES timeframe=0, int extremum_number=0, int depth=12, int deviation=5, int backstep=3) 
{
  if (symbol=="")  //Если symbol = "" , то..
  symbol=Symbol(); //Присвоить переменной symbol значение текущего символа на графике.
  
  //Объявить необходимые переменные:
  double price[];                                //Цена экстремума выбранная из массива таймсерии.
  int    count;                                  //Счетчик цикла.
  int bars_quantity=iBars(symbol, timeframe);    //Количество баров на графике. 
  int extremum_count=0;                          //Счетчик экстремумов.
  int handle;                                    //Хэндл индикатора.
  
  handle=iCustom(symbol, timeframe, "Examples\\ZigZag", depth, deviation, backstep);    //Получить хэндл Зигзага, если он есть.
  ArraySetAsSeries(price,true);                   //Устанавить флаг, чтобы индексация массива производилась как в таймсериях.
  CopyBuffer(handle,0,0,bars_quantity,price);     //Скопировать в динамический массив price[] цены указанного количества баров. 
 
  for (count=1; count < bars_quantity; count++)  //Запустить цикл, который будет бежать по каждому бару.
   {
    if (price[count]!=0)       //Если Цена Зигзага есть, то есть не равна нулю, то..
    {
      extremum_count++;        //Увеличить счетчик экстремумов на одну единицу.
      
      if (extremum_count > extremum_number) //Если счетчик экстремумов превысил значение указанного номера экстремума, то..
      return(price[count]);                 //Вернуть эту цену.
    }
   }
  Print("GetExtremumZigZagPrice(): Экстремум ЗигЗага ",extremum_number," не найден"); //А до тех пор, пока ЗигЗаг не показывает цену,
  return(0);                                                                          //Печатать Print, и возвращать ноль.
}

Может кому-нибудь пригодиться. Сам долго искал для MQL5, но так и не нашел и решил сделать все сам. По крайней мере, аналогов в MQL5 еще не встречал. )

 

Здесь готовый код для проверки:

//+------------------------------------------------------------------+
//|                                                         Test.mq5 |
//|                                       Copyright 2018. Yuriy Vins |
//|                                            https://www.sayta.net |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018. Yuriy Vins"
#property link      "https://www.sayta.net"
#property version   "1.00"

int han;
double extr1, extr2, extr3, extr4, extr5, extr6, extr7;

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  { 
    han=iCustom(Symbol(), 0, "Examples\\ZigZag", 12, 5, 3);  
    ChartIndicatorAdd(0,0,han);
    
    extr1 = GetExtremumZigZagPrice(NULL,0,1,12,5,3);
    extr2 = GetExtremumZigZagPrice(NULL,0,2,12,5,3);
    extr3 = GetExtremumZigZagPrice(NULL,0,3,12,5,3);
    extr4 = GetExtremumZigZagPrice(NULL,0,4,12,5,3);
    extr5 = GetExtremumZigZagPrice(NULL,0,5,12,5,3);
    extr6 = GetExtremumZigZagPrice(NULL,0,6,12,5,3);
    extr7 = GetExtremumZigZagPrice(NULL,0,7,12,5,3);
    
    Comment
    (
     "Extremum 1 = "+DoubleToString(extr1,_Digits),"\n",
     "Extremum 2 = "+DoubleToString(extr2,_Digits),"\n",
     "Extremum 3 = "+DoubleToString(extr3,_Digits),"\n",
     "Extremum 4 = "+DoubleToString(extr4,_Digits),"\n",
     "Extremum 5 = "+DoubleToString(extr5,_Digits),"\n",
     "Extremum 6 = "+DoubleToString(extr6,_Digits),"\n",
     "Extremum 7 = "+DoubleToString(extr7,_Digits),"\n"
    );
  }
//+-----------------------------------------------------------------------------------------------------------------------------------------------+
//|  Возвращает экстремум ЗигЗага по его номеру.                                                                                                  |
//|  Параметры:                                                                                                                                   |
//|   symbol          - наименование инструмента    ("" - текущий символ)                                                                         |
//|   timeframe       - таймфрейм                   ( 0 - текущий ТФ)                                                                             |
//|   extremum_number - номер экстремума            ( 0 - текущий)                                                                                |
//|   depth           - ExtDepth                                                                                                                  |
//|   deviation       - ExtDeviation                                                                                                              |
//|   backstep        - ExtBackstep                                                                                                               |
//+-----------------------------------------------------------------------------------------------------------------------------------------------+
double GetExtremumZigZagPrice(string symbol="", ENUM_TIMEFRAMES timeframe=0, int extremum_number=0, int depth=12, int deviation=5, int backstep=3) 
{
  if (symbol=="")  //Если symbol = "" , то..
  symbol=Symbol(); //Присвоить переменной symbol значение текущего символа на графике.
  
  //Объявить необходимые переменные:
  double price[];                                //Цена экстремума выбранная из массива таймсерии.
  int    count;                                  //Счетчик цикла.
  int bars_quantity=iBars(symbol, timeframe);    //Количество баров на графике. 
  int extremum_count=0;                          //Счетчик экстремумов.
  int handle;                                    //Хэндл индикатора.
  
  handle=iCustom(symbol, timeframe, "Examples\\ZigZag", depth, deviation, backstep);    //Получить хэндл Зигзага, если он есть.
  ArraySetAsSeries(price,true);                   //Устанавить флаг, чтобы индексация массива производилась как в таймсериях.
  CopyBuffer(handle,0,0,bars_quantity,price);     //Скопировать в динамический массив price[] цены указанного количества баров. 
 
  for (count=1; count < bars_quantity; count++)  //Запустить цикл, который будет бежать по каждому бару.
   {
    if (price[count]!=0)       //Если Цена Зигзага есть, то есть не равна нулю, то..
    {
      extremum_count++;        //Увеличить счетчик экстремумов на одну единицу.
      
      if (extremum_count > extremum_number) //Если счетчик экстремумов превысил значение указанного номера экстремума, то..
      return(price[count]);                 //Вернуть эту цену.
    }
   }
  Print("GetExtremumZigZagPrice(): Экстремум ЗигЗага ",extremum_number," не найден"); //А до тех пор, пока ЗигЗаг не показывает цену,
  return(0);                                                                          //Печатать Print, и возвращать ноль.
}
 
Yuriy Vins:

Здесь готовый код для проверки:

Вот эту штуку желательно ставить в OnInit(), или если внутри функции, то ставить флаг что хендл уже создан, и его больше не создавать

handle=iCustom(symbol, timeframe, "Examples\\ZigZag", depth, deviation, backstep);    //Получить хэндл Зигзага, если он есть.
  ArraySetAsSeries(price,true);                   //Устанавить флаг, чтобы индексация массива производилась как в таймсериях.
 
Vitaly Muzichenko:

Вот эту штуку желательно ставить в OnInit(), или если внутри функции, то ставить флаг что хендл уже создан, и его больше не создавать

Согласен! Просто хотелось сделать как можно проще, чтобы поменьше кода было.

 
Yuriy Vins:

Согласен! Просто хотелось сделать как можно проще, чтобы поменьше кода было.

Простота - хуже воровства.)

 

Здесь еще одна функция - возвращает номер бара выбранного экстремума ZigZag.

//+-----------------------------------------------------------------------------------------------------------------------------------------------+
//|  Возвращает номер бара экстремума ЗигЗага по его номеру.                                                                                      |
//|  Параметры:                                                                                                                                   |
//|   symbol          - наименование инструмента    ("" - текущий символ)                                                                         |
//|   timeframe       - таймфрейм                   ( 0 - текущий ТФ)                                                                             |
//|   extremum_number - номер экстремума            ( 0 - текущий)                                                                                |
//|   depth           - ExtDepth                                                                                                                  |
//|   deviation       - ExtDeviation                                                                                                              |
//|   backstep        - ExtBackstep                                                                                                               |
//+-----------------------------------------------------------------------------------------------------------------------------------------------+
int GetExtremumZigZagBar(string symbol="", ENUM_TIMEFRAMES timeframe=0, int extremum_number=0, int depth=12, int deviation=5, int backstep=3) 
{
  if (symbol=="")  //Если symbol = "" , то..
  symbol=Symbol(); //Присвоить переменной symbol значение текущего символа на графике.
  
  //Объявить необходимые переменные:
  double price[];                                //Цена экстремума выбранная из массива таймсерии.
  int    count;                                  //Счетчик цикла.
  int    bars_quantity=iBars(symbol,timeframe);  //Количество баров на графике.
  int    extremum_count=0;                       //Счетчик экстремумов.
  int handle;                                    //Хэндл индикатора.
  
  handle=iCustom(symbol, timeframe, "Examples\\ZigZag", depth, deviation, backstep);    //Получить хэндл Зигзага, если он есть.
  ArraySetAsSeries(price,true);                   //Устанавить флаг, чтобы индексация массива производилась как в таймсериях.
  CopyBuffer(handle,0,0,bars_quantity,price);     //Скопировать в динамический массив price[] цены указанного количества баров. 
 
  for (count=1; count < bars_quantity; count++)   //Запустить цикл, который будет бежать по каждому бару.
  { 
   if (price[count]!=0)     //Если Цена Зигзага есть, то есть не равна нулю, то..
    {
      extremum_count++;     //Увеличить счетчик экстремумов на одну единицу.
      
      if (extremum_count>extremum_number) //Если счетчик экстремумов превысил значение указанного номера экстремума, то..
      return(count);                      //Вернуть номер бара.
    }
  }
  Print("GetExtremumZigZagBar(): Номер бара ЗигЗага ",extremum_number," не найден!"); //А до тех пор, пока ЗигЗаг не показывает цену,
  return(0);                                                                          //Печатать Print, и возвращать ноль.
}
 

Ну и полный тестовый код для проверки:

//+------------------------------------------------------------------+
//|                                                        Test2.mq5 |
//|                                       Copyright 2018. Yuriy Vins |
//|                                            https://www.sayta.net |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

int bar_number1,bar_number2,bar_number3,bar_number4,bar_number5,bar_number6,bar_number7;

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
    
    bar_number1 = GetExtremumZigZagBar(NULL,0,1,12,5,3);
    bar_number2 = GetExtremumZigZagBar(NULL,0,2,12,5,3);
    bar_number3 = GetExtremumZigZagBar(NULL,0,3,12,5,3);
    bar_number4 = GetExtremumZigZagBar(NULL,0,4,12,5,3);
    bar_number5 = GetExtremumZigZagBar(NULL,0,5,12,5,3);
    bar_number6 = GetExtremumZigZagBar(NULL,0,6,12,5,3);
    bar_number7 = GetExtremumZigZagBar(NULL,0,7,12,5,3);
    
    Comment
    (
     "Bar_Number 1 = "+IntegerToString(bar_number1,0),"\n",
     "Bar_Number 2 = "+IntegerToString(bar_number2,0),"\n",
     "Bar_Number 3 = "+IntegerToString(bar_number3,0),"\n",
     "Bar_Number 4 = "+IntegerToString(bar_number4,0),"\n",
     "Bar_Number 5 = "+IntegerToString(bar_number5,0),"\n",
     "Bar_Number 6 = "+IntegerToString(bar_number6,0),"\n",
     "Bar_Number 7 = "+IntegerToString(bar_number7,0),"\n"
    );
  }
  
//+-----------------------------------------------------------------------------------------------------------------------------------------------+
//|  Возвращает номер бара экстремума ЗигЗага по его номеру.                                                                                      |
//|  Параметры:                                                                                                                                   |
//|   symbol          - наименование инструмента    ("" - текущий символ)                                                                         |
//|   timeframe       - таймфрейм                   ( 0 - текущий ТФ)                                                                             |
//|   extremum_number - номер экстремума            ( 0 - текущий)                                                                                |
//|   depth           - ExtDepth                                                                                                                  |
//|   deviation       - ExtDeviation                                                                                                              |
//|   backstep        - ExtBackstep                                                                                                               |
//+-----------------------------------------------------------------------------------------------------------------------------------------------+
int GetExtremumZigZagBar(string symbol="", ENUM_TIMEFRAMES timeframe=0, int extremum_number=0, int depth=12, int deviation=5, int backstep=3) 
{
  if (symbol=="")  //Если symbol = "" , то..
  symbol=Symbol(); //Присвоить переменной symbol значение текущего символа на графике.
  
  //Объявить необходимые переменные:
  double price[];                                //Цена экстремума выбранная из массива таймсерии.
  int    count;                                  //Счетчик цикла.
  int    bars_quantity=iBars(symbol,timeframe);  //Количество баров на графике.
  int    extremum_count=0;                       //Счетчик экстремумов.
  int handle;                                    //Хэндл индикатора.
  
  handle=iCustom(symbol, timeframe, "Examples\\ZigZag", depth, deviation, backstep);    //Получить хэндл Зигзага, если он есть.
  ArraySetAsSeries(price,true);                   //Устанавить флаг, чтобы индексация массива производилась как в таймсериях.
  CopyBuffer(handle,0,0,bars_quantity,price);     //Скопировать в динамический массив price[] цены указанного количества баров. 
 
  for (count=1; count < bars_quantity; count++)   //Запустить цикл, который будет бежать по каждому бару.
  { 
   if (price[count]!=0)     //Если Цена Зигзага есть, то есть не равна нулю, то..
    {
      extremum_count++;     //Увеличить счетчик экстремумов на одну единицу.
      
      if (extremum_count>extremum_number) //Если счетчик экстремумов превысил значение указанного номера экстремума, то..
      return(count);                      //Вернуть номер бара.
    }
  }
  Print("GetExtremumZigZagBar(): Номер бара ЗигЗага ",extremum_number," не найден!"); //А до тех пор, пока ЗигЗаг не показывает цену,
  return(0);                                                                          //Печатать Print, и возвращать ноль.
}
 
Vitaly Muzichenko:

Вот эту штуку желательно ставить в OnInit(), или если внутри функции, то ставить флаг что хендл уже создан, и его больше не создавать

А это не связано с тем что у меня тестер стратегий в МТ-5 как то сильно виснуть стал?

 
Ребята, кто знает, подскажите: Тестер стратегий , в последствии применений этих функций стал работать на очень низкой скорости. Что не так? И кстати, я воспользовался советом Виталия, все равно виснет. (((
 

Вот когда вызываю эти функции :

//---------------------------------------------------------------------------------------------------------------+
//---------- Вычислить значения экстремумов индикатора ZigZag                                                    |
//---------------------------------------------------------------------------------------------------------------+  
    ex1 = GetExtremumZigZagPrice(NULL,0,1,12,5,3);
    ex2 = GetExtremumZigZagPrice(NULL,0,2,12,5,3);
    ex3 = GetExtremumZigZagPrice(NULL,0,3,12,5,3);
    ex4 = GetExtremumZigZagPrice(NULL,0,4,12,5,3);
    ex5 = GetExtremumZigZagPrice(NULL,0,5,12,5,3);
    ex6 = GetExtremumZigZagPrice(NULL,0,6,12,5,3);
    ex7 = GetExtremumZigZagPrice(NULL,0,7,12,5,3);
    ex8 = GetExtremumZigZagPrice(NULL,0,8,12,5,3);
    ex9 = GetExtremumZigZagPrice(NULL,0,9,12,5,3);
    ex10 = GetExtremumZigZagPrice(NULL,0,10,12,5,3);

То тестер работает очень медленно. А стоит его закомментировать, то нормально работает.

Может быть мне стоит все это дело в отдельный класс завернуть все эти вычисления?

 
Yuriy Vins:

Вот когда вставляю этот код:

То тестер работает очень медленно. А стоит его закомментировать, то нормально работает.

Может быть мне стоит все это дело в отдельный класс завернуть все эти вычисления?

Вы зачем животину мучаете? Зачем на каждом обращении в функцию GetExtremumZigZagBar создаёте ОДИН хендл индикатора? 

Существует жесткое правило: хендл создаётся ОДИН раз в OnInit. И это ещё не всё, но для начала хотя бы это устраните.

Причина обращения: