Препроцессор в MQL4: улучшаем читаемость кода

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

С помощью препроцессора мы можем:

Объявление свойств программы с помощью #property

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

//+------------------------------------------------------------------+
//|                                                        Test1.mq4 |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
      Alert("Привет, мир!");
 
  }
//+------------------------------------------------------------------+

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

//copyright является указанием автора или компании, которая является правообладателем программы
#property copyright "Александр Паркер"
 
//link используется для указания url адреса
#property link      "https://traderblog.net/"
 
//version указывает версию программы
#property version   "2.00"
 
//description - это описание, оно также может быть многострочным, когда используются подряд несколько #property description
#property description "Это тестовый советник"
#property description "Здесь можно добавить дополнительное описание"
 
//Указание strict необходимо для обеспечения совместимости с кодом, созданным для MetaTrader до сборки 600. Данный режим указывает компилятору на применение особого строгого режима проверки ошибок.
#property strict
 
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
 
void OnDeinit(const int reason)
  {
  }
 
void OnTick()
  {
  }

Попробуем запустить наш советник:

препроцессор свойства property

Помните, что во включаемых файлах свойства полностью игнорируются. Свойства учитываются только в файлах mq4.

Импортирование файлов в программу

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

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

Есть два способа использования #include: вы можете использовать #include «имя_файла» или #include <имя_файла>. Разница между ними заключается в расположении файла:

  • #include «file_name» требует, чтобы файл включения .mqh находился в той же папке, что и исходный файл .mq4.
  • #include <имя_файла> требует, чтобы файл включения .mqh находился в папке включаемых файлов по умолчанию без учета текущего каталога, обычно это каталог терминала \MQL4\Include.

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

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

Для начала создадим файл Demo-1.mqh, который будет размещаться в каталоге /Include:

//Мы определяем функцию SayHello без аргументов и без возвращаемого значения
void SayHello()
{
   Print("Привет!");
}
 
//Мы вводим функцию CalculateSum, который возвращает сумму трех заданных параметров типа int
int CalculateSum(int a, int b, int c)
{
   int s=a+b+c;
   return s;
}

Теперь наш скрипт:

//+------------------------------------------------------------------+
//|                                                        Test1.mq4 |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//Мы должны включить файл Demo-1.mqh, если мы хотим использовать функции SayHello и CalculateSum
#include <Demo-1.mqh>
 
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   //Теперь мы можем использовать функции SayHello и CalculateSum
   SayHello();
   Print(CalculateSum(1,2,3));  
}

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

Импортировать функции

Иногда функция, которую вам нужно использовать, уже скомпилирована в другом файле. Вы можете импортировать функции непосредственно в проект, используя директиву #import.

Импорт функций может происходить из файлов MQL4 (файлы *.ex4) и из модулей операционной системы (файлы *.dll).

Вот синтаксис для директивы #import:

    #import "library.ex4"
      double MyImportedFunction();
    #import

В этом примере мы импортируем функцию library.ex4. Мы импортируем функцию типа double, которая называется MyImportedFunction(). Идентификатор функции должен совпадать с именем функции в файле исходной библиотеки. Обратите внимание на точку с запятой в конце объявления функции.

Использовать директиву #define

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

    #define MYCONSTANT "Это константа"

В этом примере мы можем использовать постоянный идентификатор MYCONSTANT вместо текстовой строки в нашем коде.

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