MQL4: Разбор базовых функциональных блоков кода советника

Содержание статьи: (кликните, чтобы перейти к соответствующей части статьи):

Базовые функциональные блоки MQL4

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

В базовом коде MQL4, который мы с Вами создали в предыдущей статье, имеется 5 блоков:

Основные блоки MQL4 кода

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

Базовые блоки MQL4

Справочная информация и объявление переменных

Первый блок — так называемая «Шапка». Данная «Шапка» нужна для двух моментов:

Входящие переменные в советнике

Данные переменные объявляются в нашем советнике в «шапке» после справочной информации. Так мы можем объявить какую-либо переменную в нашем советнике.

Объявление переменных в шапке MQL кода

Функция void OnTick ()

Мы с Вами разобрали первый блок. Далее у нас идет 4 основных блока. Разбирать мы их будет не по порядку, а начнем с 4 блока «void OnTick ()».

Функция OnTick

Основная задача данной функции — это выполняться циклично с приходом каждого тика.

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

Алгоритм торговой стратегии на MQL4

Имеется цена BID. Каждый приход новой цены это и есть — тик. Как новый тик поступает, так процесс выполняется от начала до конца. Процесс выполнился, и советник ждет прихода нового тика. Новый тик пришел — процесс запустился вновь, прошел до конца — закончился.

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

Посмотрим, как это выглядит в самом MQL4 коде:

Имя функции OnTick и ее тело

OnTick() – это название функции. Фигурные скобки <> – это тело функции, где мы будем прописывать весь программный код, который должен выполняться с приходом каждого тика, в рамках функции OnTick().

Функция void OnTimer ()

Идем далее. 5 блок, функция void OnTimer ().

Функция OnTimer

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

Две вышеописанные функции OnTick() и OnTimer() — это, так называемые, «моторчики», которые работают циклично и позволяют выполнять работу наших советников во времени.

Функции OnInit () и OnDeinit ()

Теперь давайте рассмотрим 2 и 3 блоки — две функции: OnInit () и OnDeinit ().

Функции OnInit и OnDeinit

Основное отличие этих двух блоков от OnTick() и OnTimer() — это в том, что OnInit () и OnDeinit () выполняются только один раз.

Функция OnInit () выполняется один раз при загрузке советника — она выполняется самая первая (иначе этот процесс называется инициализация)

Иначе говоря, OnInit () выполняется только один раз при загрузке советника на наш график. Например, если мы поставим советник MACD Sample на график в MetaTrader4 и первое, что произойдет в советнике — это выполнится функция OnInit ().

Функция OnDeinit () похожа на OnInit (), она также выполняется только один раз, но уже при удалении советника.

Для чего нужны данные функции? Ранее мы разбирали для чего нужны void OnTick () и void OnTimer () — они нужны для того, чтобы процессы проходили с некой цикличностью. Зачем же нужно выполнять разовые функции?

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

Например, есть у нас функция OnTimer (), которая работает по заданному нами таймеру. А вот сам таймер мы и задаем один раз в функции в OnInit ().

Задаем таймер функции OnTimer

На скриншоте мы видим саму функцию OnInit () и, прописанную в ней, непосредственно, настройку таймера – EventSetTimer(60);

В данном случае прописано, что таймер работает по секундам с длительностью 60 секунд. Если мы поставим единицу, то таймер будет работать с длительностью одна секунда, то есть, через каждую секунду будет запускаться OnTime ().

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

Теперь перейдем к функции OnDeinit (). Она выполняется, как я уже указывал выше, также один раз, но при удалении советника. Зачем она нужна? Затем чтобы выполнить какие-либо операции один раз и в конце работы нашего советника.

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

Очень просто — мы можем код удаления графических элементов прописать в функции OnDeinit (), которая выполняется один раз при удалении советника с графика.

В итоге получается, что когда мы удаляем советник с графика, самой последней выполнится OnDeinit (), которая воспроизводится один раз при удалении советника с графика. Тогда, при удалении советника все графические элементы будут также удалены.

Итак, резюмируемся. В составе нашего кода имеется пять основных блоков:

Блок «Шапка» — он нужен для того, чтобы прописать какую-то справочную информацию и объявить переменные.

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

Третий блок — это функция OnDeinit(). Она также работает один раз, но самой последней при удалении советника с графика.

Функция OnTick() — нужна для того, чтобы код, прописанный внутри этой функции, выполнялся циклически с приходом каждого тика.

Функция OnTimer — нужна для того, чтобы код, прописанный внутри этой функции, выполнялся циклично по нашему заданному таймеру.

Это, так называемая, основная структура кода MQL.

Дополнительные пользовательские функции в MQL4

Ниже всех этих 5 блоков мы можем также прописать свои какие-либо дополнительные функциональные блоки. Например, есть функция OnInit (), есть OnDeinit (), есть функция OnTick (), есть OnTimer() и есть еще какая-либо наша собственная функция A(), которую мы сами придумали и сами написали.

Пользовательские функции в MQL4

В <> фигурных скобках находится тело нашей функции A(). Мы прописали там какой-то код и эта функция для чего-то нам нужна.

Нашу собственную функцию мы можем вызывать: либо с приходом каждого тика (вызов внутри OnTick), либо по таймеру (вызов внутри OnTimer), либо один раз при инициализации советника (вызов внутри OnInit).

Рассмотрим пример на основе функции OnTimer().

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

Допустим, OnTimer() будет работать циклично через каждую секунду. Внутри нее (в теле функции) мы прописали какой-то код.

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

Переменная Lot равна сумме переменных a+b. И сами эти a+b на протяжении времени как-либо меняются и, соответственно, переменная Lot также будет меняться.

Рассмотрим ситуацию: пришла первая секунда – начал выполняться код, расположенный в OnTimer().

Далее, компьютер видит вызов нашей функции A (). Если он видит вызов функции, то он идет к ней. Нашел функцию A (), выполнил все то, что прописано в теле данной функции (а там прописано вычисление переменной Lot). Он все это вычислил, закончил функцию А().

Далее, компьютер вновь возвращается в OnTimer() в то место, где он ее покинул и переходит к следующей команде OrderSend (). Скажу наперед, что OrderSend() — это настоящая команда по открытию ордеров, внутри нее перечисляются какие-либо параметры открытия ордеров и, в том числе, Lot нашего ордера.

Перед тем, как запустится команда OrderSend(), компьютер дошел до вызова нашей функции, вычислил все, что там есть, а именно, переменную Lot, вернулся и начал выполнять команду OrderaSend(), внутри которой уже есть, вычисленная ранее нашей функцией, переменная Lot.

И компьютер открывает ордер именно с этим лотом, размер которого был рассчитан в нашей собственной функции A().

Все операции на первой секунде закончены, ждем наступления следующей секунды. Вторая секунда пришла – вновь выполнились все команды в OnTimer(), опять компьютер видит вызов нашей функции A(), переходит к ней, вычисляет переменную Lot, возвращается в OnTimer(), переходит к следующей команде OrderSend() и производит выполнение команды OrderSend() с новым значение лота.

Этим я хотел показать то, что есть основные блоки и есть дополнительные блоки, которые мы можем писать сами. Чтобы дополнительные блоки начали работать, их нужно вызывать из основных блоков. И делать это мы можем из основных функций: либо из тех, которые работают только один раз (OnInit, OnDeInit), либо из тех, что работают циклично (OnTick, OnTimer).

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

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

На этом все, переходите к следующей статье, где мы с Вами рассмотрим комментарии в программировании на MQL4.

Благодарю за внимание.

Другие статьи по теме Программирование на MQL4 Вы можете просмотреть в данном содержании практических уроков по MQL.

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

Ordersend error 130 как исправить

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

Коды ошибок

GetLastError() — функция, возвращающая коды ошибок. Кодовые константы ошибок определены в файле stderror. mqh. Для вывода текстовых сообщений следует использовать функцию ErrorDescription(), определенную в файле stdlib. mqh.

Коды ошибок, возвращаемые торговым сервером или клиентским терминалом:

Значение Описание
Нет ошибки
1 Нет ошибки, но результат неизвестен
2 Общая ошибка
3 Неправильные параметры
4 Торговый сервер занят
5 Старая версия клиентского терминала
6 Нет связи с торговым сервером
7 Недостаточно прав
8 Слишком частые запросы
9 Недопустимая операция нарушающая функционирование сервера
64 Счет заблокирован
65 Неправильный номер счета
128 Истек срок ожидания совершения сделки
129 Неправильная цена
130 Неправильные стопы
131 Неправильный объем
132 Рынок закрыт
133 Торговля запрещена
134 Недостаточно денег для совершения операции
135 Цена изменилась
136 Нет цен
137 Брокер занят
138 Новые цены
139 Ордер заблокирован и уже обрабатывается
140 Разрешена только покупка
141 Слишком много запросов
145 Модификация запрещена, так как ордер слишком близок к рынку
146 Подсистема торговли занята
147 Использование даты истечения ордера запрещено брокером
148 Количество открытых и отложенных ордеров достигло предела, установленного брокером.

Коды ошибок выполнения MQL4 программы:

GetLastError() — функция, возвращающая коды ошибок. Кодовые константы ошибок определены в файле stderror. mqh. Для вывода текстовых сообщений следует использовать функцию ErrorDescription(), определенную в файле stdlib. mqh.

Коды ошибок, возвращаемые торговым сервером или клиентским терминалом:

Я пытаюсь вставить takeprofit и stoploss аргумент в моей SendOrder() функции, но я получаю следующее сообщение об ошибке:

A) Полностью соответствуют MQL4 OrderSend() требованиям синтаксиса

B) Ошибка 130: == "недействительная остановка"

Вы должны проверить с вашим брокером несколько деталей:

C) Хорошая практика не назначать в extern итераторных-переменных

Источники:

https://sgr-tradeinvest. ru/mql4/bazovie-bloki-koda-sovetnika. html

https://teh-fed. ru/ordersend-error-130-kak-ispravit/

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: