Содержание
Здравствуйте. Отвлечемся от работы внутри тела функций и поговорим о препроцессорах и свойствах, которые задаются в главном mq4 файле до начала объявления самих функций.
Свойства программ #property
Начальные свойства программ (property) мы разбирали в скрипте на одном из первых уроков. Свойства задаются один раз для всей программы, будь то скрипт, индикатор или советник. Мы рассмотрели свойства: copyright, link, version, strict, description. Давайте пополним нашу базу знаний:
- icon — возможность заменить стандартную иконку в окне «о программе» на пользовательскую, формата .ico. В свойстве указывается путь к файлу в корне терминала. Как правило, все изображения хранятся в папке «Images«.
0 |
#property icon "\\Images\\NH.ico" |
- indicator_chart_window — отображать индикатор в окне графика. Как известно, индикаторы в Meta Trader 4 делятся на два вида: отображающиеся непосредственно на графике, будь то информационные панели, стандартные индикаторы Moving Average, Bollinger Bands и т.д., а также индикаторы в отдельном окне. Данное свойство назначает индикатору текущее окно валютной пары.
- indicator_separate_window — свойство вывода индикатора в отдельное окно. На сленге мы его называем «подвальным индикатором». В нем отображаются разнообразные осцилляторы, можно рисовать гистограммы, линии доходности, спреда и т.п.
- indicator_height — свойство для отдельного индикатора, которое определяет фиксированную высоту этого окна в пикселях, если это необходимо.
- indicator_minimum, indicator_maximum — ограничение минимального и максимального значения шкалы подвального индикатора. К примеру для Стохастика эти значения равны 0 и 100, программный код индикатора просто не позволит выйти за эти пределы, поэтому можно сразу указать их фиксированными.
- indicator_buffers — количества буферов, необходимых для расчета индикатора. Если вы используете расчет данных индикатора с помощью массивов, то для построения линий или гистограмм нужно использовать буферы, которые будут хранить в себе значение данных на каждой свече. Посмотреть назначенные буферы можно в «Окне Данных», включив его через меню «Вид», либо нажав Ctrl+D. К примеру для индикатора RSI нужен только один буфер, ведь он отображает только одну линию. Для Стохастика уже два, ведь в расчете участвуют основная и сигнальная линии.
- indicator_levelN — свойство, которое отображает заданную горизонтальную линию в отдельном окне индикатора. Используется, когда вы хотите указать для осциллятора уровни перекупленности и перепроданности. Стоит заменить, что это и многие другие свойства можно задать и в функции OnInit() с помощью дополнительных функций IndicatorSetInteger или IndicatorSetDouble.
- indicator_colorN — цвет для отображения линий индикатора. Может работать только, если у индикатора есть заданный буфер.
Конечно, есть и другие, второстепенные свойства, но с ними нужно знакомиться уже на практике.
Макроподстановка #define, #undef
Define — обозначает «определять». Данная директива используется при присвоении имен выражениям. Объявляется #define в самом начале программного кода до работы с функциями обработки событий. По своему принципу работы очень напоминает объявление переменной и указание ей значения. Рассмотрим беспараметрическую форму:
0 |
#define NUMBER 999 |
Мы объявили вхождение NUMBER и присвоили ему значение 999. Теперь в программном коде можно указывать слово NUMBER, которое будет выдавать нам заданное значение.
Допустим нам нужно объявить версию скрипта и потом выдать ее в значение свойства программы version, а также в коммент в функции:
0 1 2 3 4 5 6 |
#define VER "1.02" #property version VER void OnStart() { Comment("Версия программы: ",VER); } |
Версия программы это текстовая переменная, поэтому указываем ее в кавычках. Далее после того, как VER задали, ее просто прописываем в version вместо цифр, как обычно. Теперь при выводе информации в левый верхний угол экрана мы будем видеть текущую версию программы.
Другой пример, мы знаем, что при работе с типом ордеров, нулем обозначается ордер на покупку, а 1 — на продажу. Чтобы не смущать себя единицами и нулями, просто объявим вхождения BUY и SELL, т.к. они не заняты программными константами.
0 1 2 3 4 5 6 7 |
#define BUY 0 #define SELL 1 void OnStart() { if(OrderType() == BUY) Print("Ордер по покупку"); else if(OrderType() == SELL) Print("Ордер по продажу"); } |
Понятно, что сейчас ордер у нас еще не выбран, поэтому данное выражение не совсем рабочее, но как пример сгодится.
Я часто использую данную директиву в работе со статическими массивами, когда точно знаю, сколько элементов они содержат, чтобы сразу видеть, какой элемент за что отвечает:
0 1 2 3 4 5 6 7 8 9 10 |
#define ORDER 0 #define SYMBOL 1 #define PROFIT 2 void OnStart() { string array[3] = { "Buy","EURUSD","12.1" }; Print(array[ORDER]); Print(array[SYMBOL]); Print(array[PROFIT]); } |
То есть вместо обычного array[0] или array[1] мы используем уже наименования, которые присвоили нулю, единице и двойке.
У данной директивы есть и более сложный вид — параметрическая форма. Лично я не нашел ей применения в моем коде, но не сказать о ней будет неправильно. Суть в том, чтобы для нескольких вхождений выполнить арифметическое действие, определенные также заранее.
0 1 2 3 4 5 6 7 8 |
#define X 10 #define Y 5 #define SUM(a,b) (a + b) void OnStart() { double sum = SUM(X,Y); Print(sum); //результат 15 } |
Формула расчета определена до начала работы с функцией. В самой функции уже подставлены объявленные значения X и Y в переменную sum. Аналогично это можно было бы представить следующим образом:
0 1 |
double sum1 = X+Y; Print(sum1); //результат 15 |
Но если у вас будет длинная формула, то тогда такие действия выше себя оправдывают. При сложных формулах необходимо указывать выражения в скобках:
0 1 2 3 4 5 6 7 8 |
#define Z 10-5 #define W 5+3 #define MULT(a,b) ((a)*(b)) void OnStart() { double mult = MULT(Z,W); Print(mult); //результат 40 } |
Директива #undef нужна для отмены директивы #define. После вызова undef, она стирается из памяти программы.
0 1 2 3 4 5 |
#define TEXT "ABC" void OnStart() { Print(TEXT); #undef TEXT } |
Включение файлов (#include)
Данная командная строка располагается также в начале программного кода, но может быть указана в любом месте. В большинстве случаев подключенные файлы относятся к файлам библиотек. Библиотеки могут уже находиться в каталоге программ, быть стандартными, либо же пользователь может подключить свои.
Попробуем для примера подключить библиотеку stderror.mqh, которая определяет имя директивы для номера ошибки.
0 1 2 3 4 5 6 |
#include void OnStart() { int error = GetLastError(); if(error == ERR_NO_ERROR) Print("Ошибок нет"); } |
В примере мы записали в переменную error номер ошибки, а далее проверили, чтобы ошибки не было, задав вместо нуля директиву ERR_NO_ERROR, которая уже определена в подключенной библиотеке. Чтобы посмотреть код данной библиотеки, нужно щелкнуть на нее барабанчиком мыши.
Самая используемая программная библиотека stdlib.mq4 создана для того, чтобы расшифровать ошибку. В примере выше мы сами писали текст ошибки, теперь подключим уже готовую библиотеку и выдадим принт:
0 1 2 3 4 5 6 7 |
#include <..\Libraries\stdlib.mq4> void OnStart() { int error = GetLastError(); string new_error = ErrorDescription(error); Print(new_error); //результат no error } |
Тут из подключенной библиотеке мы взяли функцию и внесли в нее номер ошибки. Т.к. ошибки нет, то результат принта «no error«.
Мы рассмотрели встроенные библиотеки MQL. Помимо них можно делать пользовательские наборы. Допустим вы в каждом своем советнике используете Трейлинг Стоп, либо перевод в безубыток. Чтобы не повторять строчки из кода в код, можно создать одну библиотеку с нужными функциями и вычислениями, и прикреплять ее к каждому необходимому программному коду.
Импорт функций (#import)
Импорт функций происходит посредством программы .ex4 из модулей операционной системы с разрешением .dll, либо файлов .ex4. Файлы с расширением .dll очень часто примеряются в Windows и могут быть необходимы для работы вашей программы.
К примеру, если вы хотите парсить данные через интернет без помощи функции WebRequest(), то вам потребуется wininet.dll.
0 1 2 3 4 5 6 |
#import "Wininet.dll" int InternetOpenW(string,int,string,string,int); int InternetConnectW(int,string,int,string,string,int,int,int); int InternetOpenUrlW(int,string,string,int,int,int); int InternetReadFile(int,uchar &arr[],int,int &arr[]); int InternetCloseHandle(int); #import |
Для корректного импорта указывается слово #import и в кавычках имя нужного модуля. После перечисления всех необходимых функций этого модуля импорт закрывается также словом #import.
Хотите использовать встроенный MessageBox от Windows — пожалуйста:
0 1 2 |
#import "user32.dll" int MessageBoxW(uint hWnd,string lpText,string lpCaption,uint uType); #import |
Если нужно открыть какой то интернет ресурс через программу то нужна shell32.dll.
0 1 2 |
#import "shell32.dll" int ShellExecuteW(int hwnd,string Operation,string File,string Parameters,string Directory,int ShowCmd); #import |
Примеров может быть много, в основном я использую импорт только для получения информации из интернета, как в нашем индикаторе новостей. Данные берутся из сети и потом уже обрабатываются в коде mql.
Импортировать можно и библиотеки с расширением .ex4 из каталога программы. Выше при изучении #include мы добавляли библиотеку stdlib.mq4. Если по какой-то причине у вас нет открытого кода нужной библиотеки, мы может присоединить ее через импорт:
0 1 2 |
#import "stdlib.ex4" string ErrorDescription(int error_code); #import |
Чтобы понимать, что значит каждый параметр модуля .dll, нужно разбираться в программной среде Windows. Я же не владею этой информацией, поэтому методом тыка подбирал нужный модуль, настраивал параметры. На многие вопросы можно получить ответ, задав его на официальном форуме MQL5.Community.
Хочу заметить, что я не призываю вас сразу же использовать .dll в своем коде. Для обычного скрипта это не понадобится. Просто нужно иметь в виду, что такая возможность есть.
На этой ноте можно завершить данный урок. Предположу, что он был довольно скучным, но без основ тут никуда. Думаю вам его придется потом еще раз перечитать. Повторение и еще раз повторение.
[download url=»http://www.davinci-fx.com/wp-content/uploads/2021/01/1.8-property-define-include-import.rar» title=»Скачать примеры»]