Видеоуроки по программированию на MQL5 - страница 5

 

MQL5 Без номера. О понятиях и терминологии


MQL5 Без номера. О понятиях и терминологии

Всем привет! Хотел в этом видео сразу же продолжить написание первого скрипта на MQL5. Но настала необходимость сделать несколько оговорок по поводу используемой терминологии и особенностей программирования под MQL5.

Оговорка 1: Я уже упоминал об этом в прошлом видеоуроке, но из-за того, что все равно может возникнуть путаница, сейчас повторю. Торговый терминал не имеет понятия "пипсы". Для него существуют только пункты. Пункт - это минимальный шаг изменения цены котировки торгового инструмента. Когда я говорю о пунктах, я имею в виду именно минимальный шаг котировки.

Оговорка 2: В отличие от MQL4, где разница между позициями, ордерами и сделками очень условна, в MQL5 это различие принципиально. MQL4 не является темой этого обучающего курса, поэтому достаточно будет сказать, что если вам где-то попадаются термины "позиция", "ордер" или "сделка", половина относится к MQL4, а другая половина к MQL5.

Терминал MetaTrader 4 рассчитан только на работу с рынком форекс, где независимо от брокера и поставщика его котировок, общие правила работы одни и те же. Но терминал MetaTrader 5 рассчитан на работу с самыми разными биржами, и правила работы на этих биржах тоже разные.

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

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

Вы так, MetaTrader 4 использует только хеджинг, то нет смысла обращать внимание на разницу между позициями, ордерами и сделками.

Вот терминал MetaTrader 5 рассчитан на работу как в hedging mode, так и в netting mode. В связи с этим есть столь жесткое разграничение между понятиями "позиция", "ордер" и "сделка".

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

Любая позиция есть результат выполнения как минимум одного ордера, то есть торгового приказа. Если это открытая позиция, то ордер может быть только один и его можно представить в виде команды "открыть позицию". А у закрытых позиций будет минимум два ордера - один на открытие и один на закрытие.

Для хеджинговой открытой позиции будет только один ордер, а у закрытой - ровно 2. А отложенный ордер всегда откроет новую позицию. В netting mode у открытой позиции может быть больше одного ордера, а отложенный ордер изменит уже существующую позицию в зависимости от своего направления, объема и ценового уровня, на котором установлен. Может он и закрыть текущую позицию, если объем отложенного ордера будет равен объему позиции, но в противоположном направлении.

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

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

Разработчики MetaTrader 5 предусмотрели функционал взаимодействия между терминалом и программами, которые будут запускаться внутри него. Для этого есть встроенные функции классов, структур, констант и т.д. и т.п. Все запросы и ответные реакции на них должны иметь строго определенную форму и содержание. Например, если программе нужно узнать текущее время сервера, она делает запрос терминалу, а тот предоставляет программе последнее полученное значение даты и времени.

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

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

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

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

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

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

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

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

MQL5 Без номера. О понятиях и терминологии
MQL5 Без номера. О понятиях и терминологии
  • 2021.10.29
  • www.youtube.com
Идея этого видео появилась неожиданно, под влиянием эмоций от общения с парочкой программистов, работающих исключительно в MQL4.Возможно, немного сумбурно и,...
 

MQL5 #11 Первый скрипт. Часть 2


MQL5 #11 Первый скрипт. Часть 2

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

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

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

Первую часть задачи мы реализуем в функции "OnStart", а вторую - в отдельных функциях, которые будем вызывать из главной по мере надобности. Вы не обязаны следовать такому подходу, никто не помешает вам реализовывать нужный функционал программы в том месте, которое вам кажется наиболее удобным, лишь бы это не противоречило синтаксису и правилам MQL5.

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

Давайте начнем с наброска нашего ветвления в функции "OnStart". Все просто: если значение переменной "in_direction" соответствует значению "OP_BUY", будем покупать, а если "in_direction" соответствует "OP_SELL", продаем. Но пока это только план, и их пока закомментированы.

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

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

Для этого необходимо создать объекты структур MqlTradeRequest и MqlTradeResult. Классы структур MqlTradeRequest и MqlTradeResult уже встроены в MetaTrader 5. Структуры в свою очередь являются одним из объектов, которые можно реализовать при помощи ООП. Эти объекты нельзя использовать напрямую, но можно создать столько экземпляров этих объектов, сколько нужно, заполнить их необходимыми значениями и потом использовать. Нам необходимо только по одному экземпляру каждой структуры.

Именно объекты MqlTradeRequest и MqlTradeResult будут заполняться нашей функцией и отправляться на сервер. Объект MqlTradeRequest будет заполняться корректно для открытия позиции, а объект MqlTradeResult мы заполнять не будем и отправим его на сервер в первозданном виде. Сервер уже после обработки нашего запроса заполнит поля up и вернет его нашему терминалу. По значениям полей объекта MqlTradeResult можно будет судить, произошла ли ошибка и нужно что-то предпринять, или все в порядке и можно идти дальше.

Перед заполнением объектов MqlTradeRequest и MqlTradeResult, вызовем функцию ZeroMemory для обоих объектов. Эта функция обнуляет значение переменной, которую передали в нее в качестве аргумента. Если это строка, ей присваивается значение NULL. Остальным простым типам просто присваивается 0. Если это числовой одномерный массив, всем его элементам будет присвоен нуль. Если же это экземпляр объекта или более сложный массив, то функция ZeroMemory автоматически будет вызвана для каждого внутреннего элемента.

Теперь, нужно заполнить структуру MqlTradeRequest. Обращаться к полям экземпляров объектов нужно по имени экземпляра, ставим точку и указываем имя поля. Эта запись говорит о том, что позиция должна быть открыта на символе, имя которого содержит переменная "symbol".

Дальше интереснее - поле "action". Оно отвечает за то, что именно мы хотим получить на счете. Оно может принимать только фиксированные значения: "TRADE_ACTION_DEAL" соответствует открытию позиции по текущей цене. Заметьте, никто не ругается на канвит имен переменных.

Так что, подготовку закончили, пора заполнять структуру запроса и обращаться к полям экземпляров объектов. Перед тем, как заполнять, вызовем функцию "ZeroMemory" для объектов MqlTradeRequest и MqlTradeResult. Затем заполняем структуру запроса, обращаясь к полям по имени экземпляра объекта. Вот такая запись говорит о том, что позиция должна быть открыта на символе, имя которого содержит переменная "symbol".

Дальше, поле "action" отвечает за то, что именно мы хотим получить на счете. Оно может принимать только фиксированные значения. Например, "TRADE_ACTION_DEAL" соответствует открытию позиции по текущей цене. Заметьте, никто не ругается на кавычки и имена переменных.

Остальные значения структуры будем разбирать по ходу.

Просто присваиваем этому полю значение переменной "lab". Осталось разобраться с такой тупиковой ситуацией - неиспользованный объем. Он появился из-за того, что терминал MT5 рассчитан на работу не только на форекс, но и на других рынках. Дело в том, что на форекс сделка всегда исполняется на весь указанный объем, а на других рынках возможны варианты, когда по указанной цене нет встречного предложения достаточного объема для исполнения ордера. На форекс такого не случается, а на других рынках - еще как бывает.

Отвечает за эту настройку поле "request_type". Тут возможны всего три варианта: "ORDER_FILLING_FOK" - ордер исполняется только указанным объемом, если объема нет, ордер отменяется; "ORDER_FILLING_IOC" - ордер исполняется по максимально доступному объему, оставшийся объем отменяется; "ORDER_FILLING_RETURN" - ордер исполняется по максимально доступному объему, а остаток остается на рынке и будет исполнен, если котировка вернется на его уровень и на этом уровне будет хоть какой-то объем встречного предложения.

Как я уже говорил, на форекс нас интересует только "ORDER_FILLING_FOK", а для других рынков нужно уточнять у конкретного брокера, который предоставляет к ним доступ.

Теперь необязательные поля. Это такие показатели, как комментарии, magic и проскальзывание. За комментарии отвечает поле "comment", для проскальзывания - поле "slippage", а для magic - поле "magic".

Также можно сделать проверку на содержимое нашей переменной. Если она не значимая, то поле заполнять не будем. Похожие проверки будут и для magic и проскальзывания.

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

Если функция возвращает ложь, то можно понять, что именно произошло, по коду ошибки, который будет записан в поле "retcode" объекта "result".

Теперь наша функция готова, осталось только вызвать ее из нашей главной функции. Не забыть подправить имя вызываемой функции и указать нужные типы ордеров в полях "request.type" и "request.type_filling". На этом, скрипт готов.

Наш первый скрипт можно считать работоспособным, но есть еще пятна на солнце. В следующем видео мы их устраним. А напоследок вот вам небольшая самостоятельная работа.

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

В начале следующего видео я покажу решение данной задачки. Файл со скриптом можно скачать из описания под видео. И на данный момент все. Всем пока!

MQL5 #11 Первый скрипт. Часть 2
MQL5 #11 Первый скрипт. Часть 2
  • 2021.11.15
  • www.youtube.com
Это видео приведет наш первый скрипт в рабочее состояние. Пропишем функции открытия позиций и рассмотрим основные тонкости этого процесса.Уголок компетентног...
 

MQL5 #11 Первый скрипт. Часть 3


MQL5 #11 Первый скрипт. Часть 3

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

Итак, по условиям задачи, нужно сделать настройку, при активации которой наш скрипт не должен обращать внимание на значение стопа и тейка, и открывать позиции без них. Также можно было только дополнять, но не менять созданные нами функции, и значение внешних переменных stopLoss и takeProfit по умолчанию, и конечный пользователь должен иметь возможность менять эту настройку, не касаясь клавиатуры, то есть только с помощью мыши.

В начале следующего видео я покажу решение данной задачи. Файл со скриптом можно скачать из описания под видео.

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

Для работы с позициями нам также понадобятся два служебных значения - минимальный шаг изменения котировки символа и точность его котировки, которые мы присваиваем переменным "point" и "digits".

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

Все остальное - заполнение запроса, отправка ордера на сервер и обработка возможных ошибок - уже знакомо нам из предыдущих уроков.

Теперь мы готовы использовать наши открывающие функции, и присвоить их результаты переменной "позиция". Она будет содержать номер открытой позиции или -1, если позиция не была открыта.

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

Теперь, если значение переменной "позиция" больше 0 и при этом разрешены стоп приказы, то вызываем функцию "разрешен sale".

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

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

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

Вторая причина будет темой следующего видео.

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

А пока что, ждите следующего видео!

MQL5 #11 Первый скрипт. Часть 3
MQL5 #11 Первый скрипт. Часть 3
  • 2021.12.04
  • www.youtube.com
Продолжаем написание первого скрипта. Боремся с последствиями проскальзываний путем модификации уже открытых позиций.Уголок компетентного дилетанта в Телегра...
 

MQL5 #11 Первый скрипт. Окончание


MQL5 #11 Первый скрипт. Окончание

Всем привет! Продолжаем исправлять различные проблемы в нашем первом скрипте. Начну с исправления недочетов, которые остались в скрипте.

Во-первых, функции модификации позиции нужно указать главное - требуемую торговую операцию. В данном случае, заполнить поле "request action". Также нужно отправить функции открытия, а именно установку отложенных ордеров. Сейчас у нас есть забавная ситуация, когда мы заполняем поля стоп приказов перед заполнением поля цены открытия. Из-за этого скрипт не выставит стоп приказ, так что нужно заполнить поле "рак вас прайс" перед заполнением полей стопа.

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

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

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

  • "Stop level" - ограничение, которое работает только во время открытия позиций и установки отложенных ордеров. Если в торговом запросе проставлен "пейк" (отличается от нуля), то расстояние до стоп приказа не должно быть меньше значения 100 пунктов.
  • "Freeze level" - ограничение, которое отвечает за возможность установки отложенного ордера или модификации уже открытой позиции. Новая цена установки стоп приказов не может быть ближе к цене их активации, чем расстояние "freeze level".

