Русский

Справочник MQL4 Обновленный MQL4

Что нового в MQL4

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

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

Для этого мы разработали единый компилятор, который автоматически поддерживает оба языка MQL4 и MQL5. MetaEditor тоже становится единым для обеих платформ MetaTrader 4 и MetaTrader 5. С его помощью можно компилировать как MQL4, так и MQL5 из любой версии. Для работы также сразу становится доступным и MQL5 Storage.

Защита MQL4-программ поднимается на один уровень с MQL5, в новых EX4/EX5-файлах очень серьезная и полностью переработанная защита по сравнению со старым EX4. А это значит, что для MetaTrader 4 становится доступным и Маркет защищенных приложений на EX4.

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

Изменения в языке MQL4

Добавлены новые типы данных char, short, long, uchar, ushort, uint, ulong и double. Это позволит легко переносить коды из других C++ подобных языков. Данные разного типа обрабатываются с разной скоростью. Целочисленные данные обрабатываются быстрее всего. Для обработки данных двойной точности используется специальный сопроцессор. Однако из-за сложности внутреннего представления данных с плавающей точкой они обрабатывается дольше, чем целочисленные. Введена операция приведения типов.

Строки теперь представлены в формате Unicode, раньше они были в формате ANSI (однобайтовые). Это необходимо учитывать, если программа использует DLL и передает в них строковые переменные.

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

Добавлены структуры и классы, указатели объектов, тип void и ключевое слово this для получения объектом ссылки на самого себя. Поддерживаются все стандарты объектно-ориентированного программирования:

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

Предопределенные функции init(), deinit() и start() остались для совместимости, но вместо них теперь можно использовать OnInit(), OnDeinit(), OnStart(), OnCalculate(), OnTick(). Кроме того, добавились новые предопределенные функции-обработчики OnTimer(), OnChartEvent(), OnTester(). В старом MQL4 предопределенные функции могли иметь любые параметры и любой тип возврата, вызов этих функций осуществлялся не по сигнатуре, а по имени. В новом MQL4 все предопределенные функции должны точно соответствовать своим сигнатурам, то есть иметь четко определенный состав параметров и тип возврата.

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

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

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

  if(condition1 && condition2)
    {
     // некоторый блок операций
    }

Если выражение condition1 окажется равным false, то вычисление выражения condition2 проводиться уже не будет, так как результат false && true все равно будет равен false.

 

Изменилось поведение функции ArrayCopyRates() — в старой версии MQL4 эта функция производила копирование ценовых серий в массив double[][6]. Теперь для получения таймсерий необходимо использовать массив из элементов структуры MqlRates:

//--- Структура для хранения информации о ценах, объемах и спреде.
struct MqlRates
  {
   datetime time;         // время начала периода
   double   open;         // цена открытия
   double   high;         // наивысшая цена за период
   double   low;          // наименьшая цена за период
   double   close;        // цена закрытия
   long     tick_volume;  // тиковый объем
   int      spread;       // спред
   long     real_volume;  // биржевой объем
  };

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

  int  ArrayCopyRates(
   MqlRates&  rates_array[],   // массив MqlRates, переданный по ссылке
   string     symbol=NULL,     // инструмент
   int        timeframe=0      // таймфрейм
   );

Для совместимости со старыми MQL4 программами сохранился и старый формат вызова, но теперь производится реальное копирование данных в массив типа double.

int  ArrayCopyRates(
   void&     dest_array[][],    // массив, переданный по ссылке
   string    symbol=NULL,       // инструмент
   int       timeframe=0        // таймфрейм
   );

Это означает, что при изменении значений в таймсерии (добавлении новых баров, перестройке, обновлении цены Close последнего бара), необходимо заново скопировать нужные данные в массив dest_array[][]. При этом массив-приемник будет автоматически распределен под требуемое количество копируемых баров, даже если он был объявлен статически.

 

Изменился формат хранения исторических данных RateInfo. В старой версии состав структуры RateInfo был представлен таким образом:

struct RateInfo
  {
   unsigned int      ctm;   // дата открытия бара
   double            open;  // цена открытия
   double            low;   // минимальная цена бара
   double            high // максимальная цена бара
   double            close// цена закрытия
   double            vol;   // объем
  };

В новом формате в структура RateInfo добавлены поля для хранения спреда и торгового объема:

//--- Стандартное представление котировки в новой версии терминала
struct RateInfo
  {
   INT64             ctm;               // дата и время открытия
   double            open;              // цена открытия (абсолютное значение)
   double            high;              // минимальная цена бара
   double            low;               // максимальная цена бара
   double            close;             // цена закрытия
   UINT64            vol;               // тиковый объём
   INT32             spread;            // спред
   UINT64            real;              // торговый объём
  };

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

Старые EX4 программы и DLL, основанные на старом формате RateInfo, работать в новом терминале не будут. Требуется приведение к новому формату.

 

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

Для функций FileWrite(), FileWriteArray(), FileWriteDouble(), FileWriteInteger() и FileWriteString() изменен тип возвращаемого значения с int на uint. Данные функции возвращают количество записанных байт или 0 в случае ошибки (в старой версии MQL4 в случае ошибки возвращалось отрицательное число).

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

Следует иметь ввиду, что преобразование типа datetime в строку теперь зависит от режима компиляции:

  datetime date=D'2014.03.05 15:46:58';
  string str="mydate="+date;
//--- str="mydate=1394034418" - старый компилятор, новый компилятор без директивы #property strict
//--- str="mydate=2014.03.05 15:46:58" - новый компилятор с директивой #property strict

Ниже в таблице перечислены все различия между старым MQL4, новым MQL4 без использования strict и новым MQL4 с указанием строгого режима компиляции:

#property strict

При компиляции библиотек в режиме strict для каждой экспортируемой функции необходимо добавлять модификатор export. в противном случае функция не будет доступна извне.

Таблица отличий между компиляторами:

Старый компилятор MQL4

Новый компилятор MQL4

Новый компилятор MQL4 с #property strict

Точки входа init(), start(), deinit() могут иметь любые параметры и любой тип возврата

init(), start(), deinit(), оставленные для совместимости,

и новые OnInit(), OnStart(), OnCalculate(), OnTick(), OnTimer(), OnChartEvent(), OnTester(), OnDeinit() должны точно соответствовать своим сигнатурам

То же

Результат возврата из функции init() никак не анализируется исполняющей подсистемой

Результат возврата из функций init() и OnInit() никак не анализируется исполняющей подсистемой

При возврате из OnInit() ненулевого значения выполнение эксперта или индикатора прекращается, программа выгружается

Имена переменных практически любые (кроме зарезервированных слов), включая спецсимволы и точки

Имена переменных не могут иметь спецсимволы и точки.

Список зарезервированных слов расширен, поэтому именами не могут быть такие широко распространенные слова, как short, long, const и т.д.

То же

Область видимости переменной - от объявления (даже во вложенном блоке) до конца функции

То же

Область видимости переменной - от объявления до конца блока, в котором переменная объявлена

Неявная инициализация всех переменных (и глобальных и локальных) нулями

То же

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

Локальные массивы при выходе из функции не освобождаются

Локальные массивы освобождаются при выходе из функции

Локальные массивы освобождаются при выходе из блока {}

Ошибка "Array out of range" (индекс за пределами массива) не приводит к критической ошибке*

То же. Кроме массивов структур и классов, для которых эта ошибка является критической

"Array out of range" - критическая ошибка и приводит к остановке программы

Структур и классов нет

Структуры и классы есть. Появились дополнительные типы данных

То же

Строки - однобайтовые.

datetime - 32-битное целое

Предопределенная переменная Volume имеет тип double

Строки - юникодные.

datetime - 64-битное целое

Предопределенная переменная Volume имеет тип long

То же

ArrayCopyRates() производит виртуальное копирование в массив double[][6]

ArrayCopyRates() производит виртуальное копирование в массив MqlRates[]. Для совместимости осталось копирование в массив double[][6], но это копирование не виртуальное, а реальное.

То же

Функции могут не возвращать значения, даже если они имеют тип. Для этого в конце функции компилятором автоматически проставляется return(0)

То же

Функции любого типа всегда должны возвращать значение

Количество одновременно открытых файлов - 32

Количество одновременно открытых файлов - 64

То же

Файлы всегда открываются в режиме совместного использования **

Режим совместного использования нужно указывать явно с помощью FILE_SHARE_READ и/или FILE_SHARE_WRITE

То же

Для скриптов в окне входных параметров показываются имена extern переменных

Для скриптов в режиме show_inputs в окне входных параметров показываются имена extern и input-переменных

Для скриптов в режиме show_inputs в окне входных параметров показываются строчные комментарии вместо имен extern- и input-переменных

* Следует обратить особое внимание на ошибку "Array out of range" - многие старые пользовательские индикаторы при запуске на графике будут выдавать эту ошибку в новом компиляторе в режиме strict. Желательно найти причину и устранить её.

**  В новом MQL4 и MQL5 за режим совместного использования файлов отвечают флаги FILE_SHARE_READ и FILE_SHARE_WRITE, которых не было в старом MQL4.

 

Изменения в файловой структуре

В предыдущих билдах клиентского терминала MetaTrader 4 (509 и ниже) все MQL4 программы хранились в корневой папке <каталог_установки_терминала>\experts\ в следующих подпапках:

  • \experts - эксперты (торговые роботы),
  • \experts\indicators - пользовательские индикаторы,
  • \experts\scripts -  скрипты (программы на MQL4 для однократного выполнения на графике),
  • \include - включаемые в другие программы файлы исходного кода с расширением MQH и MQ4,
  • \libraries - библиотеки в виде исходного кода MQ4 и скомпилированные из них исполняемые файлы EX4, для динамического вызова собранных в них функций другими MQL4-программами,
  • \files - специальная "файловая песочница", только в пределах этой папки MQL4 программам разрешается  выполнять файловые операции.

 
В новой версии MQL4 файловая структура для хранения исходных кодов изменилась. Теперь все программы на MQL4 должны находиться в папке <каталог_данных>\MQL4\ во вложенных соответствующих папках:

  • \Experts - эксперты (торговые роботы),
  • \Indicators - пользовательские индикаторы,
  • \Scripts - скрипты (программы на MQL4 для однократного выполнения на графике),
  • \Include - включаемые в другие программы файлы исходного кода с расширением MQH и MQ4,
  • \Libraries - библиотеки в виде исходного кода MQ4 и скомпилированные из них исполняемые файлы EX4, для динамического вызова собранных в них функций другими MQL4-программами,
  • \Images - файлы картинок для использования в ресурсах,
  • \Files - специальная "файловая песочница", только в пределах этой папки MQL4 программам разрешается  выполнять файловые операции.

При обновлении терминала MetaTrader 4 с 509 билда на новую версию все файлы MQ4, MQH и EX4 из стандартных корневых папок старого местоположения автоматически копируются и раскладываются в соответствующие папки. Дополнительно созданные пользователем внутри стандартных папок дочерние папки с файлами никак не обрабатываются, их необходимо самостоятельно скопировать в новое место, если они необходимы.
 

Никакие файлы или папки при обновлении не удаляются! Все операции по копированию файлов при обновлении записываются в Журнал терминала с указанием подробных путей.

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

Возможно, в некоторых случаях в исходных файлах потребуется  исправить пути в #include для включаемых файлов (если относительные пути изменились).  Важно запомнить, что сейчас корневой папкой для редактора MetaEditor является папка <каталог_данных>\MQL4\, все программы должны находиться в правильных дочерних подпапках.

Найти каталог данных (<каталог_данных>) на компьютере для каждой копии установленного терминала MetaTrader 4 можно из меню терминала или редакторе MetaEditor: "Файл" - "Открыть каталог данных".