Статьи по MQL4
Создание индикатора

Создание индикатора


например, forex

Теперь мы вплотную подошли к пониманию пользовательских индикаторов в МТ4. Сделаем настоящий, а не графический индикатор по сигналам пересечения двух скользящих средних (МА). Файл CrossMA.csv содержит столбцы «Стрелка вверх» и «Стрелка вниз». Каждому бару однозначно в текущий момент времени соответствует время открытия бара (Time[]), номер бара (который будет увеличиваться с каждым новым завершенным баром) и значения из двух столбцов/массивов, указывающих на наличие красной или синей стрелки, или отсутствие обеих (нулевое значение). Создадим пользовательский индикатор с помощью «Мастера создания советника».

 
 


Укажем имя индикатора (CrossMA), автора, линк. Рядом с таблицей параметров жмем кнопку «Добавить», появляется новый параметр ExtParam1 (имя параметра по умолчанию ), даем новому параметру более осмысленное название LongPeriod, как в нашем предыдущем скрипте, тип int оставляем неизменным, начальное значение задаем равным 21.

 
 


Добавляем еще один параметр ShortPeriod, работа с внешними параметрами нашего индикатора на этом закончена. Идем «Далее». Чек-бокс «Индикатор в отдельном окне» не трогаем, наши стрелки будут располагаться на графике цен (Чек-боксы «Минимум» и «Максимум» поэтому нам недоступны). Опять жмем «Добавить», в списке индексов на строчке 1 появляется индекс типа «Line» и красного цвета («Red»), меняем тип на «Arrow» цвет на голубой «Blue». Тип символа 217(стрелка вверх) поменяем на 241 для полного сходства со скриптом.

 
 


Добавим второй индекс, также изменим все его данные (тип, цвет, символ).

 
 



#property copyright "MetaQuotes"
#property link      "http://forum.alpari-idc.ru/viewtopic.php?t=48186"
#property indicator_chart_window #property indicator_buffers 2 #property indicator_color1 Blue #property indicator_color2 Red //---- input parameters extern int LongPeriod=21; extern int ShortPeriod=13; //---- buffers double ExtMapBuffer1[]; double ExtMapBuffer2[]; //---- int init() { SetIndexStyle(0,DRAW_ARROW); SetIndexArrow(0,241); SetIndexBuffer(0,ExtMapBuffer1); SetIndexEmptyValue(0,0.0); SetIndexStyle(1,DRAW_ARROW); SetIndexArrow(1,242); SetIndexBuffer(1,ExtMapBuffer2); SetIndexEmptyValue(1,0.0); //---- return(0); } //---- int deinit() { //---- //---- return(0); } //---- int start() { int counted_bars=IndicatorCounted();
return(0); }

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

double ExtMapBuffer1[];
double ExtMapBuffer2[];
в которых, видимо, и будут храниться значения индикатора. Также созданы два входных параметра.

 
 


По сравнению с тем, как мы создавали скрипт, при создании индикатора была также создана функция init(), в которой производится окончательная настройка нашего индикатора. Индикаторы в МТ4 обладают очень большой гибкостью, каждый индикатор может «нести» в себе до 8 служебных(индикаторных) буферов. При этом достаточно только правильно объявить эти буфера, а остальную заботу о размере этих буферов возьмет на себя терминал. Эти буфера также называются индексами, пользовательский индикатор может выдавать значения для нулевого индекса, первого индекса , второго и так далее до седьмого индекса. Количество индексов мы задаем директивой
#property indicator_buffers N
но цвета при этом задаются не с нуля, а с единицы
#property indicator_color1 Blue
#property indicator_color2 Red

С помощью SetIndexStyle(номер_индекса, стиль) мы задаем каждому индексу необходимый стиль (каждый индикатор может иметь несколько индексов с разными стилями рисования), указав на стиль Arrow мы далее уточнили код символа (241 и 242) для каждого индекса, и только потом было указано, что индекс 0 – это массив ExtMapBuffer1, индекс 1 – это данные из массива ExtMapBuffer2. Без такого связывания индекса и массива функцией SetIndexBuffer(номер_индекса, имя_массива_буфера) индикатор работать не будет, это одна из ошибок при написании индикаторов. Вторая возможная ошибка (которую очень сложно бывает обнаружить) – объявление буферов типом, отличным от double, например int .

 
 

Последней строчкой идет функция SetIndexEmptyValue(номер_индекса, Пустое_Значение). В языках программирования обычно нет понятия "отсутствия значения", если у нас есть понятие "Свет", то понятие "Тьма" в программировании будет не отсутствие Света, а очень мало Света. Поэтому важно указать, что какое-то определенное значение будет означать отсутствие значения (в нашем случае – отсутствие стрелки), обычно таким значением бывает 0.0 (ноль с точностью до одного знака после запятой), хотя можно использовать и другие значения. Осталось только написать алгоритм, который и заполнит индикаторные буфера (индексы) значениями, на которых будут располагаться стрелки. Для этого обратимся к последнему скрипту CrossMASignals-5, скопируем все из блока start(), уберем операции с нанесением стрелок на график и записью в файл. Я также добавил функции Print() в блоки init() и deinit(). Мы практически сделали индикатор, не написав еще кода, а только скопировав некоторые куски из скрипта и закомментировав ненужные места. Если поставить /* в начале фрагмента, а */ в конце фрагмента, то весь фрагмент станет комментарием, которые, как мы знаем, не компилируются. Это бывает удобно при поисках ошибок и необходимости отключать при компиляции большие куски кода.

 
 


#property copyright "MetaQuotes"
#property link      "http://forum.alpari-idc.ru/viewtopic.php?t=48186"
#property indicator_chart_window #property indicator_buffers 2 #property indicator_color1 Blue #property indicator_color2 Red //---- input parameters extern int LongPeriod=21; extern int ShortPeriod=13; //---- buffers double ExtMapBuffer1[]; double ExtMapBuffer2[];
//----
int init() { //---- indicators Print("Выполняется init()"); SetIndexStyle(0,DRAW_ARROW); SetIndexArrow(0,241); SetIndexBuffer(0,ExtMapBuffer1); SetIndexEmptyValue(0,0.0); SetIndexStyle(1,DRAW_ARROW); SetIndexArrow(1,242); SetIndexBuffer(1,ExtMapBuffer2); SetIndexEmptyValue(1,0.0); return(0); }
//----
int deinit() { Print("Выполняется deinit()"); return(0); }
//----
int start() { int counted_bars=IndicatorCounted(); //---- double maLongCur, maLongPrev, maShortCur, maShortPrev;
/* string arrowName; // здесь будут назначаться уникальное имя объекта-стрелки int arrowCounter=0;// счетчик стрелок
*/
// объявим служебные переменные, в которых будем хранить ценовые координаты стрелок double value1,value2;
Print("Выполняется start()"); for(int i=Bars-1;i>=0;i--) { // обнулим службные переменные value1=0.0; value2=0.0; maLongCur=iMA(NULL,0,LongPeriod,0,MODE_SMA,PRICE_CLOSE,i+1);// медленная средняя на предыдущем баре maLongPrev=iMA(NULL,0,LongPeriod,0,MODE_SMA,PRICE_CLOSE,i+2);// медленная средняя на предпредыдущем баре maShortCur=iMA(NULL,0,ShortPeriod,0,MODE_SMA,PRICE_CLOSE,i+1);// быстрая средняя на предпредыдущем баре maShortPrev=iMA(NULL,0,ShortPeriod,0,MODE_SMA,PRICE_CLOSE,i+2);// быстрая средняя на предыдущем баре

//Если есть сигнал к покупке на предыдущем баре - поставим синюю стрелку вверх // по цене открытия бара if((maShortCur>maLongCur)&&(maShortPrev<maLongPrev)) { /* // Поставим стрелку // имя объекта - arrowName // тип объекта - OBJ_ARROW // координата по горизонтали - Time[i] время открытия бара // координата по вертикали - Open[i] цена открытия бара arrowName="arrow"+arrowCounter; ObjectCreate(arrowName,OBJ_ARROW,0,Time[i],Open[i]); // зададим тип стрелки - 241 , стрелка вверх ObjectSet(arrowName,OBJPROP_ARROWCODE,241); // зададим цвет стрелке - голубой ObjectSet(arrowName,OBJPROP_COLOR,Blue); // увеличить счетчик стрелок arrowCounter++; */ value1=Open[i];//запомним цену голубой стрелки } //Если есть сигнал к продаже на предыдущем баре - поставим красную стрелку вниз // по цене открытия бара if((maShortCur<maLongCur)&&(maShortPrev>maLongPrev)) { /* // Поставим стрелку // имя объекта - arrowName // тип объекта - OBJ_ARROW // координата по горизонтали - Time[i] время открытия бара // координата по вертикали - Open[i] цена открытия бара arrowName="arrow"+arrowCounter; ObjectCreate(arrowName,OBJ_ARROW,0,Time[i],Open[i]); // зададим тип стрелки - 242 , стрелка вниз ObjectSet(arrowName,OBJPROP_ARROWCODE,242);
// зададим цвет стрелке - красный ObjectSet(arrowName,OBJPROP_COLOR,Red); // увеличить счетчик стрелок arrowCounter++; */
value2=Open[i];//запомним цену красной стрелки }
/* //запишем данные для текущего бара в файл FileWrite(FileHandle,TimeToStr(Time[i]),i,value1,value2); */ } return(0); }

Код отлично компилируется, но рисовать наш индикатор ничего не будет. Для этого нам необходимо добавить только две строчки:

          
      ExtMapBuffer1[i]=value1;
ExtMapBuffer2[i]=value2;
Насколько мы помним, CrossMA.csv(после выполнения скрипта CrossMASignals-5) содержит два столбца : «Стрелка вверх» и «Стрелка вниз». Теперь эти столбцы у нас находятся в буферах ExtMapBuffer1[] и ExtMapBuffer2[] .
Компилируем индикатор и запускаем его опять на графике EURUSD D1. У нас снова имеется на графике два набора стрелок (красные и синие), но только стрелки меньше размером и они уже не являются графическими объектами, доступными для редактирования, стрелки стали неотъемлемой частью индикатора и будут перерисовываться при смене тайм-фрейма. Откроем панель «Окно данных» и наведем перекрестие на последнюю синюю стрелку вверх (чтобы получить режим перекрестия, достаточно нажать среднюю кнопку мыши или колесико). Напротив CrossMA находится значение 1.1886 – это и есть значение буфера ExtMapBuffer1 на данном баре, value2 – это значение буфера ExtMapBuffer2 на данном баре, значение для него отсутствует, так как 0.0 является пустым значением ( помните
 SetIndexEmptyValue(0,0.0);
  
 SetIndexEmptyValue(1,0.0);
  
? )

 
 

Как видите, ничего сложного в создании индикатора нет.
Сам индикатор можно скачать здесь


Перейти к статье «Оптимизация индикатора».
 
+7 (495) 710-76-76
8 (800) 200-01-31
по России бесплатно

закрыть

Вход в личный кабинет

Для счета alpari.classic введите номер счета (буква и 4 цифры) и пароль в ЛК.

Для счетов alpari.micro и alpari.partner введите логин и пароль в МТ.

Зарегистрироваться!Забыли пароль?

 
Rambler's Top100