Программирование на MQL 4: Функции
|

Программирование на MQL 4: Функции

   Статья о программировании на MQL 4 в предыдущем номере журнала Forex Magazine закончилась обещанием рассмотреть функции – нововведение языка MQL 4, отсутствовавшее в MQL II. Вообще-то, язык MQL II позволял писать пользовательские функции, которые компилировались отдельными модулями, но работа с ними имела некоторые ограничения, что не позволяло в полной мере пользоваться этим достижением структурного программирования.


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


   Как было отмечено в предыдущей статье, функции – это один из “кирпичиков” построения программ. Это касается не только языка MQL 4, это касается практически всех языков программирования. Программисты всех мастей используют функции для создания более понятных программ и более эффективного программирования. Если бы не было функций (как в MQL II), часто приходилось бы несколько раз на протяжении одной программы копировать код, выполняющий схожие действия. Такое копирование кода не только увеличивает трудоёмкость написания и отладки программы, оно так же ухудшает её читабельность. Функции во многом помогают решить эту проблему.


   Функции можно рассматривать как именованные блоки программы, которые скрывают в себе детали того или иного алгоритма. Однажды написанная и отлаженная функция может использоваться в нескольких местах программы (или даже в нескольких различных программах) без особых усилий. Они, как правило, имеют описательное название, что облегчает понимание её назначения. Хорошо написанная и документированная функция при последующем использовании не требует вникания в алгоритм её работы. Это как будто чёрный ящик, который на входе принимает какие-либо параметры, а по завершении своей работы выдаёт какой-либо результат.


   Функции в MQL 4 можно оформить двумя способами. Первый – это преемник пользовательских функций языка MQL II, оформляемый в виде отдельного модуля. В новой версии они имеют название “script”. Второй – это написание функции в том же модуле, что и основная программы для локального использования.


   Для создания Script’а достаточно запустить мастера по созданию программ в редакторе Meta Editor 4 и выбрать пункт “Script program”. Мастер проведёт вас через весь процесс создания пользовательской функции, после чего перед вами будет открыт остов кода script’а.


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


   Язык MQL 4 имеет три предопределённых функции, имена которых не следует использовать в качестве названий собственных функций, это init, deinit и start. Так же имена функций не должны начинаться с цифры. В остальном же, выбирая имя функции, программист имеет полную свободу.


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


   double SomeFunction(color LineColor, string LineName, int Range)


   В приведённом выше примере показано объявление функции SomeFunction с тремя параметрами: параметр LineColor имеет тип color, параметр LineName – тип string и параметр Range – тип int.


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


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


   1. Первый параметр указывает цвет, которым нужно выводить линию на график;
   2. Второй параметр указывает подпись, которая должна быть нанесена на график рядом с линией;
   3. Третий параметр указывает количество баров, которые будут обработаны функцией для нахождения максимальной цены закрытия;
   4. По окончании работы функция возвращает значение типа double, которое равно максимальной цене закрытия на периоде указанном в третьем параметре.


   Использовать такую функцию в коде можно будет так:


   // где-то в коде объявлена переменная типа double,
   // которая будет хранить наибольшее значение закрытия double fHighestClose;
  
   // Выполняем какие-то действия
   …
  
   // Затем для выполнения кода “спрятанного” в теле функции
   // SomeFunction нужно её вызвать.
   fHighestClose = SomeFunction(Yellow,”Line subscript”,50);


   // Теперь переменная fHighestClose содержит результат
   // выполнения функции SomeFunction


   Также, часто возвращаемое функцией значение используют для того, чтобы сообщить о корректности завершения “спрятанного” в неё алгоритма или о произошедшей в ходе её выполнения ошибке. Как это использовать, показано немного ниже.


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


   void OtherFunction(int Param1)


   Функции могут принимать множество параметров, и, как правило, только часть из них должна быть уникальной для обращений к функции из программы, а оставшаясячасть повторяется от вызова к вызову. Для облегчения использования функций, в MQL4 встроена возможность задавать значения по умолчанию для параметров функций. Это означает, что, пользуясь функцией, параметры которой уже имеют некоторые предопределённые значения, мы можем либо использовать их, либо указать свои. Для объявления таких параметров функции следует сразу же за ним, через знак равнo, указать параметр, используемый по умолчанию. Одно важное замечание – если вы указываете какое-либо значение по умолчанию для одного из параметров функции, то все параметры, стоящие в объявлении правее него, должны так же иметь значения по умолчанию. Параметры, не имеющие значений по умолчанию, называются “обязательными параметрами”. Рассмотрим пример:


   // Этот вариант объявления правильный – все параметры
   // правее Param2 имеют значения по умолчанию
   int SomeFunction1(int Param1, int Param2=10, int Param3=123)
   {
   // do something
   }
  
   // Этот вариант объявления неправильный – параметр
   // правее Param2 не имеют значения по умолчанию
   int SomeFunction2(int Param1, int Param2=10, int Param3)
   {
   // do something else
   }


   Соответственно, вызвать функцию SomeFunction1 можно было бы тремя способами, указывая значение только первого обязательного параметра; указывая первые два параметра и указывая все три параметра.


   // где-то в коде объявлена переменная типа int,
   // которая будет хранить значение, возвращаемое функцией
   // SomeFunction1
   int nSomeResult = 0;


   // Вызов SomeFunction1 с указанием только обязательного
   // параметра. Остальные параметры Param2 и Param3 будут
   // иметь значения 10 и 123 соответственно
   nSomeResult = SomeFunction1(10);


   // Вызов SomeFunction1 с указанием двух параметров.
   // Параметры Param3 будет иметь значения 123
   nSomeResult = SomeFunction1(10, 20);


   // Вызов SomeFunction1 с явным указанием всех трёх
   // параметров
   nSomeResult = SomeFunction1(10, 20, 30);


   Теперь вернёмся к тому, что через возвращаемое значение функции могут сообщать пользователю код, по которому можно определить, верно ли завершена функция, или в процессе её выполнения произошла какая-то ошибка.


   Ниже приведёна схема функции, которая возвращает значение типа int. Условимся считать, что, если функциявернула значение отличное от нуля, то в ней произошла какая-то ошибка. Если же функция вернула нулевое значение, значит она успешно выполнила запрограммированный в ней алгоритм:
  
   int SmartFunction()
   {
   bool bReturn = false;
  // do something
   …
   if(bReturn) {
   return(1);
   }
   // do something else
   …
   if(bReturn) {
   return(2);
   }
  return(0);
   }


   Благодаря тому, что функция возвращает различные коды ошибок, мы можем диагностировать наличие ошибки и локализовать место её возникновения.


   При написании программы приходится достаточно часто обращать внимание на возвращаемый код той или иной функции. Хорошо, что в MQL 4 появилась возможность анализировать код возврата функции, но это однотипная процедура, и разбор ошибки происходит почти всегда по одному сценарию, а именно – когда возникает ошибка, нужно сообщить об этом пользователю как можно более информативно. Почему бы не “завернуть” в отдельную функцию код анализирующий возвращаемое некоторой функцией значение?


   AnalyzeIt(bool bCondition, string sModuleName, string sDescription =”Something is wrong”)
   {
   if(bCondition){
   Alert(“WARNING: ” + sDescription + ” in ” + sModuleName);
   }
   }


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


   AnalyzeIt(SmartFunction(),”MyFileName.mq4″);


   SmartFunction вернёт код ошибки, он передастся, как первый параметр bCondition в функцию AnalyzeIt. В том случае, если код ошибки отличный от нуля, пользователю будет выведено сообщение “WARNING: Something is wrong in MyFileName.mq4”.


   В случае, когда нужно получить более внятное описание ошибки – можно воспользоваться третьим параметром, как это сделано в следующем примере:


   AnalyzeIt(SmartFunction(),”MyFileName.mq4″,”Wrong SmartFunction termination”);


   Теперь пользователю будет выведено сообщение “WARNING: Wrong SmartFunction termination in MyFileName.mq4”.


   На сегодня всё. Мы надеемся, что в этой статье удалось показать, какие горизонты открывает введение более гибких функций в язык MQL 4. Их умелое использование существенно облегчит жизнь и труд программистов, пишущих программы для новой версии информационно торговой системы Meta Trader 4.


Александр Иванов