При этом, все расстояния считаются в пунктах. Откуда считать это расстояние? Для позиций и отложенных ордеров точкой отсчета является цена закрытия позиции. Для отложенных ордеров, расстояние "stop level" считается от цены его установки, а при установке отложенного ордера, цена его установки не может быть ближе к цене его активации, чем расстояние "freeze level".

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

Как узнать числовые значения этих ограничений? Это можно сделать при помощи функций SymbolInfoInteger(). С помощью этого скрипта, я покажу значения этих ограничений на графике.

Таким образом, ограничение "stop loss" для покупок должно быть не меньше или равно текущей цене бид, а для продаж - больше или равно текущей цене аск. Ограничение "take profit" для покупок должно быть больше или равно цене бид, а для продаж - меньше или равно цене аск. Отложенный стоп ордер должен быть больше или равен цене аск для покупок и меньше или равен цене бид для продаж.

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

При написании торговых программ просто смотрите, какие ситуации предусмотрены, и в каждом конкретном случае отталкивайтесь от этого. В случае нашего скрипта, можно проверить соответствие отложенного ордера ограничению "stop level", а стоп приказа - соответствие ограничению "freeze level". Причем, проверку на stop levels мы будем делать уже в самих функциях.

Перед вызовом функции открытия нужно получить значение "freeze level". Также нужно прописать вызов соответствующих функций для разных типов отложенных ордеров и избавиться от предупреждений. Деление назначения "point" нужно для того, чтобы привести значение из вида котировки в пункты и наоборот.

Наш скрипт не знает, как ему поступить, если нужная цена открытия попадает в зону ограничений. В таком случае, он выведет нам "alert" и досрочно завершит свое выполнение. Отложенный ордер не будет установлен, а вместо него вылезет предупреждение.

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

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

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

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

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

Если какая-то попытка окажется успешной, мы просто завершаем функцию. Особо обратите внимание на то, что многие начинающие и не очень программисты могут попасть в ловушку бесконечного цикла, если вместо for они используют while. Это может привести к ручному перезапуску всей программы.

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

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

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

MQL5 #11 Первый скрипт. Окончание
MQL5 #11 Первый скрипт. Окончание
  • 2021.12.13
  • www.youtube.com
В этом видео продолжаем парировать возможные проблемы в нашем первом скрипте.Рассмотрим что ограничивают STOP LEVEL и FREEZE LEVEL, а также как с ними работа...
 

MQL5 #12 Подготовка к роботу


MQL5 #12 Подготовка к роботу

Привет! Это последнее видео перед началом написания нашего первого робота. Сегодня мы проведем подготовительную работу к этому важному событию.

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

Чтобы избежать копирования кода, что может быть сложно для программиста, создадим включаемый файл. В нем будут содержаться функции исполнителей из нашего первого скрипта. Процесс компиляции такого файла заключается в проверке на ошибки в синтаксисе MQL5, без создания отдельного исполняемого файла.

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

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

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

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

MQL5 #12 Подготовка к роботу
MQL5 #12 Подготовка к роботу
  • 2021.12.16
  • www.youtube.com
В этом коротком видео-уроке мы создадим включаемый файл, который будет подключен как к нашему будущему роботу, так, в последствии, может быть прикручен и к д...
 

MQL5 Первый робот #1 Начало


MQL5 Первый робот #1 Начало

Всем привет! Сегодня начнем писать первого робота, но для начала я исправлю неточности, которые допустил в прошлом видео. Файлы исходного кода MQL5 программ имеют расширение .mq5, а включаемые файлы имеют расширение .mqh. Если проводить аналогию с языком C++, то файлы .mq5 аналогичны файлам .cpp или файлам исходного кода, а файлы .mqh - аналогичны файлам .h или заголовочным файлам. Теперь мы можем создавать робота, но все уже известной нам схеме - кнопка "Создать", выбор советника в скобках, салон выбран по умолчанию. Жмем "Далее" и указываем имя нашего будущего робота.

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

При нажатии кнопки "Готово" мы попадаем прямиком в шаблон будущего торгового советника. Если сравнивать его с шаблоном скрипта, то сразу же бросается в глаза наличие 3-х предопределенных функций вместо одной. Эти функции являются обязательными для всех торговых роботов, и именно этим функциям посвящен сегодняшний видео-урок.

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

Сначала происходит подтверждение входящих настроек. В отличие от скрипта, в роботах и индикаторах при запуске на графике инструмента окно входящих настроек выводятся всегда. Никаких дополнительных телодвижений с директивами свойств, как в скрипте, не нужно. После подтверждения входящих настроек происходит вызов функции OnInit(). Эта функция запускается однократно при первой установке робота на график котировки торгового инструмента. Второе - в начале работы при смене торгового счета без удаления робота с графика. Третье - при изменении входящих настроек без удаления робота с графика. Четвертое - при переходе на другой таймфрейм без удаления робота с графика.

Как вы уже могли заметить, функция OnInit() не принимает никаких аргументов, но при этом имеет тип возвращаемого значения. Она возвращает одно из значений перечисления ENUM_ERROR. По умолчанию возвращается значение "SIGNAL_BASE". Все в порядке.

Однако есть еще 3 возможных возвращаемых значения:

  • ENUM_ERROR_INVALID_PARAMETERS - возвращается, если произошла ошибка при проверке начального состояния робота, например, если что-то не так с внешними переменными;
  • ENUM_ERROR_INTERNAL_ERROR - какая-то другая ошибка инициализации;
  • ENUM_INIT_PARAMETERS_INCORRECT - никакая из других ошибок инициализации.

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

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

Стоит помнить, что только возвращение значения не равного 0 считается успешной инициализацией. Все остальные значения засчитываются как ошибка инициализации. Робот не будет установлен на график, если функция OnInit() возвращает не 0. То сразу же вызывается функция OnDeinit(), аргументом при вызове которой будет значение, которое вернет функция OnInit().

В других случаях, при наличии ошибки, это значение будет получено из функций, где это предполагается, и которая будет вызвана автоматически. А если пользователь просто удалит робота с графика торгового инструмента, то это будет отражено в журнале соответствующим текстовым сообщением, и обычно это соответствует значению формального параметра 0. Помимо указанного случая, функция OnDeinit() вызывается однократно и автоматически при первом удалении робота с графика торгового инструмента, при изменении входящих настроек, при переключении на другой торговый счет и при переходе на другой таймфрейм.

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

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

Кстати, если вы использовали функцию "Коммент", то функцию OnChartEvent() можно прописать такую команду. Это единственный известный мне способ избавиться от комментария на графике без изменения шаблона или перезапуска всего терминала. Когда этот комментарий перестал быть нужным, можно использовать эту функцию для его удаления.

Хитрый комментарий в МТ5 вообще в роботах OnChartEvent() может быть востребован. Они часто используются. В индикаторах использовать его строго рекомендуется. Но сейчас не о них речь, с OnChartEvent() закончили.

Пора идти дальше. Если функция OnChartEvent() не вернула 0 или значение не равно 0, то в работу вступает функция OnTick(). Это главная функция программы, именно с ее вызова начинается фактическое выполнение самой программы. А завершение этой функции без ошибок говорит о том, что программа выполнена успешно.

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

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

Из этой же причины нет смысла обновлять запрос после каждой неудачной попытки. Новых данных не будет, пока не завершится функция OnTick(). Так что не получилось 5-10-100 раз запросам прерывайте отправку и при запуске OnTick() в процессе. Я покажу, как это организовать.

