Сегодня разберемся, как работать в языке MQL4 с внешними индикаторами. Невозможно встроить все индикаторы форекс в терминал Metatrader. Постоянно появляются новые индикаторы Forex и усовершенствуються старые индикаторы. Поэтому разработчики терминала Metatrader4 позаботились о работе с внешними индикаторами в языке MQL.
Рассмотрим например индикатор форекс «ZigZag»:
Он не встроен в терминал MT4, хотя и поставляется вместе с ним. Если взглянуть на график валютной пары, то прекрасно видно преимущества данного индикатора Forex.
Было бы здорово, если бы трейдер покупал внизу и продавать вверху точек излома индикатора ZigZagа. Стратегию я такую не нашел. Поэтому просто проверю — действительно это так или нет. Но для начала необходимо сформулировать условия торговли:
— покупаем когда ZigZag рисует линию вниз.
— продаем когда ZigZag рисует линию вверх.
— окончание линии ZigZagа анализируем при открытии следующей свечи
— стоп-лосс ставим на 5 пунктов вниз или вверх от экстремума ZigZagа
— тейк-профит ставим в 5 раз больше величины стоп-лосса
— при образовании нового фрактала, стоп-лосс переносим вслед за ценой
Правила сформулировали, теперь можно заняться созданием советника форекс для Metatrader 4 на языке MQL4.
Создаем новый советник — назовем его «expert3».
Переносить наши функции теперь не надо, достаточно подключить нашу библиотеку «MyLib».
Добавим новые параметры для индикатора форекс ZigZag:
extern int ExtDepth=12;
extern int ExtDeviation=5;
extern int ExtBackstep=3;
Вот что у нас получится:
//+——————————————————————+
//| expert3.mq4 |
//| Copyright c 2010, MQL для тебя. |
//| http://strategy4you.ru |
//+——————————————————————+
#property copyright «Copyright c 2010, MQL для тебя.»
#property link «http://strategy4you.ru»
#include <MyLib.mqh>
extern int MaxRisk=2;
extern int TakeProfit=5;
extern int StopLoss=5;
extern int ExtDepth=12;
extern int ExtDeviation=5;
extern int ExtBackstep=3;
datetime Today=0;
//+——————————————————————+
int init() {return(0);}
//+——————————————————————+
int deinit() {return(0);}
//+——————————————————————+
int start()
{if(DayOfWeek()==0 || DayOfWeek()==6) return(0); // в выходные не работаем
if(!IsTradeAllowed()) return(0); // пропустим тик если терминал занят
//:проверим открытие новой свечи
if(Time[0]==Today) return(0);
Today=Time[0];
//:получим значение ZigZag на предыдущей свече
double lZZ=iCustom(NULL,0,«ZigZag»,ExtDepth,ExtDeviation,ExtBackstep,0,1);
return(0);}
//+——————————————————————+
С помощью функции iCustom() можно получить значение из внешнего индикатора. Хорошо скажите Вы. А откуда мы знаем, какие параметры и сколько буферов у индикатора, если он скомпилирован? Ведь нам их надо указать функции iCustom().
Установите индикатор на график в терминале и посмотрите его параметры:
Вот мы и увидели параметры индикатора и порядок их следования.
А здесь мы видим что буфер для рисования всего один:
Продолжим. Нам необходимо знать количество уже открытых ордеров что бы не открывать ордера повторно. Это мы можем глянуть в наших предыдущих советниках. Предлагаю сразу же в цикле подсчета ордеров реализовать перенос стоп-лосса по фракталам:
int oBuy=0,oSell=0;
for(int i=OrdersTotal()-1;i>=0;i—)
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{if(OrderType()==OP_BUY)
{double f1=NormalizeDouble(iFractals(NULL,0,MODE_LOWER,3),Digits);
if(f1>0 && OrderStopLoss()<f1 && f1<Bid) EditOrder(OrderTicket(),f1);}
if(OrderType()==OP_SELL)
{double f2=NormalizeDouble(iFractals(NULL,0,MODE_UPPER,3),Digits);
if(f2>0 && OrderStopLoss()>f2 && f2>Ask) EditOrder(OrderTicket(),f2);}
if(OrderType()==OP_BUY) oBuy++;
if(OrderType()==OP_SELL) oSell++;}
С помощью функции iFractals() мы получаем значение индикатора. Для ордеров типа Buy — берем нижние фракталы, а для ордеров типа Sell — верхние. Фракталы ищем на 3 свече от текущей. Дело в том что фрактал считается сформировавшимся если после свечи со стрелочкой идет 2 подряд свечи вверх или вниз соответственно.
Еще я использовал округление: NormalizeDouble(…,Digits). Дело в том, что некоторые Брокеры форекс с 4 значными котировками (типа Forex4you) не имеют истории своих котировок. При подгрузке котировок в этом случае будет использоваться сервер MetaQuotes, а там хранятся 5 значные котировки — в итоге при тестировании будут ошибки при открытии или модификации ордеров.
Осталось самое основное: открытие ордеров.
if(lZZ>0 && oBuy+oSell==0)
{i=2;
while(iCustom(NULL,0,«ZigZag»,ExtDepth,ExtDeviation,ExtBackstep,0,i)==0) i++;
double fZZ=iCustom(NULL,0,«ZigZag»,ExtDepth,ExtDeviation,ExtBackstep,0,i);
double Lot=GetLot(MaxRisk);
if(Lot==0) {Alert(«Недостаточно средств!»);return(0);}
double tp=0;
double sl=0;
if(lZZ>fZZ)
{sl=NormalizeDouble(lZZ+StopLoss*Point,Digits);
if(TakeProfit>0) tp=NormalizeDouble(Bid-(sl-Bid)*TakeProfit,Digits);
NewOrder(OP_SELL,Lot,0,tp,sl);}
if(lZZ<fZZ)
{sl=NormalizeDouble(lZZ-StopLoss*Point,Digits);
if(TakeProfit>0) tp=NormalizeDouble(Ask+(Ask-sl)*TakeProfit,Digits);
NewOrder(OP_BUY,Lot,0,tp,sl);}}
Здесь мы проверяем что нет открытых ордеров и что окончание линии индикатора ZigZagа на предыдущей свече. Определяем направлении линии ZigZagа (для этого сравниваем точки между которыми проведена последняя линия) и открываем ордера. Осталось проверить как это все работает.
Для этого запустим тестер стратегий MT4 в визуальном режиме:
Обратите внимание на галочку «Визуализация». Нажимаем старт и после этого кнопочку:
Откроется график, но тестирование дальше не пойдет. Нам это и нужно. Устанавливаем на открывшийся график индикаторы ZigZag и Фракталы. После этого нажимаем кнопочку:
Начинается тестирование и мы видим все действия эксперта:
За декабрь месяц у меня, созданный нами эксперт «expert3» получил прибыль:
Признаться, я такого результата даже и не ожидал… При тестировании же эксперта «expert3» на большем промежутке времени, получили полный слив депозита.
Но т.к. я и не нанадеялся что созданный нами советник сразу будет прибыльным, то это вполне нормально! Я хотел всего лишь проверить свою идею и показать Вам, как можно использовать в своем эксперте MT4 внешние индикаторы.
Скачать: Советник «expert3»
При компиляции советника выдает две ошибки
А какие ошибки? К сожалению я еще не научился читать мысли 🙂 И не зная что за ошибки проблематично ответить из-за чего они возникают.
компилятор ругнулся на скобки
‘)’ wrong parametr count (35,78 и (38,77) которые стоят в вызове функции EditOrder после f1 и f2 соответственно
хотя по количеству скобок все нормально, не могу понять в чем дело
Когда скобок не хватает компилятор ругается по другому: ‘\end_of_program’ — unbalanced left parenthesis
В данном случае компилятор сообщает что количество параметров функции EditOrder и количество параметров передаваемых ей при вызове не совпадают.
Если вы копировали код прямо со страницы — рекомендую скачать советника в конце статьи. Редактор не всегда правильно оформляет код.
указанные ошибки возникают при компиляции скачанного советника.
Странно. Скачал сейчас советника и библиотеку с заголовочным файлом. Откомпилировал. Все работает. Скачайте заново библиотеку и заголовочный файл из урока MyLib
Возможно Вы ранее скачали первую версию библиотеки. Там действительно был всего 1 параметр у функции EditOrder. В обновленной 2 параметра.
Здравствуйте !
Очень интересный и классный материал , но мне непонятно как реализован трейлинг стоп . Можно ли объяснить подробнее
Здравствуйте Александр!
А можно ли дополнить советник на zigzag чтобы открывалось несколько ордеров и sl у них был общий
при открытии ордера в другую сторону все открытые ордера закрывались Спасибо за интересный сайт. Но есть просьба подробнее объяснять, потому что Вам может быть все понятно, а нам неучам еще далековато, хотя благодаря Вашей работе, начинает что-то проясняться
Добрый день!
В данном уроке трал происходит по фракталам. Перебираем в цикле все открытые ордера и для каждого ордера смотрим где находится стоп лосс. Если ордер Buy и стоплосс находится ниже последнего фрактала «вниз», то мы его переносим на уровень этого фрактала. Если ордер Sell и стоп лосс находится выше последнего фрактала «вверх», то переносим его на уровень этого фрактала.
Добрый день!
Можно открывать любое количество ордеров. Для этого необходимо вызвать функцию NewOrder() столько раз — сколько ордеров необходимо открыть. Например так: for(i=1;i<3;i++) NewOrder(...,sl); будет открыто 2 ордера с одинаковым стоп лоссом.
Советник игнорирует все сигналы пока есть хоть один открытый ордер. Для изменения его согласно Вашим условиям необходимо исправить: if(lZZ>0 && oBuy+oSell==0) на if(lZZ>0), if(lZZ>fZZ) на if(lZZ>fZZ && oSell==0) и if(lZZ<fZZ) на if(lZZ<fZZ && oBuy==0). А для закрытия противоположных — перед вызовом функции NewOrder() сделать цикл по всем открытым ордерам (аналогично подсчету ордеров) только с вызовом функции CloseOrder() из библиотеки MyLib Пример:
if(lZZ>fZZ && oSell==0)
{sl=NormalizeDouble(lZZ+StopLoss*Point,Digits);
if(TakeProfit>0) tp=NormalizeDouble(Bid— (sl-Bid)*TakeProfit,Digits);
for(i=OrdersTotal() −1;i>=0;i—)
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
if(OrderType()==OP_BUY) CloseOrder(OrderTicket());
for(i=1;i<3;i++) NewOrder(OP_SELL,Lot,0,tp,sl);}
А как сделать советника, который просто ставит стоп-лосс на открытую позицию на уровне вершины (низины) zigzag’а? И чтобы был трал (отключаемый) тоже по zigzag’у. Вроде бы простой принцип, но что-то нигде не нашел. Много всяких советников со сложнейшими алгоритмами, а когда нужен просто с элементарными функциями, оказывается, что такого и нет.
Здравствуйте!
Хотел создать советник по фракталам , т.е. Как написать код, например когда один фрактал выше предыдущего то buy , если еще выше то опять + buy , и т.д. но вдруг не пробил high , то стоп, все позы закрываются
Здравствуйте!
Почему то при тестировании советника перенос SL осуществляется с запозданием
Пожалуйста можно комментировать строки, было бы хорошо для понимания
Здравствуйте!
В строках , где идет установка SL и TP мне кажется есть ошибка т.к. эти параметры не устанавливаются
Hermann
Аналогично тралу по фракталам описаному в Работа с внешними индикаторами
Амир
Ошибок нет. Советника я тестировал. Возможно Вы пытаетесь запускать советника у брокера с 5 значными котировками. Если это так, то необходимо увеличить параметры TakeProfit и StopLoss в 10 раз.
Амир
Что значит с запаздыванием?
Амир0 && fl>0) break;
Добрый день! Фракталы есть вверх и вниз. Обычно они чередуются. Если имеется ввиду фракталы вверх, то приблизительно так:
double fl=0;
for(int i=1;i
if(ff>0) fl=ff;}
if(fl>ff) OrderSend(…);
if(fl
Здраствуйте палт,
Возник такой вопрос, а как в индикатор фракталов они смещены несколко пипсов над хай и лоу баров! Думаю если разясните ето будет интересно для постоение собственных индикаторов! Оригинальной код невозможно прочитат с метаедитор!
венцислав
Добрый день.
Индикаторный буфер содержит цены (как значения одной из оси координат). Если мы сами заполняем буфер (пишем индикатор), то кто нам мешает к значению прибавить или отнять несколько пунктов? А это и будет смещение.
Здраствуйту палт,
спосибо для совет смещение с фракталов получилось. Возник такой вопрос в связи с разное серверное и локальное время. Думаю что надо сделат урок с примеров. Получаються очень нехорошие ошибки когда ползуються времевые идникаторы (пивоты), межсесионные флеты и т.д. FXCM хорошии ДЦ, ну у них время лондонское и готовые времевые идникаторы дают ложные сигналы!
ПС. Думаю также что всем будет полезно если сделаете уроки об статистическая обработка исторических данных. Ето очень мало разясняють в разные курсы. Прежде чем делать ТС, надо хорошо анализировать историческое движение цен и найти зависимости!
Благодарю вас за экспресс-курс ))
Давно хотел начать, да все руки не доходили ))
А теперь почти готов робот на CCI+MA.
Пока еще есть непонятные моменты, но стараюсь разобраться, справка помогает.
Если не до кумекаю, то спрошу 😉
венцислав
Пожалуйста. Смещение времени в скомпилированном индикаторе поменять нельзя, если он только не имеет такой опции. Если пишем свой индикатор, то нет ничего проще. Просто берем значение цены со смещением. Например время ДЦ отличается от GMT на +2 часа, тогда берем не Open[1], а Open[1+2].
Ребята напишите пожальуйста код….
если закрываеться ордер по SL открываеться противоположный ордер с задаваемым лотом, tp и sl
Здравствуйте!
Вот у меня такой код:
»
//|Анализатор тренда на основании индикатора ZigZag |
//+——————————————————————+
//…получим значение ZigZag на предыдущей свече
double LCZZ=iCustom(NULL,0,»ZigZag»,ExtDepth,ExtDeviation,ExtBackstep,0,1);
//…получим значение ZigZag на свече, X свечей назад
double FCZZ=iCustom(NULL,0,»ZigZag»,ExtDepth,ExtDeviation,ExtBackstep,0,ForwardCandleZigZag);
if(LCZZ>FCZZ)
TrendUp=true;
else TrendUp=false;
if(LCZZ<FCZZ)
TrendDn=true;
else TrendDn=false;
»
Пишет ошибки:
1) ‘double’ — variable expected C:\Program Files (x86)\Alpari MT4\experts\My_TS_Candle.mq4 (96, 2)
2) ‘LCZZ’ — variable not defined C:\Program Files (x86)\Alpari MT4\experts\My_TS_Candle.mq4 (96, 9)
3) ‘LCZZ’ — variable not defined C:\Program Files (x86)\Alpari MT4\experts\My_TS_Candle.mq4 (100, 5)
Не понимаю, что я делаю не так. Помогите пожалуйста
Здравствуйте. Вот у меня есть индикатор который создает на графике объекты — квадраты, скажите как получить верхнюю и нижнюю цены этого квадрата? Точнее как получить эти цены из самого индикатора? Скажите пожалуйста.
Здравствуйте, palt! Спасибо за обучение! Не могли бы Вы написать цикл для советника, который увеличивал бы лот вдвое в следующей сделке при убыточной предыдущей. Или переписать эксперта работающего по ZigZag.
За ранее благодарен!
То есть если буфера два тогда:
lZZ=iCustom(NULL,0,»ZigZag»,ExtDepth,ExtDeviation,ExtBackstep,0,1);
А если буфер один тогда:
lZZ=iCustom(NULL,0,»ZigZag»,ExtDepth,ExtDeviation,ExtBackstep,0);
так ?
Доброго времени суток.
Спасибо за столь ясные статьи, сравнимые с нитью Ариадны в темных корридорах MQL4 🙂
Я пытался протестировать предложенный советник, но почему-то у меня не открываются ордера. Тестировщик просто бежит по графику и все. в репорте все данные на нулях.
Код был взят с прикрепленного примера, включая Mylib библиотеку.
Заранее благодарен за помощь!
Здравствуйте.
Привильно ли я понял, что используя вариант внешний индикатор (например зиг-заг) невозможно использовать (вытянуть данные) где были предыдущие минимумы и максимумы которые этот индикатор сделал. Что бы использовать (например) эти уровни как уровни support/resistanse .
Удалите пожалуйта мой глупый вопрос номер 27 🙂
Для написания советника по данным индикаторов AIMS Box и AIMS Entry Alert, не могу открыт их коды. Проверил и оказалось, что коды открываются не у всех пользовательских индикаторов, может подскажите как поступит.