strelkaХотите изучить MQL4 быстро, легко и бесплатно?
MQL4 подробно и с самого нуля. Фишки, секреты и только практика
А также, СУПЕРБОНУС - разбор стратегии и программного MQL кода советника SGR


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


 

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

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

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

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

 

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

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

 

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

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

  • справочная информация — здесь прописано наименование советника (как мы его назвали), авторские права, сайт, версия советника (1-я, 2-я и т.д.). Также, в шапке имеется строчка-команда, нужная для того, чтобы во время компилирования MetaEditor строго проверял в коде наши ошибки. Данную строчку можно убрать, от этого ничего не изменится, разве что компилятор будет менее строго проверять ошибки в данном коде. Мы эту строчку все же оставим. Блок шапка в MQL4
  • второе назначение данной «Шапки» — это объявление переменных. То есть, в каждом советнике есть какие-либо переменные. Например, советник MACD Sample. Когда мы его переносим на график, у нас появляется окно с вкладкой «Входные параметры»: TakeProfit, Lots, TrailingStop и т.д. Все эти входные данные и являются переменными.

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

 

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

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

 

strelkaХотите изучить MQL4 быстро, легко и бесплатно?
MQL4 подробно и с самого нуля. Фишки, секреты и только практика
А также, СУПЕРБОНУС - разбор стратегии и программного MQL кода советника SGR


 

Функция 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() — это, так называемые, «моторчики», которые работают циклично и позволяют выполнять работу наших советников во времени.

 

strelkaХотите изучить MQL4 быстро, легко и бесплатно?
MQL4 подробно и с самого нуля. Фишки, секреты и только практика
А также, СУПЕРБОНУС - разбор стратегии и программного MQL кода советника SGR


 

Функции 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.

 

strelkaХотите изучить MQL4 быстро, легко и бесплатно?
MQL4 подробно и с самого нуля. Фишки, секреты и только практика
А также, СУПЕРБОНУС - разбор стратегии и программного MQL кода советника SGR


 

Дополнительные пользовательские функции в 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

 

С уважением, Антон.

Обучающий Форекс портал SanGReal Invest
 

strelkaХотите изучить MQL4 быстро, легко и бесплатно?
MQL4 подробно и с самого нуля. Фишки, секреты и только практика
А также, СУПЕРБОНУС - разбор стратегии и программного MQL кода советника SGR


 


Вам это может быть интересно. Другие статьи нашего обучающего портала:


  • Антон — SanGReal Invest (Сангрил Инвест)

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

  • Александр

    Хочу попросить посмотреть на код нижеследующего советника и подсказать мне как переделать его так , что-бы советник поддерживал баланс не одним открытым хеджирующим ордером,а открывал много противоположных. Допустим (0.1Buy+0.1Buy+0.3Buy = 0.5Sell) -это алгоритм работы советника, т.е. он одним ордером 0.5 Sell перекрывает три ордера Buy.
    А надо сделать так ; (0.1Buy+0.1Buy+0.3Buy=0.1Sell+0.1Sell+0.1Sell+0.1Sell+0.1Sell). Т.е 3 ордера Buy он перекрывает 5-ю мелкими ордерами Sell.
    Подскажите пожалуйста,что надо исправить в коде. Спасибо .extern double LockLot=0.01;

    void OnTick(void)
    {
    double LB=0,LS=0;
    int b=0,s=0;
    for (int i=0; i<OrdersTotal(); i++)
    {
    if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
    {
    if (OrderSymbol()==Symbol())
    {
    int tip = OrderType();
    if (tip==OP_BUY)
    {

    }
    if (tip==OP_SELL)
    {

    }
    }
    }
    }
    //—
    Comment(b," Buy ",DoubleToStr(LB,2)," lot",
    "n",s," Sell ",DoubleToStr(LS,2)," lot");
    //—
    if (LSLB)
    {
    if (OrderSend(Symbol(),OP_BUY,LockLot ,NormalizeDouble(Ask,Digits),100,0,0,NULL,0,0,CLR_NONE)==-1)
    Print(«Ошибка «,GetLastError(),» открытия ордера «);
    }
    }
    //——————————————————————
    int deinit()
    {
    Comment(«»);
    return(0);
    }
    //+——————————————————————+