Возможно, вы хотели войти в рынок, а уже пора выходить. Такое вполне может произойти. Привыкайте к каким-то важным новостям.

Функция OnTick() имеет тип void, то есть возвращаемого значения у нее нет. Как нет и формальных параметров. В этой функции пишется весь код вашей программы. А если вы используете функции из OnChartEvent(), они будут вызываться именно из функций OnTick().

Обычно я пишу торговую логику робота, а вспомогательные действия выношу в отдельные функции, которые либо включаю из другого файла через include, либо определяю за пределами функции OnTick(). Собственно, вот и все с обязательным минимумом торговых роботов разобрались.

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

А на данный момент, все не забывайте про палец вверх, комментарий, подписку на канал и позвонить в колокол, если хотите помочь развитию канала. Всем пока!

MQL5 Первый робот #1 Начало
MQL5 Первый робот #1 Начало
  • 2021.12.19
  • www.youtube.com
В этом видео-уроке приступаем к написанию торгового робота. Вкратце рассмотрим процесс создания, а после внимательно разберемся с заранее определенными и обя...
 

MQL5 Первый робот #2 Формализация идеи


MQL5 Первый робот #2 Формализация идеи

Всем привет! Итак, заготовка под робота есть, но даже идей для него нет. Вот идея, которую мы сегодня проработаем, и заключается она в довольно простом на первый взгляд алгоритме: если идут три свечи одного цвета подряд, то можно ожидать отката и нужно ловить вход. Мы можем назвать это алгоритмом "Тройная свеча".

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

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

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

Такой же сигнал на продажу выглядит, но в обратном направлении. При растущих свечах подряд стоп-лосс ставится на самый высокий хай сигнальных свечей, и также с фильтром. На открытие первой свечи в конфигурации стоп-лосс ставится вход.

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

Что касается правил выхода, то после закрытия очередной свечи, если по позиции есть прибыль, закрываем позицию. Ну или ставим приказом стоп. По таким правилам получается не очень большие профиты, но может выстрелить и тейк-профит.

Так что в этом видео мы сформализовали алгоритм и определили основные настройки для его реализации. В следующем уроке мы займемся механизмом определения новой свечи и связанными с этим процессом особенностями.

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

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

MQL5 Первый робот #2 Формализация идеи
MQL5 Первый робот #2 Формализация идеи
  • 2021.12.22
  • www.youtube.com
Вторая часть из серии создания первого робота в MQL5. Описание и формализация торговой идеи, а также рассуждения насчет её - идеи - потенциала.Уголок компете...
 

MQL5 Первый робот #3 Настройки и определение новой свечи


MQL5 Первый робот #3 Настройки и определение новой свечи

Всем привет! Продолжаем написание первого робота. Сегодня оформим входящие настройки и определение новой свечи.

Начнем с внешних переменных, которые уже знакомы нам из предыдущего видео. Всего у нас 4 переменные: идентификатор робота, объем входа, фильтр для уровня 100 поинтов и допустимое проскальзывание. Компилируем код и идем дальше.

Теперь нам понадобится еще одна глобальная переменная, которую назовем "т". Это переменная типа datetime и будет использоваться для определения новой свечи. Изначально она будет инициализирована значением 0 часов 0 минут 1 января 1970 года. Переменная "т" будет участвовать в проверке на новый бар, то есть на новую свечу.

Чтобы проверка на новый бар была корректной, я использую ключевое слово "static" для глобальной переменной "т". В MQL5 оно не имеет особого смысла, но в коде на C++ это позволяет объявить локальную переменную, которая сохраняет свое значение на протяжении всего времени работы программы и доступна только в том файле, где объявлена. Таким образом, избегается возможная путаница с глобальными переменными с одинаковыми именами в разных файлах программы.

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

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

Если условие выполнено и нужно продолжить, то присваиваем переменной "т" новое значение, которое возвращает функция "Time". Таким образом, у нас всегда будет контрольное значение нового бара.

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

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

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

Второй аргумент функции "Antique" отвечает за период графика или таймфрейм. Это значение имеет тип int, но разработчики MQL5 любезно предоставили нам встроенное перечисление с предопределенными таймфреймами. Например, период "PERIOD_CURRENT" соответствует таймфрейму графика, на котором запущена программа. Мы также можем использовать информацию из других периодов, что может пригодиться для определенных торговых стратегий.

Третий аргумент функции также имеет тип int и отвечает за конкретную свечу на графике. Все бары на графике пронумерованы, и их нумерация идет аналогично массиву "time". Текущая не закрытая свеча имеет индекс 0, закрытая перед текущей - индекс 1, и так далее. Для истории торговли, загруженной в терминал, индексация также идет по порядку.

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

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

На практике функция проверяет значение переменной "т" на соответствие времени открытия текущей свечи. Если это условие выполняется, переменной "т" присваивается значение времени открытия текущей свечи. Когда появляется новая свеча, ей присваивается индекс 0, и переменная "т" сохраняет свое значение. Каждый раз при появлении новой свечи происходит такая проверка и обновление значения переменной "т".

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

MQL5 Первый робот #3 Настройки и определение новой свечи
MQL5 Первый робот #3 Настройки и определение новой свечи
  • 2021.12.30
  • www.youtube.com
Продолжаем обучаться MQL5 на примере написания робота. Готовим входящие настройки, включаем файл и, раз уж дело идет к Новому году, то и прописываем реализац...
 

MQL5 Первый робот #4 Поиск позиций


MQL5 Первый робот #4 Поиск позиций

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

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

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

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

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

Тут на помощь приходит тот факт, что все позиции в терминале имеют индексацию, аналогичную массивам, то есть от нуля и до значения всего позиции минус один. Если на счете всего 8 позиций, то их индексы будут от 0 до 7 включительно. Общее количество позиций на счете возвращает функция "PositionsTotal()". Аргументов при ее вызове, как видите, не требуется.

Условия цикла, в котором мы перебираем позиции, ничем не отличаются от условий цикла, в котором перебираются массивы. Чтобы получить "ticket" позиции, нужно вызвать функцию "PositionGetTicket()", в качестве аргумента передав число типа int, которое и должно быть индексом искомой позиции.

Для работы с выбранной позицией используется ее уникальный идентификатор или ticket. Для выбора позиции по тикету используется функция "PositionGetInteger(POSITION_MAGIC)".

Осталось только сравнить сохраненные свойства выбранной позиции с значениями параметров функции "CountPositions()". Для этого можно добавить еще один параметр, который будет отвечать за направление искомых позиций.

Можно использовать перегрузку функции, чтобы задать направление позиций, и при вызове функции указывать одно из значений перечисления "Direction". Также можно использовать еще два варианта перегрузки функции для подсчета всех позиций робота или всех позиций на торговом инструменте без учета их принадлежности к роботам или пользователям.

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

MQL5 Первый робот #4 Поиск позиций
MQL5 Первый робот #4 Поиск позиций
  • 2022.01.15
  • www.youtube.com
Продолжаем изучать MQL5 на примере написания робота. В этом видео рассмотрим такой важный момент, как поиск роботом позиций, которые он открывал ранее и за к...
 

MQL5 Первый робот #5 Торговый сигнал


MQL5 Первый робот #5 Торговый сигнал

Продолжаем изучать MQL5 на примере написания торгового эксперта. В этом видео-уроке научим нашего робота определять момент входа в рынок. Или определять торговый сигнал по заданной ему торговой стратегии.

MQL5 Первый робот #5 Торговый сигнал
MQL5 Первый робот #5 Торговый сигнал
  • 2022.01.18
  • www.youtube.com
Продолжаем изучать MQL5 на примере написания торгового эксперта. В этом видео-уроке научим нашего робота определять момент входа в рынок. Или определять тор...
Причина обращения: