5
Авг
2014

Как написать индикатор для терминала MetaTrader 4




Сегодня хотелось бы рассказать о том, как самостоятельно писать индикаторы на MQL4 для терминала MetaTrader 4.

Индикатор – штука полезная :)

Согласитесь, довольно сложно отыскать “на глаз” точку входа – сигнал для открытия позиции. В процессе изучения форекс в наших светлых головах возникают кое-какие наработки, основанные на техническом анализе. Порой хитросплетение условий для входа, например, даже основанных на базовых индикаторах, весьма затруднительно для восприятия и последующего анализа. Было бы замечательно, если бы некая программа, работающая по нашему алгоритму, отмечала на графике финансового инструмента точку входа (рисовала стрелочки, звездочки разного цвета, раскрашивала бары и т.п.) в покупки/продажи, а мы уже самостоятельно принимали бы решение об открытии позиции.

Как написать индикатор для терминала MetaTrader 4

Все-таки благо, что терминал MetaTrader 4 позволяет писать несколько видов исполняемых программ. Таких, например, как советники, скрипты и, наконец, пользовательские индикаторы (программа для графического отображения в терминале MT4 рассчитанных зависимостей).

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

Обращаю внимание, что размер массива буфера предопределяется числом баров для соответствующего графика финансового инструмента с учетом выбранного таймфрейма. В MQL4 есть такая специальная предопределенная переменная Bars – количество баров на текущем графике. Графики цены финансовых инструментов представлены в терминале в виде ценовой таймсерии, состоящей из ценовых баров в количестве Bars “штук”. Каждый бар графика характеризуется рядом значений, которые хранятся в одноименных предопределенных массивах-таймсериях (для каждого таймфрейма свой массив):

  • Time – время открытия каждого бара текущего графика;
  • Open – цена открытия каждого бара текущего графика;
  • Close – цена закрытия каждого бара текущего графика;
  • High – максимальная цена каждого бара текущего графика;
  • Low – минимальная цена каждого бара текущего графика;
  • Volume – тиковый объем каждого бара текущего графика.

Предлагаю рассмотреть пример, когда точка входа на графике финансового инструмента терминала МТ4 будем обозначаться индикатором в виде подсветки тела свечи характерным цветом: красное тело – вход в продажи, синее тело – вход в покупки. Разумеется, цвета “причинных” тел свечей, впрочем, как и параметры написанного нами индикатора, можно настраивать.

Как написать индикатор для терминала MetaTrader 4

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

  • Простая линия;
  • Отрезки между непустыми значениями линии;
  • Гистограмма;
  • Стрелки (символы);
  • Отрезки между непустыми значениями чётной и нечётной линий (зигзаг);
  • Отсутствие какого-либо рисования.

Для реализации задуманного, следует использовать формат вывода данных буферов в виде гистограммы (предопределенная константа для данного индикаторного стиля DRAW_HISTOGRAM). Только так, как мне видится, в простейшем случае мы можем подкрашивать требуемые свечки с помощью стандартных средств, предоставляемых языком MQL4 для пользовательских индикаторов. Конечно, путем программирования графических объектов посредством MQL4 можно создавать более гибкие решения. Но в сегодняшнем примере нам этого совсем не требуется, поскольку поставленную задачу можно решить значительно проще, не вдаваясь в подробности программирования графических объектов средствами MQL4.

Итак, обратимся к формату вывода гистограммы. Технические возможности, заложенные в MQL4, позволяют отображать одну гистограмму путем передачи терминалу пары буферов с данными. Причем, вертикальная линия гистограммы формируется между значениями с одноименными индексами буферов. Т.е., если бы мы имели два буфера с данными: Буф1 и Буф2, то для построения i-того элемента гистограммы для i-того бара ценового графика мы бы брали два значения (а эти значения для индикатора – цена на графике финансового инструмента): Буф1[i] и Буф2[i], и рисовали бы вертикальную линию по полученным точкам. Чтобы окрашивать именно тело свечи, наши буфера должны содержать информацию о ценах открытия и закрытия финансового инструмента. Т.е. буфер Буф1 должен содержать цены открытия Open (см. перечень предопределённых имён массивов-таймсерий языка MQL4), а буфер Буф2 цены закрытия Close соответствующего инструмента, к графику которого прикреплен индикатор в терминале. Если цвет тела свечи изменять не требуется (нет сигнала на вход), то соответствующие значения данных буферов приравняем нулю. Это значение укажет терминалу, что ничего отображать не надо.

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

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

//Индикатор выводит графическую информацию в основное окно
#property indicator_chart_window
//Количество используемых пользовательских индикаторных буферов 4 
//(2 буфера - подсветка покупок, 2 буфера - подсветка продаж)
#property indicator_buffers 4             
//Определим цвета индикаторных линий (тел свечей) для каждого сигнала
//Первая пара для сигнала покупок
#property indicator_color1 DeepSkyBlue    // Цвет тела свечи для покупок
#property indicator_color2 DeepSkyBlue    // То же самое значение
//Вторая пара для сигнала продаж
#property indicator_color3 OrangeRed      // Цвет тела свечи для продаж
#property indicator_color4 OrangeRed      // То же самое значение
//Определим толщину индикаторных линий
//(толщину подбираем такой, чтобы на всех масштабах тело свечи было полностью раскрашено)
#property indicator_width1  12
#property indicator_width2  12
#property indicator_width3  12
#property indicator_width4  12

Объявим массивы данных, которые будут привязаны к индикаторным буферам. В эти массивы мы будем “укладывать” значения для формирования индикаторных линий.

//Объявляем пользовательские массивы данных,
//которые будут привязаны к индикаторным буферам 
double Buy1[], Buy2[], Sell1[], Sell2[];

В инициализирующей функции программы индикатора init() (запускается единожды при инициализации индикатора на соответствующем ценовом графике) свяжем массивы данных с предопределенными буферами пользовательского индикатора, определим стили отображения индикаторных линий, установим значение пустой величины, при котором не происходит отображение индикаторной линии (мы же не все тела свечи будем помечать, а только “сигнальные” !), зададим строку с названием индикатора для всплывающей подсказки и описание каждой индикаторной линии.

//Функция инициализации индикатора (запускается один раз:
//при установке индикатора на график или при переключении таймфрейма)
int init()
{
   //Связываем наши массивы (в них мы будем "укладывать" рассчитанные зависимости) с индикаторными буферами МТ4
   SetIndexBuffer (0, Buy1);
   SetIndexBuffer (1, Buy2);
   SetIndexBuffer (2, Sell1);
   SetIndexBuffer (3, Sell2);
   //Устанавливаем значение пустой величины для линий индикатора 
   //(эти значения не рисуются и не показываются в основном окне)
   SetIndexEmptyValue (0, 0.0);
   SetIndexEmptyValue (1, 0.0);
   SetIndexEmptyValue (2, 0.0);
   SetIndexEmptyValue (3, 0.0);
   //Определяем стиль отображения индикаторных линий - гистограмма
   SetIndexStyle (0, DRAW_HISTOGRAM);
   SetIndexStyle (1, DRAW_HISTOGRAM);
   SetIndexStyle (2, DRAW_HISTOGRAM);
   SetIndexStyle (3, DRAW_HISTOGRAM);
   //Определяем разрядность значений индикаторных линий - приравниваем разрядности фин. инструмента
   IndicatorDigits (Digits);
   //Строка с кратким названием индикатора, выводимая в сплывающей подсказке при наведении указателя мыши на индикаторную линию
   IndicatorShortName ("Мой первый индикатор");
   //Устанавливаем текст описания линий индикатора для отображения информации в всплывающей подсказке.
   SetIndexLabel(0, "Покупаем");
   SetIndexLabel(1, "Покупаем");
   SetIndexLabel(2, "Продаем");
   SetIndexLabel(3, "Продаем");
   return(0);
}

Наконец, переходим к основной функции программы индикатора start() (запускается с каждым новым тиком – при изменении цены). В этой функции мы должны формировать на каждом новом тике массивы данных для их последующей трансляции в пользовательских индикаторных буферах (массивы же с ними мы связали в инициализирующей функции) и отображения индикаторных линий терминалом MT4 в определенном нами виде.

//Основная функция индикатора (запускается с каждым новым тиком - новой ценой)
int start ()
{
   //Определим количество не измененных баров с последнего вызова индикатора (по прошлому тику)
   int counted_bars = IndicatorCounted();
   int limit, s1;
   //Пересчитаем последний посчитанный бар
   if ( counted_bars>0) counted_bars-- ;
   //Определяем число баров, которые следует пересчитать
   limit=Bars-counted_bars;
   //Чтобы индикатор "не перерисовывался" расчет ведем с последнего закрытого бара - он имеет индекс равный 1
   //(нулевой бар является текущим, т.е. он изменяется с каждым новым тиком до тех пор пока не будет закрыт)
   for ( int i = 2; i < limit; i++ )  {
         //Заполняем массивы данных для текущего бара пустыми значениями (у нас это 0)
         Sell1[i-1] = 0.0;
         Sell2[i-1] = 0.0;
         Buy1[i-1] = 0.0;
         Buy2[i-1] = 0.0;
         //Проверяем сигнал на вход для текущего бара
         s1 = signal (i);
         if( s1 != FLET )
         {
             //Есть ли сигнал на продажу?
             if ( s1 == SELL )  {
                //В первый массив записываем цену открытия бара
                Sell1[i-1] = Open[i-1];
                //Во второй массив записываем цену закрытия бара
                Sell2[i-1] = Close[i-1];
                //Эти координаты как раз и определят тело свечи, которое следует закрасить, чтобы показать вход в продажи
             }
             //Есть ли сигнал на покупку?
             if ( s1 == BUY )  {
                //В первый массив записываем цену открытия бара
                Buy1[i-1] = Open[i-1];
                //Во второй массив записываем цену закрытия бара
                Buy2[i-1] = Close[i-1];
                //Эти координаты как раз и определят тело свечи, которое следует закрасить, чтобы показать вход в покупки
             }     
          }    
   }
   return(0);
}

Вот мы и написали некий универсальный каркас программы индикатора для терминала MetaTrader 4 с возможностью выделять тела сигнальных свечей. Как вы можете видеть, нам осталось только определить некую функцию signal(), которая бы возвращала программе индикатора три параметра:

  • нет сигнала для данного ценового бара;
  • есть сигнал покупок для данного ценового бара;
  • есть сигнал продаж для данного ценового бара.

Чтобы код программы индикатора был удобочитаемым, в ее информационную часть введем определение трех констант (BUY, SELL, FLET), одну из которых функция signal() будет возвращать для каждого ценового бара:

//Определяем константы (для удобства восприятия кода), которые будем использовать
#define BUY 1
#define SELL 2
#define FLET -1

Теперь осталось определиться, какой именно алгоритм мы будем использовать для определения наличия сигнала для входа или его отсутствие. Каждый из вас может, разумеется, предложить свой вариант. Я же в этом примере индикатора буду использовать стохастик, ADX и некое подобие простейшего фильтра флета. В общем все то, что первым пришло в голову.

Итак, будем считать, что сигналом в покупки для расчетного бара является пересечение стохастика в нижней зоне, определяемой параметром stohastic_min. При этом индикатор ADX имеет значение больше параметра adx_min, а фильтр флета показывает наличие движения. В этом случае наша функция signal() будет возвращать значение BUY. Будем считать, что сигналом в продажи для расчетного бара является пересечение стохастика в верхней зоне, определяемой параметром stohastic_max. При этом индикатор ADX имеет значение больше параметра adx_min, а фильтр флета показывает наличие движения. В этом случае наша функция signal() будет возвращать значение SELL. Во всех остальных случаях функция signal() будет возвращать значение FLET.

Таким образом, для моего примера функция signal() принимает вид:

//Функция определяет для бара с индексом i наличие сигнала в покупки/продажи либо его отсутствие
int signal (int i)
{
    //вычисляем значения стандартных индикаторов (стохастик и ADX) для баров с индексами i и i-1
    double st1_signal = iStochastic (Symbol(),Period(), 5, 3, 3, 0, 0, MODE_SIGNAL, i);
    double st1_value =  iStochastic (Symbol(),Period(), 5, 3, 3, 0, 0, MODE_MAIN, i);
    double st2_signal = iStochastic (Symbol(),Period(), 5, 3, 3, 0, 0, MODE_SIGNAL, i-1);
    double st2_value =  iStochastic (Symbol(),Period(), 5, 3, 3, 0, 0, MODE_MAIN, i-1);
    double adx1 = iADX (Symbol(), Period(), 14, 0, MODE_MAIN, i);
    double adx2 = iADX (Symbol(), Period(), 14, 0, MODE_MAIN, i-1);
    //покупаем, если: стохастик показал пересечение в нижней зоне, определяемой параметром stohastic_min; 
    //индикатор ADX имеет значение больше параметра adx_min; фильт флета показывает наличие движения
    if ( (adx1>adx_min || adx2>adx_min) && st1_value<=stohastic_min && st1_value<st1_signal && st2_value>st2_signal && !FletFilter(i-1) ) return ( BUY );
    //продаем, если: стохастик показал пересечение в верхней зоне, определяемой параметром stohastic_mах; 
    //индикатор ADX имеет значение больше параметра adx_min; фильт флета показывает наличие движения
    if ( (adx1>adx_min || adx2>adx_min) && st1_value>=stohastic_max && st1_value>st1_signal && st2_value<st2_signal && !FletFilter(i-1) ) return ( SELL );
    //нет сигнала - функция возвращает константу FLET
    return ( FLET );
}

И дело за малым. Пробуем писать некое подобие фильтра флета – функцию FletFilter(). Считаем, что в текушей рыночной ситуации для заданного таймфрейма имеет место флет, если размер свечи (расстояние между максимальной и минимальной ценой бара) не превышает на fletpercent процентов среднее значение размера свечи для заданного диапазона некой глубины filterlenght. Если какой-либо размер свечи выходит за допустимые границы диапазона, то считаем, что в текущей ситуации (для бара с индексом i) имеет место движение, отличное от флета.

//Наша функция, которая выступает в роли некого фильтра флета
bool FletFilter (int i)
{
   double sum = 0;
   //вычисляем среднее значение "амплитуды" свечи для баров с индексами от i-1
   //на глубину filterlenght
   for ( int j = i-1; j < i-1+filterlenght; j++ )  {
         sum+=MathAbs(High[j]-Low[j]);
   }
   sum = sum/filterlenght;
   //"пройдемся" от текущего индекса бара на глубину filterlenght баров
   for ( j = i-1; j < i-1+filterlenght; j++ )  {
      //если какая-либо из "амплитуд" свечей для набора превышает среднее значение на fletpercent процентов, 
      //то считаем, что на данном таймфрейме в текущее время имеет место движение, а не флет.   
      if ( 100*(sum-MathAbs(High[j]-Low[j]))/sum>fletpercent ) {
         return (false);
      }   
   }
   //в текущей ситуации флет
   return (true);
}

Осталось собрать все в кучу, и мы получим программу нашего первого индикатора для терминала MetaTrader4.

//+------------------------------------------------------------------+
//|                                                 myfirstinduk.mq4 |
//|                                         http://moneyinnetwork.ru |
//|                                         http://moneyinnetwork.ru |
//+------------------------------------------------------------------+
#property copyright "http://moneyinnetwork.ru"
#property link      "http://moneyinnetwork.ru"
 
//Индикатор выводит графическую информацию в основное окно
#property indicator_chart_window
//Количество используемых пользовательских буферов данных 4 
//(2 - подсветка покупок, 2 - подсветка продаж)
#property indicator_buffers 4             
//Определим цвета индикаторных линий (тел свечей) для каждого сигнала
//Первая пара для сигнала покупок
#property indicator_color1 DeepSkyBlue    // Цвет тела свечи для покупок
#property indicator_color2 DeepSkyBlue    // То же самое значение
//Вторая пара для сигнала продаж
#property indicator_color3 OrangeRed      // Цвет тела свечи для продаж
#property indicator_color4 OrangeRed      // То же самое значение
//Определим толщину индикаторных линий
#property indicator_width1  12
#property indicator_width2  12
#property indicator_width3  12
#property indicator_width4  12
 
//Объявляем пользовательские массивы данных,
//которые будут привязаны к индикаторным буферам 
double Buy1[], Buy2[], Sell1[], Sell2[];
 
//Определяем константы (для удобства восприятия кода), которые будем использовать
#define BUY 1
#define SELL 2
#define FLET -1
 
//Параметры нашего индикатора
//уровень пересечения стохастика в верхней зоне - для продаж
extern int stohastic_max = 80;
//уровень пересечения стохастика в нижней зоне - для покупок
extern int stohastic_min = 20;
//уровень ADX
extern int adx_min = 30;
//"глубина" фильтра флета - число баров вглубь от текущего бара
extern int filterlenght = 6;
//допустимое отклонение размера каждой свечи набора от среднего значения для данного набора, в %
extern int fletpercent = 10;
 
//Функция инициализации индикатора (запускается один раз:
//при установке индикатора на график или при переключении таймфрейма)
int init()
{
   //Связываем наши массивы (в них мы будем "укладывать" рассчитанные зависимости) с индикаторными буферами МТ4
   SetIndexBuffer (0, Buy1);
   SetIndexBuffer (1, Buy2);
   SetIndexBuffer (2, Sell1);
   SetIndexBuffer (3, Sell2);
   //Устанавливаем значение пустой величины для линий индикатора 
   //(эти значения не рисуются и не показываются в основном окне)
   SetIndexEmptyValue (0, 0.0);
   SetIndexEmptyValue (1, 0.0);
   SetIndexEmptyValue (2, 0.0);
   SetIndexEmptyValue (3, 0.0);
   //Определяем стиль отображения индикаторных линий - гистограмма
   SetIndexStyle (0, DRAW_HISTOGRAM);
   SetIndexStyle (1, DRAW_HISTOGRAM);
   SetIndexStyle (2, DRAW_HISTOGRAM);
   SetIndexStyle (3, DRAW_HISTOGRAM);
   //Определяем разрядность значений индикаторных линий - приравниваем разрядности фин. инструмента
   IndicatorDigits (Digits);
   //Строка с кратким названием индикатора, выводимая в сплывающей подсказке при наведении указателя мыши на индикаторную линию
   IndicatorShortName ("Мой первый индикатор");
   //Устанавливаем текст описания линий индикатора для отображения информации в всплывающей подсказке.
   SetIndexLabel(0, "Покупаем");
   SetIndexLabel(1, "Покупаем");
   SetIndexLabel(2, "Продаем");
   SetIndexLabel(3, "Продаем");
   return(0);
}
 
//Функция деинициализации индикатора (запускается один раз)
int deinit ()
{ 
   return (0);
}
 
//Основная функция индикатора (запускается с каждым новым тиком - новой ценой)
int start ()
{
   //Определим количество не измененных баров с последнего вызова индикатора (по прошлому тику)
   int counted_bars = IndicatorCounted();
   int limit, s1;
   //Пересчитаем последний посчитанный бар
   if ( counted_bars>0) counted_bars-- ;
   //Определяем число баров, которые следует пересчитать
   limit=Bars-counted_bars;
   //Чтобы индикатор "не перерисовывался" расчет ведем с последнего закрытого бара - он имеет индекс равный 1
   //(нулевой бар является текущим, т.е. он изменяется с каждым новым тиком до тех пор пока не будет закрыт)
   for ( int i = 2; i < limit; i++ )  {
         //Заполняем массивы данных для текущего бара пустыми значениями (у нас это 0)
         Sell1[i-1] = 0.0;
         Sell2[i-1] = 0.0;
         Buy1[i-1] = 0.0;
         Buy2[i-1] = 0.0;       
         //Проверяем сигнал на вход для текущего бара
         s1 = signal (i);
         if( s1 != FLET )   {
             //Есть ли сигнал на продажу?
             if ( s1 == SELL )  {
                //В первый массив записываем цену открытия бара
                Sell1[i-1] = Open[i-1];
                //Во второй массив записываем цену закрытия бара
                Sell2[i-1] = Close[i-1];
                //Эти координаты как раз и определят тело свечи, которое следует закрасить, чтобы показать вход в продажи
             }
             //Есть ли сигнал на покупку?
             if ( s1 == BUY )  {
                //В первый массив записываем цену открытия бара
                Buy1[i-1] = Open[i-1];
                //Во второй массив записываем цену закрытия бара
                Buy2[i-1] = Close[i-1];
                //Эти координаты как раз и определят тело свечи, которое следует закрасить, чтобы показать вход в покупки
             }     
         }    
   }
   return(0);
}
 
//Функция определяет для бара с индексом i наличие сигнала в покупки/продажи либо его отсутствие
int signal (int i)
{
    //вычисляем значения стандартных индикаторов (стохастик и ADX) для баров с индексами i и i-1
    double st1_signal = iStochastic (Symbol(),Period(), 5, 3, 3, 0, 0, MODE_SIGNAL, i);
    double st1_value =  iStochastic (Symbol(),Period(), 5, 3, 3, 0, 0, MODE_MAIN, i);
    double st2_signal = iStochastic (Symbol(),Period(), 5, 3, 3, 0, 0, MODE_SIGNAL, i-1);
    double st2_value =  iStochastic (Symbol(),Period(), 5, 3, 3, 0, 0, MODE_MAIN, i-1);
    double adx1 = iADX (Symbol(), Period(), 14, 0, MODE_MAIN, i);
    double adx2 = iADX (Symbol(), Period(), 14, 0, MODE_MAIN, i-1);
    //покупаем, если: стохастик показал пересечение в нижней зоне, определяемой параметром stohastic_min; 
    //индикатор ADX имеет значение больше параметра adx_min; фильт флета показывает наличие движения
    if ( (adx1>adx_min || adx2>adx_min) && st1_value<=stohastic_min && st1_value<st1_signal && st2_value>st2_signal && !FletFilter(i-1) ) return ( BUY );
    //продаем, если: стохастик показал пересечение в верхней зоне, определяемой параметром stohastic_mах; 
    //индикатор ADX имеет значение больше параметра adx_min; фильт флета показывает наличие движения
    if ( (adx1>adx_min || adx2>adx_min) && st1_value>=stohastic_max && st1_value>st1_signal && st2_value<st2_signal && !FletFilter(i-1) ) return ( SELL );
    //нет сигнала - функция возвращает константу FLET
    return ( FLET );
}
 
//Наша функция, которая выступает в роли некого фильтра флета
bool FletFilter (int i)
{
   double sum = 0;
   //вычисляем среднее значение "амплитуды" свечи для баров с индексами от i-1
   //на глубину filterlenght
   for ( int j = i-1; j < i-1+filterlenght; j++ )  {
         sum+=MathAbs(High[j]-Low[j]);
   }
   sum = sum/filterlenght;
   //"пройдемся" от текущего индекса бара на глубину filterlenght баров
   for ( j = i-1; j < i-1+filterlenght; j++ )  {
      //если какая-либо из "амплитуд" свечей для набора превышает среднее значение на fletpercent процентов, 
      //то считаем, что на данном таймфрейме в текущее время имеет место движение, а не флет.   
      if ( 100*(sum-MathAbs(High[j]-Low[j]))/sum>fletpercent ) {
         return (false);
      }   
   }
   //в текущей ситуации флет
   return (true);
}

Наш первый индикатор для терминала MT4 имеет несколько параметров, определенных в информационной части программы:

//Параметры нашего индикатора
//уровень пересечения стохастика в верхней зоне - для продаж
extern int stohastic_max = 80;
//уровень пересечения стохастика в нижней зоне - для покупок
extern int stohastic_min = 20;
//уровень ADX
extern int adx_min = 30;
//"глубина" фильтра флета - число баров вглубь от текущего бара
extern int filterlenght = 6;
//допустимое отклонение размера каждой свечи набора от среднего значения для данного набора, в %
extern int fletpercent = 10;

Эти параметры мы можем настраивать как угодно при установке индикатора на график либо в процессе работы индикатора (нажимаем в терминале Ctrl+I и в списке индикаторов выбираем myfirstinduk):

Настройка параметров индикатора в MT4

Также можем менять и цвета сигнальных тел свечей. Для этого перейдите на вкладку “Цвета” в вышеуказанном окне и настройте их по своему вкусу (в зависимости от фона основного окна).

Скачать индикатор для терминала MetaTrader 4 можно по этой ссылке.

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

Скачать данный вид индикатора для терминала MetaTrader 4 можно по этой ссылке. Как мне кажется, для графического восприятия он значительно лучше:

Полностью закрашенная сигнальная свеча в индикаторе MT4

Если у кого-либо из читателей возникнут вопросы, то постараюсь на них ответить по мере наличия времени. Кстати, недавно для удобства общения я сделал форум, где можно обсудить многие вопросы с разбивкой по подразделам с узкой тематикой (например, тема обсуждения брокера GKFX или тема введение в программирование на MQL4 для MetaTrader), что раньше было не совсем удобно в масштабах Гостевой.

Материалы схожей тематики:
Поделитесь с другими:

Получать информацию о новых заметках:

Комментарии


  1. Немного изменил код индикатора (в том числе, теперь он написан на обновленном MQL4).
    Логика сигналов несколько изменилась. Добавлена скользящая средняя. Фильтр флета в коде отключен.
    СКАЧАТЬ

  2. дмитрий 5 0

    Здравствуйте ! могли вы мне помоч с написание индикатора, есть хорошая идея

  3. дмитрий 5 0

    нужно что бы индикатор сообщал о очередности свечей к примеру (вверх вниз вверх вниз) и сообщал об этом за полторы минуты до закрытия той по очереди свечи которую в настройках мы выставили сами!это возможно?

  4. дмитрий 5 0

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

  5. артем 4 0

    Можно ли сделать вот такой индикатор в mq4

    #property copyright "Copyright 2015"
    #property link "..."
    #property version "1.00"
    #property strict
    #property indicator_chart_window
    #property description "Индикатор диапазонов"
    #property description "относительно предыдущего дня"
    #property indicator_buffers 6 //сколько будет изображено линий
    #property indicator_color1 clrLimeGreen
    #property indicator_width1 2
    #property indicator_color2 clrGreen
    #property indicator_width2 2
    #property indicator_color3 clrRed
    #property indicator_width3 2
    #property indicator_color4 clrMaroon
    #property indicator_width4 2
    #property indicator_color5 clrDarkViolet
    #property indicator_width5 2
    #property indicator_color6 clrBlue
    #property indicator_width6 2
    //параметры - после слешей - название индикатора для пользователей
    input ENUM_TIMEFRAMES UpTime = PERIOD_D1;
    input double Range1Percent = 20;
    input double Range2Percent = 40;
    input double Range3Percent = 60;
    //буфферы
    double bufUp1[];
    double bufDown1[];
    double bufUp2[];
    double bufDown2[];
    double bufUp3[];
    double bufDown3[];
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    //--- indicator buffers mapping
    IndicatorShortName("dzRanges");
    IndicatorBuffers(6);
    //задаем привязку и стили
    SetIndexBuffer(0, bufUp1);
    SetIndexStyle(0, DRAW_LINE);
    SetIndexShift(0, 0);
    SetIndexDrawBegin(0, 0);
    SetIndexBuffer(1, bufDown1);
    SetIndexStyle(1, DRAW_LINE);
    SetIndexShift(1, 0);
    SetIndexDrawBegin(1, 0);
    SetIndexBuffer(2, bufUp2);
    SetIndexStyle(2, DRAW_LINE);
    SetIndexShift(2, 0);
    SetIndexDrawBegin(2, 0);
    SetIndexBuffer(3, bufDown2);
    SetIndexStyle(3, DRAW_LINE);
    SetIndexShift(3, 0);
    SetIndexDrawBegin(3, 0);
    SetIndexBuffer(4, bufUp3);
    SetIndexStyle(4, DRAW_LINE);
    SetIndexShift(4, 0);
    SetIndexDrawBegin(4, 0);
    SetIndexBuffer(5, bufDown3);
    SetIndexStyle(5, DRAW_LINE);
    SetIndexShift(5, 0);
    SetIndexDrawBegin(5, 0);
    //---
    return(INIT_SUCCEEDED);
    }
    //+------------------------------------------------------------------+
    //| Custom indicator iteration function |
    //+------------------------------------------------------------------+
    int OnCalculate(const int rates_total,const int prev_calculated,const datetime &time[],const double &open[],const double &high[],const double &low[],const double &close[],
    const long &tick_volume[],const long &volume[],const int &spread[])
    {
    //---
    int period = 1; //сюда заносим самый большой расчетный период
    if(rates_total < period)
    return(-1); //на графике нет достаточного количества баров
    int limit = rates_total - prev_calculated;
    //текущий бар всегда пересчитываем и предыдущий
    limit++;
    //при первом расчете может выйти за 0, поэтому
    while(limit < 0)
    limit++;
    //при первом расчете - отступаем слева, так как там не хватит свечей для расчета
    limit = MathMin(limit, rates_total - period);
    //сам расчет
    for(int i = limit; i >= 0; i--)
    {
    int shift = iBarShift(Symbol(), UpTime, Time);
    double h = iHigh(Symbol(), UpTime, shift + 1);
    double l = iLow(Symbol(), UpTime, shift + 1);
    double o = iOpen(Symbol(), UpTime, shift);
    bufUp1 = o + (h - l) * (1 + Range1Percent) / 100;
    bufUp2 = o + (h - l) * (1 + Range2Percent) / 100;
    bufUp3 = o + (h - l) * (1 + Range3Percent) / 100;
    bufDown1 = o - (h - l) * (1 + Range1Percent) / 100;
    bufDown2 = o - (h - l) * (1 + Range2Percent) / 100;
    bufDown3 = o - (h - l) * (1 + Range3Percent) / 100;
    }
    //--- return value of prev_calculated for next call
    return(rates_total);
    }
    • артем 07.07.2017 в 15:02:
      Можно ли сделать вот такой индикатор в mq4

      Артем, наверное, вот так:

      #property copyright "Перенос на mql4 moneyinnetwork.ru"
      #property link "http://moneyinnetwork.ru"
      #property version "1.00"
      #property strict
      #property indicator_chart_window
      #property description "Индикатор диапазонов"
      #property description "относительно предыдущего дня"
      #property description "Перенос на mql4 moneyinnetwork.ru"
      #property indicator_buffers 6
      #property indicator_color1 clrLimeGreen
      #property indicator_width1 2
      #property indicator_color2 clrGreen
      #property indicator_width2 2
      #property indicator_color3 clrRed
      #property indicator_width3 2
      #property indicator_color4 clrMaroon
      #property indicator_width4 2
      #property indicator_color5 clrDarkViolet
      #property indicator_width5 2
      #property indicator_color6 clrBlue
      #property indicator_width6 2
       
      input ENUM_TIMEFRAMES UpTime = PERIOD_D1;
      input double Range1Percent = 20;
      input double Range2Percent = 40;
      input double Range3Percent = 60;
       
      double bufUp1[];
      double bufDown1[];
      double bufUp2[];
      double bufDown2[];
      double bufUp3[];
      double bufDown3[];
       
      int OnInit()
      {
         IndicatorShortName("dzRanges");
         IndicatorBuffers(6);
         SetIndexBuffer(0, bufUp1);
         SetIndexStyle(0, DRAW_LINE);
         SetIndexShift(0, 0);
         SetIndexDrawBegin(0, 0);
         SetIndexBuffer(1, bufDown1);
         SetIndexStyle(1, DRAW_LINE);
         SetIndexShift(1, 0);
         SetIndexDrawBegin(1, 0);
         SetIndexBuffer(2, bufUp2);
         SetIndexStyle(2, DRAW_LINE);
         SetIndexShift(2, 0);
         SetIndexDrawBegin(2, 0);
         SetIndexBuffer(3, bufDown2);
         SetIndexStyle(3, DRAW_LINE);
         SetIndexShift(3, 0);
         SetIndexDrawBegin(3, 0);
         SetIndexBuffer(4, bufUp3);
         SetIndexStyle(4, DRAW_LINE);
         SetIndexShift(4, 0);
         SetIndexDrawBegin(4, 0);
         SetIndexBuffer(5, bufDown3);
         SetIndexStyle(5, DRAW_LINE);
         SetIndexShift(5, 0);
         SetIndexDrawBegin(5, 0);
         return(INIT_SUCCEEDED);
      }
       
      int OnCalculate(const int rates_total,const int prev_calculated,const datetime &time[],
                      const double &open[],const double &high[],const double &low[],const double &close[],
                      const long &tick_volume[],const long &volume[],const int &spread[])
      {
         int period = 1; //сюда заносим самый большой расчетный период
         if(rates_total < period)
         return(-1); //на графике нет достаточного количества баров
         int limit = rates_total - prev_calculated;
         //текущий бар всегда пересчитываем и предыдущий
         limit++;
         //при первом расчете может выйти за 0, поэтому
         while(limit < 0)
         limit++;
         //при первом расчете - отступаем слева, так как там не хватит свечей для расчета
         limit = MathMin(limit, rates_total - period);
         //сам расчет
         for(int i = limit; i >= 0; i--)
         {
            int shift = iBarShift(Symbol(), UpTime, time[i]);
            double h = iHigh(Symbol(), UpTime, shift + 1);
            double l = iLow(Symbol(), UpTime, shift + 1);
            double o = iOpen(Symbol(), UpTime, shift);
            bufUp1[i] = o + (h - l) * (1 + Range1Percent) / 100;
            bufUp2[i] = o + (h - l) * (1 + Range2Percent) / 100;
            bufUp3[i] = o + (h - l) * (1 + Range3Percent) / 100;
            bufDown1[i] = o - (h - l) * (1 + Range1Percent) / 100;
            bufDown2[i] = o - (h - l) * (1 + Range2Percent) / 100;
            bufDown3[i] = o - (h - l) * (1 + Range3Percent) / 100;
         }
         return(rates_total);
      }
  6. артем 4 0

    Подскажите а сложно ли переделать скрипт в индикатор Добавлено сообщение 09.07.2017, в 20:37https://yadi.sk/d/wg1YsGfJ3KtThS
    вот этот скрипт в индикатор по возможности

  7. fl1cker 2 0

    Доброго времени суток!

    Как изменить код чтобы он показывал значение именно размера свечи не учитывая размера теней.
    вот сам код, написанный когда-то самим админом.

    //+------------------------------------------------------------------+ 
    //|                               candle_size_for_Natashika_mmgp.mq4 | 
    //|                                 Vlad Sergeev aka moneyinnetwork  | 
    //+------------------------------------------------------------------+ 
    #property copyright "http://moneyinnetwork.ru"
    #property link "http://moneyinnetwork.ru" 
    #property version   "1.00" 
    #property strict 
    #property indicator_chart_window 
     
    input int      TextSize = 8; //размер шрифта 
    input color    TextColor = clrYellow; //цвет текста 
    input int      TextAngle = 90; //угол поворота текста 
    input int      MaxBar = 100;  //количество баров, начиная с 0, для которых вычисляется размер свечей 
     
    int OnInit() 
    { 
       return(INIT_SUCCEEDED); 
    } 
     
    int OnCalculate(const int rates_total, 
                    const int prev_calculated, 
                    const datetime &time[], 
                    const double &open[], 
                    const double &high[], 
                    const double &low[], 
                    const double &close[], 
                    const long &tick_volume[], 
                    const long &volume[], 
                    const int &spread[]) 
    { 
       int i; 
       for ( i = 0; i < MaxBar; i++ )   { 
          if ( ObjectFind ("candlesize"+ IntegerToString(i)) >=0 )   { 
                 ObjectDelete("candlesize"+ IntegerToString(i)); 
          } 
          ObjectCreate ("candlesize"+ IntegerToString(i),  
                        OBJ_TEXT,  
                        0,  
                        time[i],  
                        high[i]+StepPer()*Point); 
          ObjectSet (  "candlesize"+IntegerToString(i),  
                        OBJPROP_ANGLE,  
                        TextAngle 
                     ); 
          ObjectSetText ( "candlesize"+IntegerToString(i),  
                          DoubleToStr(NormalizeDouble((high[i]-low[i]+Point)/Point, 0), 0),  
                          TextSize,  
                          NULL,  
                          TextColor 
                         ); 
       } 
       return(rates_total); 
    } 
     
    int StepPer () 
    { 
         int i = 0; 
         switch (Period()) 
         { 
              case PERIOD_M1: 
              i = 5; 
              break; 
              case PERIOD_M5: 
              i = 15; 
              break; 
              case PERIOD_M15: 
              i = 25; 
              break; 
              case PERIOD_M30: 
              i = 40; 
              break; 
              case PERIOD_H1: 
              i = 60; 
              break; 
              case PERIOD_H4: 
              i = 90; 
              break; 
              case PERIOD_D1: 
              i = 220; 
              break; 
              case PERIOD_W1: 
              i = 500; 
              break; 
              case PERIOD_MN1: 
              i = 2000; 
              break; 
              default:  
              break; 
         } 
         return (i); 
    }
    • Здравствуйте. Необходимо изменить код так, чтобы был расчет размера тела свечи, т.е.:

      ObjectSetText ( "candlesize"+IntegerToString(i),  
                            DoubleToStr(NormalizeDouble((high[i]-low[i]+Point)/Point, 0), 0),  
                            TextSize,  
                            NULL,  
                            TextColor 
                           );

      заменить на:

      ObjectSetText ( "candlesize"+IntegerToString(i),  
                            DoubleToStr((NormalizeDouble(close[i]-open[i])+Point())/Point(), 0), 0),  
                            TextSize,  
                            NULL,  
                            TextColor 
                           );

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

      //+------------------------------------------------------------------+
      //|                                               last_body_size.mq4 |
      //|                                                moneyinnetwork.ru |
      //|                                         http://moneyinnetwork.ru |
      //+------------------------------------------------------------------+
      #property copyright "moneyinnetwork.ru"
      #property link      "http://moneyinnetwork.ru"
      #property version   "1.00"
      #property description "Показывает размер тела для заданного количества свечей"
      #property description "Автоматически рассчитывает масштаб для вывода надписей"
      #property description "http://moneyinnetwork.ru"
      #property strict
      #property indicator_chart_window
       
      input int      TextSize = 8; //размер шрифта 
      input color    TextColor = clrYellow; //цвет текста 
      input int      TextAngle = 90; //угол поворота текста 
      input int      MaxBar = 100;  //количество баров, начиная с текущего, для которых вычисляется размер свечей 
      input int      Exp = 1;      //точность - количество знаков после запятой 
       
      int OnInit() 
      { 
         ObjectsDeleteAll(ChartID(),"candlesize_"+Symbol()+"_");
         return(INIT_SUCCEEDED); 
      }
       
      void OnDeinit(const int reason)
      {
         ObjectsDeleteAll(ChartID(),"candlesize_"+Symbol()+"_");
      } 
       
      int OnCalculate(const int rates_total, 
                      const int prev_calculated, 
                      const datetime &time[], 
                      const double &open[], 
                      const double &high[], 
                      const double &low[], 
                      const double &close[], 
                      const long &tick_volume[], 
                      const long &volume[], 
                      const int &spread[]) 
      { 
         int i; 
         double candle_len;
         long chart_ID = ChartID(), height_in_pixels;
         double max_price, min_price;
         ChartGetDouble(chart_ID,CHART_PRICE_MAX,0,max_price);
         ChartGetDouble(chart_ID,CHART_PRICE_MIN,0,min_price);
         double height_in_price = max_price-min_price;
         ChartGetInteger(chart_ID,CHART_HEIGHT_IN_PIXELS,0,height_in_pixels);
         double mast = height_in_price/(double)height_in_pixels;
         for ( i = 0; i < MaxBar; i++ )   { 
            candle_len = MathAbs(close[i]-open[i]);
            if ( NormalizeDouble(close[i],Digits)==NormalizeDouble(open[i],Digits) )
               candle_len = Point();
            if ( ObjectFind ("candlesize_"+Symbol()+"_"+IntegerToString(i)) >= 0 )   { 
                   ObjectDelete("candlesize_"+Symbol()+"_"+IntegerToString(i)); 
            } 
            ObjectCreate ("candlesize_"+Symbol()+"_"+IntegerToString(i),  
                          OBJ_TEXT,  
                          0,  
                          time[i],  
                          low[i]-(double)(TextSize-1)*mast*(double)StringLen(DoubleToStr(candle_len/Point(), Exp))); 
            ObjectSet (  "candlesize_"+Symbol()+"_"+IntegerToString(i),  
                          OBJPROP_ANGLE,  
                          TextAngle 
                       ); 
            ObjectSetText ( "candlesize_"+Symbol()+"_"+IntegerToString(i),  
                            DoubleToStr(candle_len/Point(), Exp),  
                            TextSize,  
                            NULL,  
                            TextColor 
                           ); 
         } 
         return(rates_total); 
      }
      • Кстати, во втором случае индикатор “подчищает” за собой при его удалении с графика.

      • fl1cker 2 0

        Код первого индикатора поменял как написано.
        ObjectSetText ( “candlesize”+IntegerToString(i),
        DoubleToStr((NormalizeDouble(close[i]-open[i])+Point())/Point(), 0), 0),
        TextSize,
        NULL,
        TextColor
        );

        Индикатор не появляется при открытии мт4. Мб ошибка где? :( Добавлено сообщение 21.07.2017, в 08:22Разобрался. Спасибо большое. Настроил как нужно, теперь все работает как и хотел.
        Было бы вообще круто…. даже не так нет… БЫЛО БЫ МЕГА КРУТО, если бы можно было дополнить “другую версию моего же индикатора с автоматическим подстраиванием положения текста под текущий масштаб графика” следующим:
        Индикатор отслеживает появление 3-ех или более подряд свечей бычьих или медвежьих. Если тела каждой из 3-ех или более одинаковых свечей 10 и более пунктов индикатор выдает алерт например: “GBPUSD, M1, бычьих баров-3″
        Настраиваемый параметры:
        1) Символы (обозначения Валютных пар, например GBPUSD)
        2) Тайм фреймы
        3) Включение сигнала
        4) Количество баров для сигнала
        5) Количество пунктов свечей для сигнала

Ваш комментарий

Подписаться без комментирования