тел.: 8 800 200 86 47|+7 (812) 336 61 11Заказать звонок
Выберите город
Choose your city
Admiral Markets Global Admiral Markets Global Choose your country

Разновидности индикаторов Каги (часть 2)

Скачать индикатор Kagi_Ind_Trade.mq4

Скачать индикатор Kagi_Ind_7.mq4  

 

Если в распоряжении трейдера имеется эффективный пользовательский индикатор, то он может быть применён для вычисления торговых критериев в эксперте.  Каждый конкретный метод, положенный в основу стратегии, как правило, требует индивидуального подхода. В ряде случаев могут потребоваться некоторые изменения в коде индикатора, а также специфический алгоритм вычисления критериев в эксперте. Как практически может выглядеть индикатор, данные которого используются в эксперте для вычисления торговых критериев, проследим на примере пользовательского индикатора Каги (см. статью Разновидности индикаторов Каги).

Итак, пусть у нас есть индикатор Kagi_Ind_7.mq4, показывающий обнадёживающие результаты на истории. Этот индикатор является обычным в том смысле, что он строится по барам текущего таймфрейма. Это значит, что настройки индикатора не привязаны к какому-либо конкретному таймфрейму. По этой причине рисунки линий каги в разных таймфреймах на одном историческом промежутке (например, в течение суток) будут выглядеть по-разному. Обычный трейдер в процессе торговли неоднократно переключает таймфрейм, и если это не учитывать, то индикатор будет выполнен неправильно. Задача программиста заключается в построении такого эксперта, который использовал бы данные индикатора, взятые из конкретного таймфрейма, независимо от того, какой таймфрейм задан пользователем в текущий момент.

Для получения данных из пользовательского индикатора в MQL 4 предусмотрена функция iCustom():

 

void iCustom (string symbol, int timeframe, string name, ..., int mode, int shift)

Расчет указанного пользовательского индикатора. Пользовательский индикатор должен быть скомпилирован (файл с расширением EX4) и находиться в директории каталог_терминала\experts\indicators.

Параметры:

symbol - Символьное имя инструмента, на данных которого будет вычисляться индикатор. NULL означает текущий символ.
timeframe - Период. Может быть одним из периодов графика. 0 означает период текущего графика.
name - Имя пользовательского индикатора.
...
- Список параметров (при необходимости). Передаваемые параметры должны соответствовать порядку объявления и типу внешних (extern) переменных пользовательского индикатора.
mode - Индекс линии индикатора. Может быть от 0 до 7 и должен соответствовать индексу, используемому одной из функций SetIndexBuffer.
shift - Индекс получаемого значения из индикаторного буфера (сдвиг относительно текущего бара на указанное количество периодов назад).

 

Используя эту функцию в эксперте можно получить данные любого индикаторного массива в любом таймфрейме. В общем случае в коде индикатора могут использоваться обращения к функциям технических индикаторов. В частности, в параметрах такой функции может быть указан конкретный таймфрейм. Поэтому, перед тем, как использовать в эксперте обращение к пользовательскому индикатору, его (индикатор) необходимо ещё раз просмотреть и, при необходимости, исправить некоторые фрагменты кода. Кроме того, индикатор может содержать "лишний" код, т.е. такой, который не используется для вычисления индикаторных массивов. В случае пользовательского индикатора Kagi_Ind_7.mq4 это строки кода для вывода и удаления графических объектов, используемых для правильного отображения линии каги, но не используемых в вычислениях.

Обратимся к индикатору Kagi_Ind_7.mq4 (см. Создание индикатора Каги), чтобы понять какие переделки могут потребоваться. Вообще говоря, этот индикатор может использоваться и без переделок. Но такое решение, во-первых, усложнит алгоритм расчёта торговых критериев в эксперте, и во-вторых, приведёт к неоправданным затратам компьютерных ресурсов при тестировании. Чтобы лучше понять почему это так, рассмотрим как должен быть составлен в этом случае алгоритм вычисления торговых критериев. В большей части случаев пользователь наблюдает следующую ситуацию:

Рис. 1. Последний фрагмент линии Каги.

Линия каги всегда заканчивается вертикальным участком. Горизонтальный участок отрисовывается только тогда, когда рынок разворачивается в противоположном направлении, при этом в конце горизонтального участка присутствует новый развивающийся вертикальный отрезок. В рассматриваемом индикаторе для построения линии каги используются не цены закрытия баров, а ценовые значения Moving Average, что определяет запаздывание. По этой причине всегда имеется последовательность n баров (см. Рис.1), на которой линия каги не отображается. Это значит, что все 8 массивов индикатора Kagi_Ind_7.mq4 на этом участке содержат пустые значения. Поэтому, для вычисления текущего торгового критерия необходимо опросить все n баров, чтобы найти последнюю вертикаль каги, а после этого выполнить анализ значений индикаторных массивов на этой вертикали. Практически такой метод предполагает вызов пользовательского индикатора n раз только для того, чтобы добраться до начала анализа. В практической работе (особенно при тестировании в режиме оптимизации) многократное обращение к индикатору через iCustom() приводит к неоправданным затратам времени, поэтому неприемлемо.

Для расчёта торговых критериев в эксперте желательно обратиться к элементам индикаторных массивов лишь на одном последнем баре. В индикаторе Kagi_Ind_7.mq4 для отображения линии каги необходимо используются все 8 индикаторных буферов. В пользовательском индикаторе, предназначенном для вызова через iCustom(), это не требуется. В данном случае достаточно иметь всего два индикаторных массива - один для "синей" тенденции, а другой - для "красной". Факт смены тенденции должен определяться по данным элементов индикаторных массивов, рассчитанных для последнего (нулевого) бара.

 

Программный код.

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

 

 
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
   // Kagi_Ind_Trade.mq4                                                          Индикатор. 
   // Сергей Ковалёв, Днепропетровск, sk@autograf.dp.ua, ICQ 64015987, http://autograf.dp.ua
   //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж 0 жж
#property copyright "Copyright SK AutoGraf © 2008"
#property link      "http://autograf.dp.ua/"
//================================================================================== 1 ==
#property indicator_chart_window                // Индикатор в основном окне
#property indicator_buffers 8                   // Количество буферов 8
extern int Delta     = 31;                      // Порог для смены тенденции
extern int Method    = 1;                       // Метод построения Каги
extern int Period_MA = 34;                      // Период МА
extern int TimeFrame = 15;                      // Таймфрейм
int Width = 2;                                  // Толщина основной линии
extern color Color_1 = DodgerBlue;              // Цвет 1
extern color Color_2 = OrangeRed;               // Цвет 2
double Gor_B[];                                 // Буфер для гориз. синей   
double Gor_S[];                                 // Буфер для гориз. красной 
int   Vector,                                   // Направление вертикали
      Tip,                                      // Тип линии (красная/синяя)
      Last_V,                                   // Индекс последней вертикали
      BB, SS,                                   // Количество пунктов по Buy и Sell       
      Rez,                                      // Общее количество заработанных пунктов
      Ord;                                      // Общее количество открытых ордеров
double delta,                                   // Порог для смены тенденции в пунктах
       Revers,                                  // Цена смены тенденции
       Pr_Min,                                  // Минимальное  значение данных 
       Pr_Max,                                  // Максимальное значение данных 
       Last_Min,                                // Текущее минимальное  значение данных 
       Last_Max,                                // Текущее максимальное значение данных 
       bb,                                      // Цена открытия по текущему Buy
       ss;                                      // Цена открытия по текущему Sell
   //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж 3 жж
int init()
   {
//================================================================================== 4 ==
   SetIndexBuffer(0,Gor_B);                     // Связь ном буфера с назв. масс
   SetIndexBuffer(1,Gor_S);                     // Связь ном буфера с назв. масс
   SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,Width,Color_1); // Стиль линии верх синяя
   SetIndexStyle(1,DRAW_LINE,STYLE_SOLID,Width,Color_2); // Стиль линии верх красная
   delta = Delta*Point;                         // Теперь в пунктах
   //================================================================================== 8 ==
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж 9 жж
int start()
   {
//================================================================================= 10 ==
   int 
         counted_bars,                             // Количество неизменённых баров
      i;                                        // Технические переменные
   double Data;
   string
      Ts_Name;                                  // Имя граф. объекта
   //================================================================================= 11 ==
   counted_bars=IndicatorCounted();             // Количество неизменённых баров
   i=Bars-counted_bars-1;                       // Индекс последнего непосчитанного бара
   if (counted_bars == 0)                       // При самом первом включении start()
      {
      if (Close[i]>Open[i])                     // Повышающая свеча
         {
         Tip = 0;                               // Тип горизонта = синий, тенденция Buy
         Vector = 1;                            // Направление - вверх
         Pr_Min=MathMin(Close[i]-delta,Open[i]);// Цена минимум 
         Pr_Max = Close[i];                     // Цена максимум 
         Last_Min = Pr_Max;                     // Текущее минимальное  значение данных 
         Last_Max = Pr_Max;                     // Текущее максимальное значение данных 
         bb = Open[i];
         }
      else                                      // Понижающая свеча
         {
         Tip = 1;                               // Тип горизонта = красн, тенденция Sell
         Vector = -1;                           // Направление - вниз
         Pr_Max=MathMax(Close[i]+delta,Open[i]);// Цена максимум 
         Pr_Min = Close[i];                     // Цена минимум 
         Last_Min = Pr_Min;                     // Текущее минимальное  значение данных 
         Last_Max = Pr_Min;                     // Текущее максимальное значение данных 
         ss = Open[i];
         }
      Last_V = i;                               // Индекс последней вертикали
      }
//================================================================================= 12 ==
   while(i>=1)                                  // Цикл для вычисления буферов
      {
      static int First=0;                       // Не было вычислений на 1м баре
      if (i==1)                                 // Если это 1й бар
         {
         if (First==1)                          // Это не первый расчёт на 1м баре
            Last_V++;                           // Увеличиваем индекс последн вертик на 1
         First=1;                               // Будем помнить: это не первый расчёт
         }
//--------------------------------------------------------------------------------- 13 --
      switch(Method)                            // По методу расчётов
         {
         case 1:  Data = iMA(NULL,TimeFrame,Period_MA,0,MODE_SMMA,PRICE_TYPICAL,i); break;
         default: Data = Close[i];
         }
//--------------------------------------------------------------------------------- 14 --
      if (Gor_B[i+1] != EMPTY_VALUE)            // Перед расчётом принимаем ..
         Gor_B[i]=Close[i];                     // .. старые значения как значимые
      else
         Gor_B[i]=EMPTY_VALUE;                  // .. старые значения как значимые
         
         if (Gor_S[i+1] != EMPTY_VALUE)            // Перед расчётом принимаем ..
            Gor_S[i]=Close[i];                     // .. старые значения как значимые
      else
         Gor_S[i]=EMPTY_VALUE;                  // .. старые значения как значимые
      switch(Tip)                               // По типу последн горизонта 
         {
//================================================================================= 15 ==
         case 1:                                         // Тенденция красная
            switch(Vector)                               // По направлению
               {
//--------------------------------------------------------------------------------- 16 --
               case -1:                                  // Вниз (в направлении типа)
                  if (NormalizeDouble(Data-Last_Min,Digits)<0.0)
                     Last_Min = Data;
                  if (NormalizeDouble(Data-(Last_Min+delta),Digits)>=0.0)//Разворот
                     {
                     Vector = 1;                         // Направление - вверх
                     Pr_Min = Last_Min;                  // Новая цена горизонта
                     Last_Max = Data;   
                        Last_V = i;                         // Индекс последней вертикали
                     if (NormalizeDouble(Last_Max-Pr_Max,Digits)>0.0)// Выше реверса
                        {
                        Tip = 0;                         // Тенденция меняется на синюю
                        Gor_B[i]=Close[i];               // Новые значения массивов
                        Gor_S[i]=EMPTY_VALUE;            // Новые значения массивов
                        }
                     }   
                     break;
//--------------------------------------------------------------------------------- 17 --
               case 1:                                   // Вверх
                  if (NormalizeDouble(Data-Last_Max,Digits)>0.0)
                     {
                     Last_Max = Data;
                     if (NormalizeDouble(Last_Max-Pr_Max,Digits)>0.0)// Выше реверса
                        {
                        Tip = 0;                         // Тенденция меняется на синюю
                        Gor_B[i]=Close[i];               // Новые значения массивов
                        Gor_S[i]=EMPTY_VALUE;            // Новые значения массивов
                        }
                     }
                  if (NormalizeDouble(Data-(Last_Max-delta),Digits)<=0.0)//Разв.
                     {
                     Vector = -1;                        // Направление - вниз
                     Pr_Max = Last_Max;                  // Новая цена горизонта
                     Last_Min = Data;                    // Текущий минимум
                     Last_V = i;                         // Индекс последней вертикали
                     }
                  break;
//--------------------------------------------------------------------------------- 18 --
               }
            break;
//================================================================================= 19 ==
         case 0:                                         // Тенденция синяя
            switch(Vector)                               // По направлению
               {
//--------------------------------------------------------------------------------- 20 --
               case 1:                                   // Вверх (в направлении типа)
                  if (NormalizeDouble(Data-Last_Max,Digits)>0.0)
                     Last_Max = Data;
                  if (NormalizeDouble(Data-(Last_Max-delta),Digits)<=0.0)//Разворот
                     {
                     Vector = -1;                        // Направление - вверх
                     Pr_Max = Last_Max;                  // Новая цена горизонта
                     Last_Min = Data;   
                        Last_V = i;                         // Индекс последней вертикали
                     if (NormalizeDouble(Last_Min-Pr_Min,Digits)<0.0)// Ниже реверса
                        {
                        Tip = 1;                         // Тенденция меняется на красную
                        Gor_S[i]=Close[i];               // Новые значения массивов
                        Gor_B[i]=EMPTY_VALUE;            // Новые значения массивов
                        }
                     }   
                     break;
//--------------------------------------------------------------------------------- 21 --
               case -1:                                  // Вниз
                  if (NormalizeDouble(Data-Last_Min,Digits)<0.0)
                     {
                     Last_Min = Data;
                     if (NormalizeDouble(Last_Min-Pr_Min,Digits)<0.0)// Ниже реверса
                        {
                        Tip = 1;                         // Тенденция меняется на красную
                        Gor_S[i]=Close[i];               // Новые значения массивов
                        Gor_B[i]=EMPTY_VALUE;            // Новые значения массивов
                        }
                     }
                  if (NormalizeDouble(Data-(Last_Min+delta),Digits)>=0.0)//Разв.
                     {
                     Vector = 1;                         // Направление - вверх
                     Pr_Min = Last_Min;                  // Новая цена горизонта
                     Last_Max = Data;                    // Текущий минимум
                     Last_V = i;                         // Индекс последней вертикали
                     }
                  break;
//--------------------------------------------------------------------------------- 22 --
               }
            break;
//================================================================================= 23 ==
         }
      i--;
      }
//================================================================================= 29 ==
   return;
   }
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж Конец модуля жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж 45 жж
 

 Рассмотрим какие изменения внесены код индикатора. Для удобства нумерация блоков в индикаторе Kagi_Ind_Trade.mq4 полностью сохранена (унаследована от Kagi_Ind_7.mq4).

Блок 1-3. В индикаторе Kagi_Ind_Trade.mq4 используются всего два индикаторных массива, удалены все переменные, использовавшиеся в Kagi_Ind_7.mq4 в расчётах для построения линии каги и экономических показателей.

Блок 3-9. В функции init() указанны настройки для отображения двух линий - "красной" и "синей" тенденций. Настройки для других (отсутствующих) массивов удалены.

Весь основной код функции start() оставлен без изменения. Удалены все строки кода, используемые для построения линии каги. В частности, удалены блоки 30-33, 33-36, 36-40, 40-45, содержащие описание функций для расчёта отсутствующих индикаторных массивов, а также вызовы этих функций в функции start().

Для расчёта индикаторных массивов принят простой принцип. Если тенденция сохраняется, то значение последнего (i-го) элемента индикаторного массива приравнивается цене закрытия i-го бара. Если же тенденция изменяется, то в i-й элемент индикаторного массива записывается пустое значение. Таким образом, на каждом баре отображается либо красная либо синяя линия. Для реализации этого метода в блок 14-15 добавлены строки:

 
      if (Gor_B[i+1] != EMPTY_VALUE)            // Перед расчётом принимаем ..
         Gor_B[i]=Close[i];                     // .. старые значения как значимые
      else
         Gor_B[i]=EMPTY_VALUE;                  // .. старые значения как значимые
         
         if (Gor_S[i+1] != EMPTY_VALUE)            // Перед расчётом принимаем ..
            Gor_S[i]=Close[i];                     // .. старые значения как значимые
      else
         Gor_S[i]=EMPTY_VALUE;                  // .. старые значения как значимые
 

В указанных строках реализован принцип наследования тенденции. Если же в дальнейших расчётах вычисляется факт изменения тенденции, то значения элементов массивов переопределяются. Например, в блоке 16-17 при изменении тенденции с красной на синюю выполняются следующие действия:

 
                      if (NormalizeDouble(Last_Max-Pr_Max,Digits)>0.0)// Выше реверса
                        {
                        Tip = 0;                         // Тенденция меняется на синюю
                        Gor_B[i]=Close[i];               // Новые значения массивов
                        Gor_S[i]=EMPTY_VALUE;            // Новые значения массивов
                        }
 

До указанных вычислений значение элемента индикаторного массива Gor_B[i] было равно пустому значению, а элемента Gor_S[i] - цене закрытия i-го бара. Аналогичные вычисления выполняются во всех последующих блоках, где вычисляется факт смены тенденции.

Важное изменение выполнено в блоке 13-14. В индикаторе Kagi_Ind_7.mq4 данные, принимаемые к расчёту, вычисляются так:

 
         case 1:  Data = iMA(NULL,0,Period_MA,0,MODE_SMMA,PRICE_TYPICAL,i); break;
 

Здесь указано нулевое значение второго параметра. Это значит, что данные берутся с текущего таймфрейма. Однако, после исследований при тестировании будет определён конкретный таймфрейм, из которого должны браться данные для расчётов. Поэтому, в индикаторе Kagi_Ind_Trade.mq4 указан следующий код:

 
         case 1:  Data = iMA(NULL,TimeFrame,Period_MA,0,MODE_SMMA,PRICE_TYPICAL,i); break;
 

 

В данном варианте вторым параметром указана настраиваемая переменная TimeFrame.  При получении данных пользовательского индикатора в эксперте в списке параметров функции iCustom() необходимо будет указать TimeFrame (указать все внешние переменные в том порядке, в котором они указаны в индикаторе Kagi_Ind_Trade.mq4).

Пользовательский индикатор Kagi_Ind_Trade.mq4 был задуман как источник данных для расчёта торговых критериев в эксперте. Однако, он может использоваться также для визуального наблюдения тенденций. Этот индикатор выгодно отличается тем, что смена тенденций отображается на том баре, на котором она происходит фактически (в отличие от линии каги, рассчитанной в индикаторе Kagi_Ind_7.mq4).

Рис. 2. Индикаторы Kagi_Ind_7 и Kagi_Ind_Trade в окне финансового инструмента.

На Рис. 2 показаны линии обоих индикаторов. Смена тенденции индикатора Kagi_Ind_7 происходит в точке А, в момент, когда МА в точке В преодолевает последний уровень, сформированный "синей" тенденцией. Индикатор Kagi_Ind_Trade показывает фактическую (последнюю известную) цену в точке С, которая должна приниматься во внимание при расчёте торговых критериев.

Аналогичное изображение показано на Рис. 3, когда тенденция меняется с красной на синюю.

Рис. 3. Индикаторы Kagi_Ind_7 и Kagi_Ind_Trade в окне финансового инструмента.

 

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

 Сергей Ковалёв
Апрель 2009
http://autograf.dp.ua/
Специально для компании Admiral Markets
 

4.1
 
 
X
Loading