Наши рекомендации:

  1. Главная
  2. Уроки MQL4
  3. 3.0 Программируем простой MQL4 советник по системе «Монетка»

3.0 Программируем простой MQL4 советник по системе «Монетка»

обучение mql4

Если вы задавались вопросом «Как написать советник на языке программирования MQL4», то данный пост создан именно для вас. Сегодня мы будем создавать самый простой из всевозможных советников для МТ4, который будет определять незамысловатое условие на вход, открывать ордер и модифицировать его цели.

Алгоритм программирования советника на MQL4

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

OnInit()

Она генерируется только один раз за время работы советника в самом начале. Нужна, чтобы внутри нее определить, рассчитать и задать те переменные и массивы данных, которые не нуждаются в дальнейшей корректировке по мере обновления тиков. То же самое касается и графических объектов. В советнике раздел OnInit выполняет ту же роль, что мы проходили в теме создания первого индикатора.

OnDeinit()

Функция вызывается советником только один раз перед непосредственным удалением его с графика. Она используется также и в индикаторах. Раздел OnDeinit нужен, чтобы подчистить график после советника, обнулить глобальные переменные и выдать окончательный расчет или текст пользователю. Более подробно мы ее проходили при создании первого индикатора.

OnTick()

Данная функция новая в наших уроках. Раздел OnTick генерирует события исключительно для экспертов и не может быть вызвана в индикаторах или скриптах. Ее тип данных void и набор параметров отсутствует. По своей логике работы она схожа с функцией для индикаторов OnCalculate,  только она не возвращает никакого значения после завершения. Задача у нее одна — запускаться каждый новый тик и проходить циклом весь написанный код в ней от начала до конца. Так как любой советник должен проверять условия для входа/выхода из рынка, считать количество открытых ордеров и выполнять их сопровождение, то можно уверенно сказать, что функция OnTick является самой важной в коде любого эксперта.

Продолжим разбирать алгоритм работы. Вначале советник инициализируется. Далее запускается функция OnTick, в которой выполняются все дальнейшие действия. Для данного советника сначала необходимо проверить наличие уже открытых им ордеров. Если они есть — дальнейший расчет и поиск условия на вход не выполняются, потому что в рынке у нас должен быть только один ордер за раз. Если же открытых сделок нет, то идет определение направления будущей позиции. В зависимости от него запускается пользовательская функция на открытие Buy или Sell ордера. Если по какой-то причине сделка не смогла открыться, расчет возвращается назад в функцию OnTick, чтобы попробовать выставить ордер снова. Если же ордер открылся, то он модифицируется (выставляется Тейк-Профит и Стоп-Лосс). На этом алгоритм заканчивает свою работу по работе с ордерами, потому что счетчик новых ордеров уже будет учитывать этот открывшийся ордер, делая проверку каждый тик. И только после того, как ордер закроется по достижению своей цели (ТП или СЛ), цикл проверки условия на открытие ордера запустится снова. Функция OnDeinit запустится только тогда, когда вы удалите советник с графика.

Наш код, конечно, не будет выглядеть точь-в-точь как эта схема, но думаю, что принцип его написания вам понятен.

Торговая система «Монетка»

форекс тс монетка

Когда перед нами стоит вопрос «как создать Форекс советник», то в первую очередь в голову приходит мысль о торговой системе, заложенной в нем, логике открытия ордеров. Так как в этом уроке не стоит цель создать так называемый на сленге «Грааль», то для получения опыта в написании первого эксперта мы возьмем на вооружение самую простую ТС, которую только можно выдумать.

Период советника установим М15. Мы будем входить в рынок по воле случая, или, если хотите, удачи. Мы начнем условно подкидывать монетку и смотреть на результат этого несложного действия. Орел или Решка — только два исхода событий будет у советника. Вариант «ребро» в данном случае не рассматривается 🙂

Зачем использовать такую простую систему? Чтобы понять, что произойдет в результате этого эксперимента и ответить себе на вопрос: можно ли заработать на Форекс входя в рынок наобум? Получится ли прибыльно торговать не имея четко спланированной торговой системы?

Проверка советника на ошибки: GetLastError()

При написании советника (как и при его использовании) очень важно следить за возможными ошибками в коде. Речь идет не об ошибках компиляции, их вы можете увидеть во вкладке «Ошибки» окна «Инструменты». Разговор о скрытых ошибках, которые проявляют себя во время тестирования или работы советника на реальном счете. Проверку на эти ошибки нужно делать как минимум один раз за тик в функции обработки событий OnTick. Как максимум — в каждой вашей пользовательской функции.

Чтобы получить номер возможной ошибки, нужно вызвать функцию GetLastError(). Она имеет тип int и возвращает целое число, значение системной переменной _LastError. Тут нужно обратить внимание, что на языке MQL4 после вызова функции GetLastError ее значение обнуляется и повторный вызов ее в том же месте кода вернет значение 0, поэтому ее значение нужно сохранять в отдельную переменную.

Язык MQL различает как минимум 150 разных ошибок. Соответственно каждый возвращаемый номер имеет свою расшифровку. Ноль значит это ошибки нет и все отлично, 134 значит, что недостаточно денег на счете и т.д.

Чтобы получить примерную расшифровку ошибки на английском языке, нужно обратиться ко встроенной библиотекой stdlib.mq4, которая находится в папке Libraries терминала. Для этого нужно воспользоваться препроцессором включение файлов #include. Для этого прописываем импорт данной библиотеке в самом начале кода вне функций.

Теперь осталось прописать проверку в самом конце функции обработки событий OnTick()

В этом коде вначале сохраняется значение ошибки в переменную Error, далее проверяется, чтобы ошибка точно была (значение не было равно нулю) и если это так, то выводится принт в журнал с номером ошибки и ее расшифровка.

Напиши в комментариях, если вы хотите видеть более подробную расшифровку ошибок на русском языке в будущих уроках.

Пишем свой первый советник

Чтобы создать советник, нажмите «Файл»  — «Создать». Затем выберите вариант «Советник (шаблон)», клик по кнопке Далее, придумываете ему имя, гордо записывая себя, как автора и добавляете ссылку на ваш (или наш) сайт. Параметры добавлять не нужно, мы их пропишем вручную, тык по кнопке Далее. Обработчики событий нам не нужны, поэтому еще раз клик на Далее. Функция OnTester полезная при оптимизации сов, но в этом уроке она не понадобится (мы рассмотрим ее в будущих статьях). Жмем Готово.

Программа создаст стандартный шаблон из описания и трех функций обработки событий: OnInit, OnDeinit и OnTick.

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

  • Lot — торговый лот, с которым будет открываться ордер. По умолчанию задаем его минимальным. Тип переменной будет double, т.к. это лот не может быть целым числом.
  • Slippage — максимально допустимое проскальзывание в пунктах, больше которого ордер не будет открыт.
  • Stop Loss — Стоп Лосс (ограничение убытка) для каждого ордера советника. По умолчанию задается в пунктах.
  • Take Profit — Тейк Профит нужен для закрытие ордера при достижении заданной прибыли. По умолчанию задается в пунктах.
  • Comments — текстовый комментарий, с которым будет открыт ордер. Его можно будет увидеть в окнах «Торговля» и «История Счета» в столбце «Комментарий». Он полезен, если на счете торгует несколько советников, либо используется ручная торговля. Некоторые брокеры в комментарий прописывают проскальзывания при открытии конкретного ордера. Также он хранит информацию, если ордер был частично закрыт.
  • MagicNumber — номер (целое число), который задается всем ордерам конкретного советника, открытым по текущему символу. Магик нужен для того, чтобы советник мог отличить свои сделки от чужих. Для каждой пары и советника рекомендуется задавать свой уникальный магик. Ордера, открытые вручную имеют нулевой магик. Магик также можно увидеть на мониторинге сервисов MyFxBook или FxBlue, и сделать по нему фильтрацию.

Данные шесть параметров являются необходимыми даже для самого простого советника. Чтобы их можно было видеть при настройке советника, воспользуемся классом памяти extern, который определит наши переменные как внешние. Данный блок кода прописывается в самом начале редактора.

Переходим к функции OnInit. Так как на Форекс до сих пор существуют типы счетов с котировками, у которых разное количество знаков после запятой, то необходимо добавить проверку для тех параметров, значение которых указываются в пунктах. Изначально мы задали значения проскальзывания, Стоп Лосса и Тейк Профита в старых пунктах. Если же у валютной пары три знака (для JPY) или пять (для остальных валют) после запятой, то нам необходимо перевести старые пункты в новые, умножив это значение на десять.

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

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

Мы дошли до функции OnTick. В ней дальнейший код будет совершать свой цикл каждый тик. В соответствии со схемой работы нашего алгоритма вначале мы должны проверить, что в рынке нет открытых ордеров у данного советника. Для этого напишем пользовательскую функцию анализа сделок CountOrder().

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

Теперь эту функцию нужно добавить в тело OnTick и проверить условие, чтобы открытых ордеров не было.

Далее нам необходимо определиться с направлением сделки. Как говорилось выше, мы будем входить по системе «Монетка», т.е. нам нужно рандомно (наугад) определить направление входа. С этим поможет справиться функция MathRand(), она возвращает псевдослучайное целое число в диапазоне от 0 до 32767. Так как нам нужно получить только два значения: 0 (для покупок) или 1 (для продаж), то просто добавим знак %, с помощью которого получим остаток от деления на 2. Каждый тик результат будет случайно определяться между 0 и 1.

Пользовательская функция OpenTrade()

