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

Nikolay Kositsin | 25 января, 2007

Введение

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

В обычном исполнении без цветовой окраски индикаторов направления тренда:


и в исполнении, при котором цвет индикаторов дифференцированно окрашивается в зависимости от направления тренда:



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

Займемся построением таких индикаторов.


Трехцветный индикатор 3c_JJRSX1


Прежде всего займемся построением трехцветной линейной диаграммы на основе осциллятора JJRSX:

iCustom(NULL,0,"JJRSX",Length,Smooth,Smooth_Phase,
        Input_Price_Customs,0,bar).

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

/*
Для  работы  индикатора  следует  положить  файлы  
JJMASeries.mqh 
JurXSeries.mqh 
PriceSeries.mqh 
в папку (директорию): MetaTrader\experts\include\
Heiken Ashi#.mq4
в папку (директорию): MetaTrader\indicators\
*/
//+------------------------------------------------------------------+ 
//|                                                    3c_JJRSX1.mq4 |
//|                           Copyright c 2006,     Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+ 
#property copyright "Copyright c 2006, Nikolay Kositsin"
#property link      "farria@mail.redcom.ru" 
//---- отрисовка индикатора в отдельном окне
#property indicator_separate_window
//---- количество индикаторных буферов
#property indicator_buffers  3
//---- цвета индикатора
#property indicator_color1  BlueViolet
#property indicator_color2  Magenta
#property indicator_color3  Gray
//---- толщина индикаторных линий
#property indicator_width1 3
#property indicator_width2 3
#property indicator_width3 3
//---- параметры горизонтальных уровней индикатора
#property indicator_level1  0.5
#property indicator_level2 -0.5
#property indicator_level3  0.0
#property indicator_levelcolor MediumBlue
#property indicator_levelstyle 4
//---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА 
extern int        Length = 8;  // глубина сглаживания индикатора
extern int        Smooth = 3; // глубина дополнительного JMA сглаживания
// дополнительного JMA сглаживания, изменяющийся в пределах -100 ... +100, 
//влияет на качество переходного процесса;
extern int  Smooth_Phase = 100;
/* Выбор цен, по которым производится расчёт индикатора 
(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.) */
extern int Input_Price_Customs = 0; 
//---- индикаторные буферы
double Ind_Buffer1[];
double Ind_Buffer2[];
double Ind_Buffer3[]; 
//+------------------------------------------------------------------+  
//| JJRSX initialization function                                    |
//+------------------------------------------------------------------+ 
int init()
  {
// стили изображения индикатора
   SetIndexStyle(0,DRAW_HISTOGRAM, STYLE_SOLID);
   SetIndexStyle(1,DRAW_HISTOGRAM, STYLE_SOLID);
   SetIndexStyle(2,DRAW_HISTOGRAM, STYLE_SOLID);
// 4 индикаторных буфера использованы для счёта 
   SetIndexBuffer(0,Ind_Buffer1);
   SetIndexBuffer(1,Ind_Buffer2);
   SetIndexBuffer(2,Ind_Buffer3);
// установка значений индикатора, которые не будут видимы на графике
   SetIndexEmptyValue(0,0); 
   SetIndexEmptyValue(1,0);
   SetIndexEmptyValue(2,0);
// имена для окон данных и лэйбы для субъокон
   SetIndexLabel(0,"Up_Trend");
   SetIndexLabel(1,"Down_Trend");
   SetIndexLabel(2,"Straight_Trend");
   IndicatorShortName("JJRSX(Length="+Length+")");
// Установка формата точности (количество знаков после десятичной точки) 
//для визуализации значений индикатора  
   IndicatorDigits(0);
// корекция недопустимого значения параметра Length
  if(Length<1)Length=1; 
// установка номера бара, начиная с которого будет отрисовываться индикатор  
   int draw_begin=3*Length+30+1; 
   SetIndexDrawBegin(0,draw_begin);
   SetIndexDrawBegin(1,draw_begin);
   SetIndexDrawBegin(2,draw_begin);   
//---- завершение инициализации
return(0);
  }
//+------------------------------------------------------------------+ 
//| JJRSX iteration function                                         |
//+------------------------------------------------------------------+ 
int start()
  {
// Введение целых переменных памяти
   static int time2;
// Введение переменных памяти с плавающей точкой 
   static double VelueM;
// Введение переменных с плавающей точкой   
    double Velue0,Velue1,trend; 
// Введение целых переменных и получение уже подсчитанных баров
    int bar,limit,MaxBar,Tnew,counted_bars=IndicatorCounted();
// проверка на возможные ошибки
    if (counted_bars<0)return(-1);
// последний подсчитанный бар должен быть пересчитан 
    if (counted_bars>0) counted_bars--;
// определение номера самого старого бара, 
// начиная с которого будет произедён пересчёт всех баров
    MaxBar=Bars-3*Length-30; 
    //---- определение номера самого старого бара, 
    //начиная с которого будет произедён пересчёт новых баров
    limit=Bars-counted_bars-1; 
    //+--- инициализация нуля
    if (limit>=MaxBar)
      for(bar=Bars-1;bar>=MaxBar;bar--)
       {
        limit=MaxBar;
        Ind_Buffer1[bar]=0.0;
        Ind_Buffer2[bar]=0.0;
        Ind_Buffer3[bar]=0.0;
       }
//+--- восстановление значений переменных 
    Tnew=Time[limit+1];
    if (limit<MaxBar)
    if (Tnew==time2)
     {
      Velue1=VelueM;
     }
    else 
     {
      if (Tnew>time2)
           Print("Ошибка восстановления переменных!!! Tnew>time2");
      else Print("Ошибка восстановления переменных!!! Tnew<time2");
      Print("Будет произведён пересчёт индикатора на всех барах!");
      return(-1);  
     }
//----+ ОСНОВНОЙ ЦИКЛ ВЫЧИСЛЕНИЯ ИНДИКАТОРА
    while (bar>=0)
      {
       //+--- Сохранение значений переменных +====+ 
     if (bar==1)
      {
       if(((limit==1)&&(time2==Time[2]))||(limit>1))
         {
          VelueM=Velue1;
          time2=Time[bar];
         }
      }
     //+---+====================================+          
        Velue0=iCustom(NULL,0,"JJRSX",Length,Smooth,Smooth_Phase,
                       Input_Price_Customs,0,bar);
        if (bar==MaxBar)
          {
           Velue1=Velue0;
           continue;
          }        
        //---- Трёхцветный код индикатора 
        trend=Velue0-Velue1;     
        if(trend>0)     
          {
            Ind_Buffer1[bar]=Velue0; 
            Ind_Buffer2[bar]=0;      
            Ind_Buffer3[bar]=0;
          }
        else
          {
            if(trend<0)
              {
                Ind_Buffer1[bar]=0;
                Ind_Buffer2[bar]=Velue0; 
                Ind_Buffer3[bar]=0;
              }
            else 
              {
                Ind_Buffer1[bar]=0;
                Ind_Buffer2[bar]=0;
                Ind_Buffer3[bar]=Velue0;
              }
          }    
        //---- 
        Velue1=Velue0;
        //----+
        bar--;
     } 
    //---- завершение вычислений значений индикатора
    return(0);
  }
//+--------------------------------------------------------------+


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

Velue0=iCustom(NULL,0,"JJRSX",Length,Smooth,Smooth_Phase, 
               Input_Price_Customs,0,bar);

имя пользовательского индикатора. В строке

MaxBar = Bars - 3*Length - 30;

нужно изменить формулу вычисления, также изменить формулу вычисления в строке

int draw_begin = 3*Length + 30 + 1;

в блоке инициализации. И, вполне естественно, заменить в шапке индикатора внешние переменные на необходимые. График можно сделать более информативным, если добавить в него индикатор BollingerBands и возможность изменять вид линейной диаграммы на точечную. Вдобавок, если использовать этот индикатор как шаблон, то возникают некоторые неудобства с поиском для замены нужных строк внутри программного кода, который никаким дальнейшим изменениям в других трехцветных диаграммах подвергаться не будет. Весь этот программный код было бы гораздо практичнее завернуть в mqh-файл и использовать его внутри индикатора с помощью оператора #include, что мы и сделаем. В таком случае код индикатора приобретает достаточно простой вид и в нем не остается лишних элементов. Его достаточно удобно использовать в качестве шаблона для написания других осцилляторных диаграмм:

/*
Для  работы  индикатора  следует  положить  файлы   
JJMASeries.mqh
PriceSeries.mqh
3c_BB_Osc.mqh  
в папку (директорию): MetaTrader\experts\include\
JJRSX.mq4 
Heiken Ashi#.mq4
в папку (директорию): MetaTrader\indicators\
*/
//+------------------------------------------------------------------+  
//|                                                     3c_JJRSX.mq4 |
//|                               Copyright © 2006, Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Nikolay Kositsin"
#property link      "farria@mail.redcom.ru"
//---- отрисовка индикатора в отдельном окне
#property indicator_separate_window
//---- количество индикаторных буферов
#property indicator_buffers 8 
//---- цвета индикатора 
#property indicator_color1 Gray 
#property indicator_color2 LimeGreen
#property indicator_color3 Red
#property indicator_color4 Purple
//---- Bollinger Bands цвета
#property indicator_color5 Blue
#property indicator_color6 Blue
#property indicator_color7 Magenta
#property indicator_color8 Magenta
//---- толщина индикаторных линий
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 1 
#property indicator_width4 1
//---- стиль огибающей линии
#property indicator_style1 4
//---- стиль линий Bollinger Bands
#property indicator_style5 4
#property indicator_style6 4
#property indicator_style7 4
#property indicator_style8 4
//---- параметры горизонтальных уровней индикатора
#property indicator_level1 0.0
#property indicator_levelcolor SteelBlue
#property indicator_levelstyle 4
//---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА
extern int  Length = 8;  // глубина JurX сглаживания индикатора
// глубина JJMA сглаживания полученного индикатора
extern int  Smooth = 3; 
// параметр, изменяющийся в пределах -100 ... +100, влияет на 
// качество переходныx процессов сглаживания
extern int  Phase = 100; 
/* Выбор цен, по которым производится расчёт индикатора 
(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.) */
extern int Input_Price_Customs = 0;
//---- Введение функции COUNT_begin() для вычисления номера бара, 
// начиная с которого будет отрисовываться индикатор и расчитываться 
// Bollinger Bands 
int COUNT_begin()
{int count_begin=2*Length+30;return(count_begin);}
//---- введение функции digits() для установки формата точности 
// (количество знаков после десятичной точки) для визуализации 
// значений индикатора 
int digits(){return(2);}
//---- установка значений индикатора, которые не будут видимы на графике 
int EmptyValue=0.0;
//---- Определение названия индикатора
string Label = "JJRSX";
 
//---- Включение в текст индикатора его основного текста
#include <3c_BB_Osc.mqh> 
//---- введение функции INDICATOR 
//---- обращение к исходному индикатору для получения иcходных значений
double INDICATOR(int INDICATOR.bar)
 {
  return(iCustom( NULL, 0, "JJRSX", Length, Smooth, Phase, 
         Input_Price_Customs, 0, INDICATOR.bar) );
 }
//---- ---------------------------------------------------------------+

Весь "лишний" код помещён в файл 3c_BB_Osc.mqh и представлен всего одной строкой

#include <3c_BB_Osc.mqh>

в индикаторе. В mqh-файл помещены и внешние переменные для полос Боллинджера и для выбора стиля отображения графика. Вполне естественно, что файл 3c_BB_Osc.mqh должен лежать в папке: \MetaTrader\EXPERTS\INCLUDE.



Алгоритм создания трехцветного индикатора


Теперь, для создания нового трёхцветного осциллятора, достаточно сохранить данный файл под новым именем в папке \MetaTrader\EXPERTS\indicators и сделать в нём некоторые изменения:

1. Выбрать цвета индикаторных элементов, которые вас устраивают и их остальные параметры;
2. Вписать новые входные параметры индикатора, перекопировав их из пользовательского индикатора;
3. Вписать в функцию COUNT_begin() формулу для расчёта стартового бара (обычно достаточно вписать внешнюю переменную индикатора, определяющую период или сумму этой переменной с переменной, производящей дополнительное сглаживание осциллятора);
4. Вписать в строку

digits()
  {
    return(2);
  }

необходимое значение точности индикатора. Если индикатор изменяется от 0 и до 100, то вписать ноль, если индикатор изменяется от нуля до единицы вписать 2 (два знака после запятой!);
5. Установить значения индикатора, которые не будут видимы на графике;
6. Сделать имя для индикатора;
7. Написать обращение к пользовательскому индикатору iCustom(). После этого откомпилировать получившийся код и индикатор готов!

Единственное, чтобы ещё иногда бы хотелось сделать, так это немного сгладить форму осциллятора. На такой случай в тексте индикатора достаточно дописать к имени mqh-файла букву "J": было

#include <3c_BB_Osc.mqh>

стало

#include <3c_BBJ_Osc.mqh>

При компиляции будет использован файл с JMA сглаживанием пользовательского осциллятора.


Трехцветный индикатор 3c_JJRSX2


Можно пойти на дальнейшее улучшение индикатора. Было бы неплохо добавить ещё один одноцветный быстрый JJRSX, он будет весьма к месту. Сам код индикатора по аналогии с последним примером разделим на две части, завернув в mqh-файл ту часть кода, которая максимально упрощает восприятие индикатора (3c_BB_Osc2.mqh):

/*
Для  работы  индикатора  следует  положить  файлы   
JJMASeries.mqh
JurXSeries.mqh
PriceSeries.mqh
3c_BB_Osc2.mqh  
в папку (директорию): MetaTrader\experts\include\
JJRSX.mq4 
Heiken Ashi#.mq4
в папку (директорию): MetaTrader\indicators\
*/
//+------------------------------------------------------------------+  
//|                                                    3c_JJRSX2.mq4 |
//|                               Copyright c 2006, Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+ 
#property copyright "Copyright c 2006, Nikolay Kositsin"
#property link      "farria@mail.redcom.ru"
//---- отрисовка индикатора в отдельном окне
#property indicator_separate_window
//---- количество индикаторных буферов
#property indicator_buffers 8 
//---- цвета индикатора 
#property indicator_color1 Gold
#property indicator_color2 LimeGreen 
#property indicator_color3 Red
#property indicator_color4 Purple
//---- Bollinger Bands цвета
#property indicator_color5 Blue
#property indicator_color6 Blue
#property indicator_color7 Magenta
#property indicator_color8 Magenta
//---- толщина индикаторных линий
#property indicator_width1 1
#property indicator_width2 2
#property indicator_width3 1 
#property indicator_width4 1
//---- стиль огибающей линии
#property indicator_style1 4
//---- стиль линий Bollinger Bands
#property indicator_style5 4
#property indicator_style6 4
#property indicator_style7 4
#property indicator_style8 4
//---- параметры горизонтальных уровней индикатора
#property indicator_level1  0.0
#property indicator_level2  0.8
#property indicator_level3 -0.8
//---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА
//---- входные параметры быстрого одноцветного JJRSX
extern int  Length1 = 8;  // глубина JurX сглаживания индикатора
// глубина JJMA сглаживания полученного индикатора
extern int  Smooth1 = 3;
// параметр, изменяющийся в пределах -100 ... +100, 
//влияет на качество переходныx процессов сглаживания
extern int  Phase1 = 100;
//Выбор цен, по которым производится расчёт индикатора 
extern int Input_Price_Customs1 = 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.) */
//---- входные параметры медленного трёхцветного JJRSX
extern int  Length2 = 40;  // глубина JurX сглаживания индикатора
// глубина JJMA сглаживания полученного индикатора
extern int  Smooth2 = 12;
// параметр, изменяющийся в пределах -100 ... +100, 
// влияет на качество переходныx процессов сглаживания
extern int  Phase2 = 100;
// Выбор цен, по которым производится расчёт индикатора 
extern int Input_Price_Customs2 = 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.)*/
//---- Стиль исполнения горизонтальных уровней индикаторов
extern int    Levels_Style = 3;         // Стиль линий уровней
extern int    Levels_Width = 0;         // Толщина линий уровней
extern color  Levels_Color = SlateGray; // цвет линий уровней
//---- Введение функции COUNT_begin() для вычисления номера бара, 
// начиная с которого будет отрисовываться индикатор и 
// расчитываться Bollinger Bands 
int COUNT_begin(){int count_begin=2*Length2+30;return(count_begin);}
//---- введение функции digits() для установки формата точности 
//(количество знаков после десятичной точки) для визуализации значений 
//индикатора 
int digits(){return(2);}
//---- установка значений индикатора, которые не будут видимы на графике 
int EmptyValue=0.0;
//---- Определение названия индикатора
string Label = "JJRSX";
 
//---- Включение в текст индикатора его основного текста
#include <3c_BB_Osc2.mqh> 
//---- введение функции INDICATOR1
//---- обращение к исходному индикатору для получения иcходных значений
double INDICATOR1(int INDICATOR1.bar)
 {
  return(iCustom( NULL, 0, "JJRSX", Length1, Smooth1, Phase1, 
         Input_Price_Customs1, 0, INDICATOR1.bar) );
 }
//---- введение функции INDICATOR2
//---- обращение к исходному индикатору для получения иcходных значений
double INDICATOR2(int INDICATOR2.bar)
 {
  return(iCustom( NULL, 0, "JJRSX", Length2, Smooth2, Phase2, 
         Input_Price_Customs2, 0, INDICATOR2.bar) );
 }
//---- --------------------------------------------------------------+

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



Трехцветные скользящие средние


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

/*
Для  работы  индикатора  следует  положить файлы 
JJMASeries.mqh  
PriceSeries.mqh 
3Color.mqh
в папку (директорию): MetaTrader\experts\include\
J2JMA.mq4 
в папку (директорию): MetaTrader\experts\indicators\
*/
//+------------------------------------------------------------------+  
//|                                                     3c_J2JMA.mq4 | 
//|                           Copyright c 2006,     Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+  
#property copyright "Copyright c 2006, Nikolay Kositsin"
#property link "farria@mail.redcom.ru" 
//---- отрисовка индикатора в главном окне
#property indicator_chart_window 
//---- количество индикаторных буферов
#property indicator_buffers 6
//---- цвета индикатора
#property indicator_color1 Blue
#property indicator_color2 Blue
#property indicator_color3 Red
#property indicator_color4 Red 
#property indicator_color5 Gray
#property indicator_color6 Gray
//---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА
extern int Length1 = 5;   // глубина  первого сглаживания 
extern int Length2 = 5;   // глубина  второго сглаживания 
// параметр первого сглаживания, изменяющийся в пределах -100 ... +100,
//влияет на качество переходного процесса; 
extern int Phase1  = 100;
// параметр второго сглаживания, изменяющийся в пределах -100 ... +100, 
//влияет на качество переходного процесса; 
extern int Phase2  = 100;
/* Выбор цен, по которым производится расчёт индикатора 
(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.) */
extern int Input_Price_Customs = 0;
//---- введение функции digits() для установки формата точности 
// (количество знаков после десятичной точки) для визуализации значений
// индикатора 
int digits(){return(Digits);}
//---- Введение функции COUNT_begin() для вычисления номера бара, 
//начиная с которого будет отрисовываться индикатор
int COUNT_begin(){return(60);}
//---- установка значений индикатора, которые не будут видимы на графике 
int  EmptyValue=0;
//---- лейба для индикатора
string Label="J2JMA";                 
//---- включение в текст индикатора его основного текста
#include <3Color.mqh>
//---- введение функции INDICATOR
//---- обращение к исходному индикатору для получения иcходных значений
double INDICATOR(int INDICATOR.bar)
 {
  return(iCustom(NULL,0,"J2JMA",Length1,Length2,Phase1,Phase2,0,
         Input_Price_Customs,0,INDICATOR.bar) );
 }
//---- --------------------------------------------------------------+

Только следует учесть тот факт, что для мувингов для установки формата точности в функции

int digits()
  {
    return(Digits);
  }

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

#include <3Color.mqh>

букву "J" и получим

#include <3ColorJ.mqh>



Шаблоны индикаторов, построенные по данным крупных таймфреймов


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

//----+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ 
//Version  July 1, 2006                                              |
//Editing   Nikolay Kositsin  15.06.2006  farria@mail.redcom.ru      |
//----+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ 
/*
Построение мувинга на текущем таймфрейме по значениям другого, более 
крупного таймфрейма. Внимание!!! Значения индикатора пересчитываются 
не  на  последнем баре, а на  количестве баров, эквивалентном  одной 
свече крупного таймфрейма!
 
Для  работы  индикатора  следует  положить файлы 
JJMASeries.mqh  
PriceSeries.mqh 
HTF.mqh
в папку (директорию): MetaTrader\experts\include\
J2JMA.mq4
Heiken Ashi#.mq4
в папку (директорию): MetaTrader\indicators\
*/
//+------------------------------------------------------------------+ 
//|                                                    J2JMA_htf.mq4 |
//|                            Copyright c 2005, GS  Conversion only |
//|                    http://www.gustis.narod.ru/;     gsb51@mail.ru |
//+------------------------------------------------------------------+ 
#property copyright "  Copyright c 2005, GS  Conversion only"
#property link      " http://www.gustis.narod.ru/;     gsb51@mail.ru"
//---- отрисовка индикатора в главном окне
#property indicator_chart_window 
//---- количество индикаторных буферов
#property indicator_buffers  4
//---- цвета индикатора
#property indicator_color1 BlueViolet
#property indicator_color2 Lime
#property indicator_color3 Red
#property indicator_color4 Gray
//---- толщина индикаторной линии
#property indicator_width1 3
#property indicator_width2 1
#property indicator_width3 1
#property indicator_width4 3
//---- стиль индикаторной линии
#property indicator_style1 0
//---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА
//Параметры пользовательского индикатора iCustom
extern int Length1 = 5;   // глубина  первого сглаживания 
extern int Length2 = 5;   // глубина  второго сглаживания 
// параметр первого сглаживания, изменяющийся в пределах -100 ... +100, 
//влияет на качество переходного процесса; 
extern int Phase1  = 100;
// параметр второго сглаживания, изменяющийся в пределах -100 ... +100, 
//влияет на качество переходного процесса; 
extern int Phase2  = 100;
//Выбор цен, по которым производится расчёт индикатора 
extern int Input_Price_Customs = 0;
/*
//---- ВХОДНЫЕ ПАРАМЕТРЫ HTF +--------------------------------------------+
extern int  TFrame_Period = 240; // Старший период в минутах
// сглажиание полученного мувинга. Наиболее оптимальное значение 
// равно отношению периодов старшего таймфрейма к периоду графика
extern int         Smooth = 48;
extern bool Trend_Visible = true;// визуализация индикации тренда
// минимальная скорость мувинга, принимаемая за тренд
extern int  Trend_Minimum = 5;
extern int         Shift  = 0;   // cдвиг индикатора вдоль оси времени 
*/
//---- введение функции digits() для установки формата точности 
// (количество знаков после десятичной точки) для визуализации значений 
// индикатора 
int digits(){return(Digits);}
//---- установка значений индикатора, которые не будут видимы на графике 
int EmptyValue=0;
string Label="J2JMA";                 
//---- включение в текст индикатора его основного текста
#include <HTF.mqh>
//---- введение функции INDICATOR
//---- обращение к исходному индикатору для получения иcходных значений
double INDICATOR(int INDICATOR.bar)
 {
  return(iCustom(NULL,TFrame_Period,"J2JMA",Length1,Length2,Phase1,Phase2,
         0,Input_Price_Customs,0,INDICATOR.bar) );
 }
//---- -----------------------------------------------------------+

Для нормальной работы мувинга следует открыть оба графика! Следует учесть, что исторические данные на обоих графиках должны быть все до последнего бара от одного брокера!

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


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

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

