Эффективные алгоритмы усреднения с минимальным лагом и их использование в индикаторах и экспертах

Автор: lexy Вторник, Сентябрь 9th, 2014 Нет комментариев

Рубрика: Разное

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

Одна и та же торговая система с использованием различных алгоритмов усреднения может показывать весьма внушительные отличия торговых показателей. Причём никогда нельзя сказать заранее, какие из имеющихся в наличии алгоритмов усреднения обеспечат максимальную прибыльность торговой системы. Так что гораздо разумнее будет строить код с возможностью использования в нём абсолютно различных алгоритмов усреднения, выбор которых можно осуществлять посредством изменения значений внешних переменных эксперта. В конечном итоге при таком подходе дело сводится к замене индикаторов, которые использует эксперт, на самостоятельно написанные с более гибкой настройкой выбора алгоритмов усреднения. Таким образом, данный подход можно разделить на три этапа:

1. Пишется рабочий код эксперта на основе стандартных мувингов и индикаторов, входящих в комплект технических индикаторов клиентского терминала MetaTrader 4.
2. Пишутся пользовательские индикаторы по описаниям стандартных индикаторов с возможностью использования более гибкой замены алгоритмов сглаживания.
3. Делается замена обращений к техническим индикаторам на обращения к этим пользовательским индикаторам с вытаскиванием внешних переменных этих индикаторов во внешние переменные эксперта.

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

Универсальная функция усреднения

В своей предыдущей статье я ознакомил читателей с пятью функциями усреднения. Для большей полноты комплекта к этим функциям следовало бы добавить ещё и MASeries() с классическими алгоритмами усреднения, что я сейчас и сделаю:

double MASeries
(
  int number, int MA_Method, int MaxBar, int limit, int period, double series, int bar, int& reset
)

Функция в плане её использования абсолютно аналогична предыдущим пяти функциям, так что в каких-либо подробных комментариях не нуждается. Программный код этой функции представлен файлом MASeries.mqh.

Теперь на базе этих шести функций можно построить универсальную функцию усреднения, которую я назвал SmoothXSeries() и разместил в файле SmoothXSeries.mqh. Как и предыдущие функции эта функция объявляется директивой #include < >:

#include <SmoothXSeries.mqh>

В плане внешних переменных эта функция аналогична функции JJMASeries(), но появляется новая переменная идентификатора алгоритма усреднения SmoothMode:

double SmoothXSeries
(
  int number,int SmoothMode, int din, int MaxBar, int limit, int Phase, int Length, double Series, int bar, int& reset
)

Варьированием значения этого параметра SmoothMode от нуля до восьми и достигают выбора требуемого алгоритма усреднения:

  // 0 : JJMA
  // 1 : JurX        
  // 2 : ParMA
  // 3 : LRMA
  // 4 : T3
  // 5 : SMA
  // 6 : EMA
  // 7 : SSMA
  // 8 : LWMA

Вполне естественно, что переменные din и Phase оказываются задействованными только для тех алгоритмов усреднения, для которых они были определены первоначально. Прежде, чем использовать эту функцию в коде индикатора, следует произвести инициализацию переменных этой функции и распределить память для них. Для этого в блоке инициализации индикатора необходимо сделать обращение к функции SmoothXSeriesResize(). В качестве значения её внешней переменной Size следует сделать количество обращений к функции SmoothXSeries() в коде индикатора

  //Десять обращений  к функции SmoothXSeriesResize() в коде индикатора
  SmoothXSeriesResize(10);

Теперь, имея универсальный алгоритм усреднения SmoothXSeries(), можно приступать к построению кода индикаторов.

Универсальный мувинг

Любой мувинг(от англ. moving — скользящая) получается сглаживанием какой-нибудь ценовой таймсерии. В своей предыдущей статье я познакомил читателей с функцией PriceSeries() для выбора значений ценового ряда таймсерии. Вся задача построения мувинга сводится к обработке этих значений ценового ряда функцией SmoothXSeries() и передача их в индикаторный буфер. Вот вариант реализации кода:

/*
Для  работы  индикатора  следует  положить файлы 

SmoothXSeries.mqh
T3Series.mqh
MASeries.mqh
LRMASeries.mqh
JurXSeries.mqh
ParMASeries.mqh
JJMASeries.mqh
PriceSeries.mqh
в папку (директорию): MetaTrader\experts\include\

Heiken Ashi#.mq4
в папку (директорию): MetaTrader\indicators\
*/
//+X================================================================X+  
//|                                                         X1MA.mq4 |
//|                        Copyright © 2009,        Nikolay Kositsin |
//|                              Khabarovsk,   farria@mail.redcom.ru |
//+X================================================================X+  
#property copyright "Copyright © 2009, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//---- отрисовка индикатора в основном окне
#property indicator_chart_window
//---- количество индикаторных буферов
#property indicator_buffers 1
//---- цвет индикатора
#property indicator_color1 Red
//---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА +-------------------------------------------------+
extern int Smooth_Mode = 0;   // Выбор алгоритма сглаживания 0 - JJMA, 1 - JurX,        
                 // 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA
extern int Length = 11;   // глубина сглаживания
extern int Phase  = 100; // параметр, изменяющийся в пределах -100 ... +100,
                                       //влияет на качество переходного процесса;
extern int Shift  = 0;   // cдвиг индикатора вдоль оси времени
extern int Input_Price_Customs = 0; /* Выбор цен, по которым производится расчёт
индикатора (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL,
6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW,
11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */
//---- +------------------------------------------------------------------------------+
//---- буферы
double XMA[];
//---- переменные  
bool INIT;
int  StartBar;
//+X================================================================X+  
//| SmoothXSeries() function                                         |
//+X================================================================X+    
//----+ Объявление функции SmoothXSeries
//----+ Объявление функции SmoothXSeriesResize
//----+ Объявление функции SmoothXSeriesAlert  
#include <SmoothXSeries.mqh>
//+X================================================================X+  
//| PriceSeries() function                                           |
//+X================================================================X+    
//----+ Объявление функции PriceSeries
//----+ Объявление функции PriceSeriesAlert
#include <PriceSeries.mqh>
//+X================================================================X+  
//| X1MA initialization function                                     |
//+X================================================================X+
int init()
{
//----+
   //---- установка стиля изображения индикатора
   SetIndexStyle(0, DRAW_LINE);
   //---- определение буфера для подсчёта
   SetIndexBuffer(0, XMA);
   //---- установка значений индикатора, которые не будут видимы на графике
   SetIndexEmptyValue(0, 0.0);  
   //---- установка алертов на недопустимые значения внешних переменных
   JJMASeriesAlert (0, "Length", Length);
   JJMASeriesAlert (1, "Phase",   Phase);
   PriceSeriesAlert(Input_Price_Customs);
   //----+ Изменение размеров буферных переменных функции
           //SmoothXSeries, number = 1(Одно обращение к функции SmoothXSeries)
   if (SmoothXSeriesResize(1) != 1)
    {
     INIT = false;
     return(0);
    }
   //---- инициализация переменных
   if (Smooth_Mode > 0 && Smooth_Mode < 9)
                              StartBar = Length;
   else StartBar = 30;
   //---- установка номера бара,
                     //начиная с которого будет отрисовываться индикатор
   SetIndexDrawBegin(0, StartBar);
   //---- Установка формата точности отображения индикатора
   IndicatorDigits(Digits);
   //---- завершение инициализации
   INIT = true;
   return(0);
//----+
}
//+X================================================================X+  
//| X1MA iteration function                                          |
//+X================================================================X+  
int start()
{
//----+
   //---- Получение количества всех баров
   int Bars_ = Bars - 1;
//---- проверка завершения инициализации и
     //проверка количества баров на достаточность для расчёта
if (!INIT || Bars_ <= StartBar)
                  return(-1);
//---- Введение переменных с плавающей точкой
double Price, xma;
//---- Введение целых переменных и получение
                           //количества уже посчитанных баров
int reset, MaxBar, limit, bar, counted_bars = IndicatorCounted();
//---- проверка на возможные ошибки
if (counted_bars < 0)
    return(-1);
//---- последний посчитанный бар должен быть пересчитан
if (counted_bars > 0)
counted_bars--;
//---- определение номера самого старого бара,
//начиная с которого будет произедён пересчёт новых баров
limit = Bars_ - counted_bars;
//---- определение номера самого старого бара,
//начиная с которого будет произедён пересчёт всех баров
MaxBar = Bars_;
//----+ основной цикл расчёта индикатора
for(bar = limit; bar >= 0; bar--)
{
  //---- Получение исходного значения ценового ряда
  Price = PriceSeries(Input_Price_Customs, bar);
  //---- X1MA сглаживание исходного значения ценового ряда,
  //---- Обращение к функции SmoothXSeries за номером 0,
//параметры Phase и Length не меняются на каждом баре (din = 0)
  xma = SmoothXSeries(0, Smooth_Mode, 0, MaxBar, limit,
                                     Phase, Length, Price, bar, reset);
  //---- проверка на отсутствие ошибки в предыдущей операции
  if(reset != 0)
  return(-1);

  XMA[bar] = xma;
  //----
}
//---- завершение вычислений значений индикатора
return(0);
//----+  
}
//+X--------------------+ <<< The End >>> +--------------------X+

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

Универсальный мувинг с использованием двойного усреднения

Эффективность работы с таким мувингом можно значительно улучшить, если произвести дополнительное сглаживание полученного индикатора всё той же функцией SmoothXSeries()

/*
Для  работы  индикатора  следует  положить файлы 

SmoothXSeries.mqh
T3Series.mqh
MASeries.mqh
LRMASeries.mqh
JurXSeries.mqh
ParMASeries.mqh
JJMASeries.mqh
PriceSeries.mqh
в папку (директорию): MetaTrader\experts\include\

Heiken Ashi#.mq4
в папку (директорию): MetaTrader\indicators\
*/
//+X================================================================X+  
//|                                                         X2MA.mq4 |
//|                        Copyright © 2009,        Nikolay Kositsin |
//|                              Khabarovsk,   farria@mail.redcom.ru |
//+X================================================================X+  
#property copyright "Copyright © 2009, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//---- отрисовка индикатора в основном окне
#property indicator_chart_window
//---- количество индикаторных буферов
#property indicator_buffers 1
//---- цвет индикатора
#property indicator_color1 Lime
//---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА +-------------------------------------------------+
extern int Smooth_Mode1 = 0;   // Выбор алгоритма 1 сглаживания 0 - JJMA, 1 - JurX,        
                 // 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA
extern int Length1 = 9;   // глубина сглаживания
extern int Phase1  = 100; // параметр, изменяющийся в пределах -100 ... +100,
                                       //влияет на качество переходного процесса;
extern int Smooth_Mode2 = 0;   // Выбор алгоритма 2 сглаживания 0 - JJMA, 1 - JurX,        
                 // 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA
extern int Length2 = 5;   // глубина сглаживания
extern int Phase2  = 100; // параметр, изменяющийся в пределах -100 ... +100,
                                       //влияет на качество переходного процесса;  
extern int Shift  = 0;   // cдвиг индикатора вдоль оси времени
extern int Input_Price_Customs = 0; /* Выбор цен, по которым производится расчёт
индикатора (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL,
6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW,
11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */
//---- +------------------------------------------------------------------------------+
//---- буферы
double X2MA[];
//---- переменные  
bool INIT;
int  StartBar, StartBar1, StartBar2;
//+X================================================================X+  
//| SmoothXSeries() function                                         |
//+X================================================================X+    
//----+ Объявление функции SmoothXSeries
//----+ Объявление функции SmoothXSeriesResize
//----+ Объявление функции SmoothXSeriesAlert  
#include <SmoothXSeries.mqh>
//+X================================================================X+  
//| PriceSeries() function                                           |
//+X================================================================X+    
//----+ Объявление функции PriceSeries
//----+ Объявление функции PriceSeriesAlert
#include <PriceSeries.mqh>
//+X================================================================X+  
//| X2MA initialization function                                     |
//+X================================================================X+
int init()
{
//----+
   //---- установка стиля изображения индикатора
   SetIndexStyle(0, DRAW_LINE);
   //---- определение буфера для подсчёта
   SetIndexBuffer(0, X2MA);
   //---- установка значений индикатора, которые не будут видимы на графике
   SetIndexEmptyValue(0, 0.0);
   //---- установка алертов на недопустимые значения внешних переменных
   JJMASeriesAlert (0, "Length1", Length1);
   JJMASeriesAlert (1, "Phase1",   Phase1);
   JJMASeriesAlert (0, "Length2", Length2);
   JJMASeriesAlert (1, "Phase2",   Phase2);
   PriceSeriesAlert(Input_Price_Customs);
   //----+ Изменение размеров буферных переменных функции
           //SmoothXSeries, number = 2(Два обращения к функции SmoothXSeries)
   if (SmoothXSeriesResize(2) != 2)
    {
     INIT = false;
     return(0);
    }
   //---- инициализация переменных
   if (Smooth_Mode1 > 0 && Smooth_Mode1 < 9)
                              StartBar1 = Length1;
   else StartBar1 = 30;

   if (Smooth_Mode2 > 0 && Smooth_Mode2 < 9)
                              StartBar2 = Length2;
   else StartBar2 = 30;
   StartBar = StartBar1 + StartBar2;
   //---- установка номера бара,
                     //начиная с которого будет отрисовываться индикатор
   SetIndexDrawBegin(0, StartBar);
   //---- Установка формата точности отображения индикатора
   IndicatorDigits(Digits);
   //---- завершение инициализации
   INIT = true;
   return(0);
//----+
}
//+X================================================================X+  
//| X2MA iteration function                                          |
//+X================================================================X+  
int start()
{
//----+
   //---- Получение номера последнего бара
   int Bars_ = Bars - 1;
//---- проверка завершения инициализации и
     //проверка количества баров на достаточность для расчёта
if (!INIT || Bars_ <= StartBar)
                  return(-1);
//---- Введение переменных с плавающей точкой
double Price, x1ma, x2ma;
//---- Введение целых переменных и получение
                        //количества уже посчитанных баров
int reset, MaxBar1, MaxBar2, limit,
                   bar, counted_bars = IndicatorCounted();
//---- проверка на возможные ошибки
if (counted_bars < 0)
    return(-1);
//---- последний подсчитанный бар должен быть пересчитан
if (counted_bars > 0)
counted_bars--;
//---- определение номера самого старого бара,
//начиная с которого будет произедён пересчёт новых баров
limit = Bars_ - counted_bars;
//---- определение номера самого старого бара,
//начиная с которого будет произедён пересчёт всех баров
MaxBar1 = Bars_;
MaxBar2 = MaxBar1 - StartBar1;

//----+ основной цикл расчёта индикатора
for(bar = limit; bar >= 0; bar--)
{
  //---- Получение исходного значения ценового ряда
  Price = PriceSeries(Input_Price_Customs, bar);
  //---- X1MA сглаживание исходного значения ценового ряда,
  //---- Обращение к функции SmoothXSeries за номером 0,
//параметры Phase и Length не меняются на каждом баре (din = 0)
  x1ma = SmoothXSeries(0, Smooth_Mode1, 0, MaxBar1, limit,
                                     Phase1, Length1, Price, bar, reset);
  //---- проверка на отсутствие ошибки в предыдущей операции
  if(reset != 0)
  return(-1);
  //---- X2MA сглаживание полученного индикатора,
  //---- Обращение к функции SmoothXSeries за номером 1,
//параметры Phase и Length не меняются на каждом баре (din = 0)
  x2ma = SmoothXSeries(1, Smooth_Mode2, 0, MaxBar2, limit,
                                     Phase2, Length2, x1ma,  bar, reset);
  //---- проверка на отсутствие ошибки в предыдущей операции
  if(reset != 0)
  return(-1);
  //----      
  X2MA[bar] = x2ma;
  //----
}
//----+ завершение вычислений значений индикатора
return(0);
//----+  
}
//+X--------------------+ <<< The End >>> +--------------------X+

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

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

       //----+ нормализация полученного значения x2ma
       double Norma = Step * Point;
       //----
       x2ma /= Norma;
       x2ma = NormalizeDouble(x2ma, 0);
       x2ma *= Norma;

Переменная Step представляет собой целый внешний параметр индикатора, который определяет шаг дискретизации значений полученного мувинга в пунктах. Приводить весь код этого индикатора в тексте статьи нецелесообразно, читатель может самостоятельно ознакомиться с ним, используя прикреплённый к статье индикатор X2DigMa.mq4.

Практические рекомендации по оптимизации экспертов, использующих индикатор X2DigMa.mq4

Данный мувинг имеет достаточно большое количество внешних переменных, и поэтому любого эксперта, сделанного на основе этого индикатора, можно весьма недурно подогнать под какой угодно рынок. Однако формальная подгонка параметров эксперта — это далеко не самый оптимальный способ его программирования для дальнейшей работы. Следовало бы немного поподробнее остановиться на нюансах работы с внешними переменными такого мувинга в эксперте. Итак, допустим мы имеем эксперта, в котором все внешние переменные мувинга X2DigMA.mq4 сделаны внешними переменными эксперта.

 

extern int Smooth_Mode1 = 0;
extern int Length1 = 9;
extern int Phase1  = 100;
extern int Smooth_Mode2 = 0;
extern int Length2 = 5;
extern int Phase2  = 100;
extern int Step = 10;
extern int Input_Price_Customs = 0;

Переменная Smooth_Mode1 принимает значение от нуля и до восьми, но оптимизировать значение этой переменной в тестере стратегий с использованием генетического алгоритма не стоит! Гораздо лучше будет сделать восемь независимых оптимизаций для каждого значения этой переменной. Значение аналогичной переменной для повторного сглаживания Smooth_Mode2 лучше зафиксировать равным нулю. В таком случае в качестве повторного сглаживания будет использоваться алгоритм JMA усреднения, который имеет самый минимальный лаг и в качестве дополнительного усреднения во многих ситуациях даёт самые лучшие результаты.

Параметры Phase1 и Phase2, которые используются только в JMA и T3 усреднениях, лучше тоже зафиксировать на значении равном ста(100). Параметр Length2 может принимать какие угодно значения, но во многих ситуациях и в абсолютно разных экспертах самыми оптимальными зачастую оказываются одни и те же значения из ряда 3, 5, 7, 9, 11. Перебора этих значений параметра Length2, как правило, более чем достаточно. Параметр Step сильно зависит от рынка, на котором работает эксперт и периода графика, но зачастую стабилизируется на одних и тех же значениях. Лучшими значениями параметра Input_Price_Customs оказываются ноль и девять. В итоге для досконального исследования остаётся всего один параметр Length1, значения которого могут быть какими угодно.

Универсальная MACD диаграмма

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

/*
Для  работы  индикатора  следует  положить файлы 

SmoothXSeries.mqh
T3Series.mqh
MASeries.mqh
LRMASeries.mqh
JurXSeries.mqh
ParMASeries.mqh
JJMASeries.mqh
PriceSeries.mqh
в папку (директорию): MetaTrader\experts\include\

Heiken Ashi#.mq4
в папку (директорию): MetaTrader\indicators\
*/
//+X================================================================X+  
//|                                                        XMACD.mq4 |
//|                        Copyright © 2009,        Nikolay Kositsin |
//|                              Khabarovsk,   farria@mail.redcom.ru |
//+X================================================================X+  
#property copyright "Copyright © 2009, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//---- отрисовка индикатора в отдельном окне
#property  indicator_separate_window
//---- количество индикаторных буферов
#property indicator_buffers 2
//---- цвета индикатора
#property  indicator_color1  Blue
#property  indicator_color2  Magenta
//---- толщина линии диаграммы
#property  indicator_width1  2
//---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА
extern int MACD_Mode = 0;  // Выбор алгоритма сглаживания для MACD 0 - JJMA, 1 - JurX,        
                 // 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA
extern int MACD_Phase = 100;
extern int FastXMA = 12;
extern int SlowXMA = 26;
extern int Signal_Mode = 0;  // Выбор алгоритма сглаживания для сигнальной линии
  //0 - JJMA, 1 - JurX, 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA
extern int Signal_Phase = 100;
extern int SignalXMA = 9;
extern int Input_Price_Customs = 0; /* Выбор цен, по которым производится расчёт
индикатора (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL,
6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW,
11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */
//---- индикаторные буферы
double     XMacdBuffer[];
double     XSignalBuffer[];
//---- переменные
bool   INIT;
int    StartBar, StartBar1, StartBar2;
//+X================================================================X+  
//| SmoothXSeries() function                                         |
//+X================================================================X+    
//----+ Объявление функции SmoothXSeries
//----+ Объявление функции SmoothXSeriesResize
//----+ Объявление функции SmoothXSeriesAlert  
#include <SmoothXSeries.mqh>
//+X================================================================X+  
//| PriceSeries() function                                           |
//+X================================================================X+    
//----+ Объявление функции PriceSeries
//----+ Объявление функции PriceSeriesAlert
#include <PriceSeries.mqh>
//+X================================================================X+
//| XMACD indicator initialization function                          |
//+X================================================================X+
int init()
  {
//----+
   //---- установка стиля изображения индикатора
   SetIndexStyle(0, DRAW_HISTOGRAM);
   SetIndexStyle(1, DRAW_LINE);
   //---- Установка формата точности (количество знаков
        //после десятичной точки) для визуализации значений индикатора
   IndicatorDigits(Digits + 1);
   //---- определение буферов для подсчёта
   SetIndexBuffer(0, XMacdBuffer);
   SetIndexBuffer(1, XSignalBuffer);
   //---- имена для окон данных и лэйбы для субъокон
   IndicatorShortName(StringConcatenate
            ("XMACD(", FastXMA, ",", SlowXMA, ",", SignalXMA, ")"));
   SetIndexLabel(0, "XMACD");
   SetIndexLabel(1, "XSignal");
   //---- установка алертов на недопустимые значения внешних переменных
   JJMASeriesAlert (0, "FastXMA", FastXMA);
   JJMASeriesAlert (0, "SlowXMA", SlowXMA);
   JJMASeriesAlert (0, "SignalXMA", SignalXMA);
   //----
   JJMASeriesAlert (1, "MACD_Phase", MACD_Phase);  
   JJMASeriesAlert (1, "Signal_Phase", Signal_Phase);
   PriceSeriesAlert(Input_Price_Customs);
   //---- Изменение размеров буферных переменных функции
           //SmoothXSeries, number = 3(Три обращения к функции SmoothXSeries)
   if (SmoothXSeriesResize(3) != 3)
    {
     INIT = false;
     return(0);
    }
   //---- инициализация переменных
   if (MACD_Mode > 0 && MACD_Mode < 9)
                            StartBar1 = MathMax( FastXMA, SlowXMA);
   else StartBar1 = 30;
   //----
   if (Signal_Mode > 0 && Signal_Mode < 9)
                          StartBar2 = SignalXMA;
   else StartBar2 = 30;
   //----
   StartBar = StartBar1 + StartBar2;
   //----
   SetIndexDrawBegin(0, StartBar1);
   SetIndexDrawBegin(1, StartBar);
   //---- завершение инициализации
   INIT = true;
   return(0);
//----+
  }
//+X================================================================X+
//| XMACD indicator iteration function                               |
//+X================================================================X+
int start()
  {
//----+
   //---- Получение номера последнего бара
   int Bars_ = Bars - 1;
//---- проверка завершения инициализации и
     //проверка количества баров на достаточность для расчёта
if (!INIT || Bars_ <= StartBar)
                  return(-1);
//---- Введение переменных с плавающей точкой
double Price, FastXMA_, SlowXMA_, XMACD, SignalXMA_;
//---- Введение целых переменных и получение
                        //количества уже посчитанных баров
int reset, MaxBar1, MaxBar2, limit,
                   bar, counted_bars = IndicatorCounted();
//---- проверка на возможные ошибки
if (counted_bars < 0)
    return(-1);
//---- последний подсчитанный бар должен быть пересчитан
if (counted_bars > 0)
counted_bars--;
//---- определение номера самого старого бара,
//начиная с которого будет произедён пересчёт новых баров
limit = Bars_ - counted_bars;
//---- определение номера самого старого бара,
//начиная с которого будет произедён пересчёт всех баров
MaxBar1 = Bars_;
MaxBar2 = MaxBar1 - StartBar1;

   //----+ основной цикл расчёта индикатора
for(bar = limit; bar >= 0; bar--)
{
  //---- Получение исходного значения ценового ряда
  Price = PriceSeries(Input_Price_Customs, bar);
  //---- FastXMA сглаживание исходного значения ценового ряда,
  //---- Обращение к функции SmoothXSeries за номером 0,
//параметры Phase и Length не меняются на каждом баре (din = 0)
  FastXMA_ = SmoothXSeries(0, MACD_Mode, 0, MaxBar1, limit,
                              MACD_Phase, FastXMA, Price, bar, reset);
  //---- проверка на отсутствие ошибки в предыдущей операции
  if(reset != 0)
  return(-1);
  //---- SlowXMA сглаживание исходного значения ценового ряда,
  //---- Обращение к функции SmoothXSeries за номером 1,
//параметры Phase и Length не меняются на каждом баре (din = 0)
  SlowXMA_ = SmoothXSeries(1, MACD_Mode, 0, MaxBar1, limit,
                             MACD_Phase, SlowXMA, Price,  bar, reset);                      
  //---- проверка на отсутствие ошибки в предыдущей операции
  if(reset != 0)
  return(-1);
  //----  
  if(bar < MaxBar2)
         XMACD = FastXMA_ - SlowXMA_;

  //---- SignalXMA сглаживание полученной диаграммы XMACD,
  //---- Обращение к функции SmoothXSeries за номером 2,
//параметры Phase и Length не меняются на каждом баре (din = 0)
  SignalXMA_ = SmoothXSeries(2, Signal_Mode, 0, MaxBar2, limit,
                         Signal_Phase, SignalXMA, XMACD,  bar, reset);            
  //---- проверка на отсутствие ошибки в предыдущей операции
  if(reset != 0)
  return(-1);
  //----
  XMacdBuffer[bar] = XMACD;
  XSignalBuffer[bar] = SignalXMA_;  
    }
   return(0);

//----+
  }
//+X----------------------+ <<< The End >>> +-----------------------X+

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

Заключение

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

Прикрепленные файлы:
 INCLUDE.zip (47.5 Kb)
 indicators.zip (11.5 Kb)
Источник: mql4.com

Оставить комментарий

Чтобы оставлять комментарии Вы должны быть авторизованы.

Похожие посты