С условием на вход определились, осталось в зависимости от него осуществить покупку или продажу. Для этого введем еще одну пользовательскую функцию OpenTrade(). Ей будет передаваться один параметр — направление на вход. В зависимости от направления сделки нужно определить:

  • Price — цена открытия ордера. Рыночные ордера на покупку открываются по цене Ask, а закрываются по цене Bid. И наоборот, рыночные ордера на продажу открываются по цене Bid, и закрываются по цене Ask.
  • Цвет стрелочки да пометки открытия ордера на графике. По обычаю покупки имеют синий цвет, продажи красный.
  • Текст для открытия ордера.

Для упрощения работы мы воспользуемся условным оператором ? 

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

  • symbol — символ, по которому необходимо открыть ордер. Текущий символ задается как Symbol().
  • cmd — торговая операция, т.е. один из шести типов ордера, который нужно открыть: рыночные (buy или sell) и отложенные (buylimit, selllimit, buystop, sellstop).
  • volume — размер торгового лота.
  • price — цена открытия ордера. Для рыночных ордеров нами она рассчитана выше.
  • slippage — проскальзывание в пунктах, берется из внешней переменной.
  • stoploss — Стоп Лосс рассчитанный по цене котировок.
  • takeprofit — Тейк Профит рассчитанный по цене котировок.
  • comment — комментарий к ордеру, берется из внешней переменной.
  • magic — магик номер, берется из внешней переменной.
  • expiration — срок жизни ордера. Нужен только для отложенных ордеров, поэтому оставляется равный нулю.
  • arrow_color — цвет стрелочки на графике при открытии ордера.

Открываем ордер.

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

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

Для расчета цены Стоп Лосса по текущим котировкам:

  • для покупок от текущей цены открытия ордера (OrderOpenPrice) вычитаем значение переменной StopLoss, умноженной на Point.
  • для продаж к текущей цене открытия ордера (OrderOpenPrice) прибавляем значение переменной StopLoss, умноженной на Point.

Для расчета цены Тейк Профит по текущим котировкам:

  • для покупок к текущей цене открытия ордера прибавляем значение переменной TakeProfit, умноженной на Point.
  • для продаж от текущей цены открытия ордера вычитаем значение переменной TakeProfit, умноженной на Point.

Модификацию выполняем с помощью торговой функции OrderModify. Она содержит почти такие же параметры, как и функция OrderSend, плюс ей передается номер тикета ордера, который нужно модифицировать.

Собрав все описанное выше вместе у нас получается готовая пользовательская функция для открытия и модификации ордера.

Соответственно, у нас определяется цена открытия ордера, цвет и текст. Далее открывается ордер и, если его тикет больше нуля, тогда в бой вступает расчет целей для ордера в значении котировок на графике. Затем происходит попытка модифицировать ордер, и если все прошло гладко, то функция OpenTrade вернет true, иначе же выдаст принт об ошибке и ее номер с расшифровкой. Если же ордер не открылся — советник также выдаст принт об ошибке и попытается произвести открытие на следующем тике.

Нам осталось вернуться в функцию OnTick и добавить эту пользовательскую функцию в его тело.

Проверка советника в тестере

Мы не знаем, какой таймфрейм нужен для данного советника, поэтому можно использовать любой. То же самое и с котировками, их можно использовать и с 90% качеством, для проверки работоспособности кода этого достаточно. Наша основная цель — запустить визуализацию и просмотреть глазами выполнение его логики торговли.

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

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

Все выглядит хорошо, значит делаем вывод, что код написан без ошибок. По крайней мере видимых.

Посмотрим на график тестирования системы «Монетка» и сделаем выводы.

Заключение

Мы научились создавать самый простой советник на языке программирования MQL, проверять условия на вход, рассчитывать количество открытых ордеров, а также добавили в код необходимую проверку на ошибки.

Одной из целей данного урока было доказать, что необдуманная торговля не в состоянии принести прибыль. В данном примере мы использовали рандомный вход с абсолютно одинаковыми ТП и СЛ, равными 20 пунктов каждый. Т.е. при таком раскладе, если 55% сделок были бы прибыльными, то график доходности шел вверх. В нашем случае кривая прибыли нацелена строго вниз, что говорит нам самую простую истину: вы никогда не заработаете на рынке, если у вас не будет четкой и строго сформулированной торговой системы. Форекс это далеко не казино и на волю случая тут нельзя полагаться. Без четких правил входа, сопровождения ордеров и выхода из сделки вас ждет неудача.

На этом все, код советника приложен ниже. Если пост был вам полезен, то вы знаете, что делать! Оставляйте комментарии и делитесь им в тематических сообществах. Всем профитов!

0. Начало работы

Блог для успешных трейдеров на рынке Форекс. Полезный сайт о Forex — DaVinci FX Group.

Предыдущая запись
2.9 Создаем информационную панель с сигналами индикаторов на вход. Графические объекты OBJ_RECTANGLE_LABEL, OBJ_LABEL
Следующая запись
3.1 Создаем советник, торгующий по сигналу двух скользящих средних

2 комментария. Оставить новый

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Заполните поле
Заполните поле
Пожалуйста, введите корректный адрес email.
Вы должны согласиться с условиями для продолжения

Меню