/*
//----+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ 
//Version  July 1, 2006                                              |
Editing   Nikolay Kositsin  15.06.2006  farria@mail.redcom.ru        |
//----+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ 
Построение мувинга на текущем таймфрейме по значениям другого, более 
крупного таймфрейма. Внимание!!! Значения индикатора пересчитываются 
не  на  последнем баре, а на  количестве баров, эквивалентном  одной 
свече крупного таймфрейма!
 
Для  работы  индикатора  следует  положить файлы 
JJMASeries.mqh  
PriceSeries.mqh 
HTF_Channal.mqh
в папку (директорию): MetaTrader\experts\include\
J2JMA.mq4
Heiken Ashi#.mq4
в папку (директорию): MetaTrader\indicators\
*/
//+------------------------------------------------------------------+
//|                                            J2JMA channel_htf.mq4 |
//|                            Copyright c 2005, GS  Conversion only |
//|                    http://www.gustis.narod.ru/;     gsb51@mail.ru |
//+------------------------------------------------------------------+
#property copyright "  Copyright c 2005, GS  Conversion only"
#property link      " http://www.gustis.narod.ru/;     gsb51@mail.ru"
//---- отрисовка индикатора в главном окне
#property indicator_chart_window 
//---- количество индикаторных буфферов
#property indicator_buffers  6
//---- цвета индикатора
#property indicator_color1 BlueViolet
#property indicator_color2 Gray
#property indicator_color3 Gray
#property indicator_color4 Lime
#property indicator_color5 Red
#property indicator_color6 Gray
//---- толщина индикаторной линии
#property indicator_width1 3
#property indicator_width2 0
#property indicator_width3 0
#property indicator_width4 1
#property indicator_width5 1
#property indicator_width6 1
//---- стиль индикаторной линии
#property indicator_style1 0
#property indicator_style2 4
#property indicator_style3 4
//---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА
//Параметры пользовательского индикатора iCustom
extern int Length1 = 5;   // глубина  первого сглаживания 
extern int Length2 = 5;   // глубина  второго сглаживания 
// параметр первого сглаживания, изменяющийся в пределах -100 ... +100, 
//влияет на качество переходного процесса; 
extern int Phase1  = 100;
// параметр второго сглаживания, изменяющийся в пределах -100 ... +100, 
//влияет на качество переходного процесса; 
extern int Phase2  = 100;
//Выбор цен, по которым производится расчёт индикатора 
extern int Input_Price_Customs = 0;
/*
//---- ВХОДНЫЕ ПАРАМЕТРЫ HTF +--------------------------------------------+
extern int  TFrame_Period = 240; // Старший период в минутах
extern int         Smooth = 48;  // сглажиание полученного мувинга
extern bool Trend_Visible = true;// визуализация индикации тренда
// минимальная скорость мувинга, принимаемая за тренд
extern int  Trend_Minimum = 5;
extern int         Shift  = 0;   // cдвиг индикатора вдоль оси времени 
*/
//---- введение функции digits() для установки формата точности 
// (количество знаков после десятичной точки) для визуализации значений 
// индикатора 
int digits(){return(Digits);}
//---- установка значений индикатора, которые не будут видимы на графике 
int EmptyValue=0;
string Label="J2JMA";
//---- включение в текст индикатора его основного текста
#include <HTF_channel.mqh>
//---- введение функции INDICATOR
//---- обращение к исходному индикатору для получения иходных значений
double INDICATOR(int INDICATOR.bar)
 {
  return(iCustom(NULL,TFrame_Period,"J2JMA",Length1,Length2,Phase1,Phase2,
         0,Input_Price_Customs,0,INDICATOR.bar) );
 }
//-------------------------------------------------------------------+


Заключение

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

В архиве NK_library.zip находится более ста индикаторов, написанных с применением различных алгоритмов сглаживания. Этих индикаторов более чем достаточно, чтобы научиться применять рассмотренные в этой статье примеры для написания других аналогичных индикаторов. Все индикаторы из архива с данными версиями функций сглаживания поддерживают экспертов и работают с ними без ошибок. Индикаторы из архива следует положить в папку клиентского терминала Метатрейдер 4: \MetaTrader\EXPERTS\indicators. Сами функции сглаживания и завёрнутые фрагменты программного кода находятся в папке INCLUDE. Всё содержимое этой папки следует поместить в папку клиентского терминала Метатрейдер: \MetaTrader\EXPERTS\INCLUDE.