English 中文 Español Deutsch 日本語 Português
preview
Функции в MQL5-приложениях

Функции в MQL5-приложениях

MetaTrader 5Трейдинг | 11 октября 2023, 14:38
1 043 19
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Введение

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

Внимание! Все содержание настоящей статьи предоставляется "как есть", предназначено только для целей обучения и не является торговой рекомендацией. Статья не несет в себе каких-либо гарантий результатов. Все, что вы применяете на практике на основе этой статьи, вы делаете исключительно на свой страх и риск, автор не гарантирует никаких результатов.


Определение функции

В этой части мы дадим определение функциям в программировании, а также рассмотрим их типы и преимущества. Функция представляет собой блок кода, объявленный с определенным осмысленным именем, который можно использовать в любой другой части программы, вызывая его снова и снова для выполнения определенной задачи. Если у нас есть конкретная задача, которую программа должна выполнять во многих своих частях или во многих программах, мы создаем функцию или блок кода для выполнения этой задачи, а затем вызываем ее только в этих частях, не переписывая полный код заново. Итак, мы можем сказать, что функция — это метод абстрагирования нашего кода. Различают встроенные и пользовательские функции. Встроенная функция — это готовая функция самого языка программирования, а пользовательская — это функция, которая создана пользователем в соответствии с его потребностями или задачами. В этой статье мы сосредоточимся на пользовательских функциях.

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

Чтобы ответить на вопрос, почему нам нужно использовать этот тип функций, необходимо изучить особенности использования пользовательских функций:

  • Пользовательские функции позволяют применять метод DRY (не повторяйся): Мы создаем функцию, которая может выполнить нашу задачу один раз, а затем вызвать ее в любой подходящей части программного обеспечения.
  • Повторное использование: После создания функции мы можем повторно использовать ее в любое время.
  • "Разделяй и властвуй": Мы можем разделить большую задачу на маленькие и решить каждую из них с помощью функций.
  • Код становится более читабельным и понятным: Каждый элемент кода решает конкретную задачу.
  • Абстракция: Без функций нам понадобилось бы больше строк кода.
  • Инкапсуляция: Функции позволяют защитить код и данные, а также упрощают управление ими.
  • Упрощение отладки: Функции значительно упрощают поиск и устранение ошибок.


Структура функции

В этом разделе мы рассмотрим:

  • Объявление, или определение функции
  • Вызов функции

Прежде всего, нам нужно определить или объявить новую функцию, поэтому нам нужно выполнить примерно следующее:

returnedDataType functionName(param1, param2)
{
        bodyOfFunction
}
  • (returnedDataType) - тип данных, которые функция должна возвращать после выполнения.
  • (functionName) - имя функции (соответствует выполняемой задаче.
  • (param1, param2) - переменные, или заполнители (при необходимости).
  • (bodyOfFunction) - весь код, выполняющий задачу. 

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

//addition function
// returned data type is an integer - the name of the function is add - parameters or arguments are two int variables val1 and val2
int add(int val1, int val2)
  {
   //body of function that we need the function to perform when calling it
   //create a result new variable to be assigned by the result of val1 and val2 addition
   int result = val1+val2;
   //Print result in the experts tab
   Print(result);
   //returning value
   return result;
  }

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

   //calling our defined function by its name and specifying arguments
   add(5,15);

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

добавить результат функции

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

Функция с аргументами

В последнем примере мы использовали две целочисленные переменные: val1 и val2. Эти переменные рассматриваются как аргументы в нашей функции. Эти аргументы могут быть целочисленными, строковыми и т.д. В нашем последнем примере это были целочисленные переменные. Рассмотрим аналогичный пример со строковыми аргументами:

//sayHello function
// returned data type is string - name of function is sayHello - parameters or arguments are two string variables greeting and name
string sayHello(string greeting, string name)
  {
   //body of function that we need the function to perform when calling it
   //create a result new variable to be assigned by the result of greeting and name addition
   string result = greeting+name;
   //Print result in the experts tab
   Print(result);
   //returning value
   return result;
  }

Мы можем вызвать эту функцию уже упомянутым способом и найти ее результат после выполнения, как показано ниже:

результат функции sayhello

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

Функция без аргументов

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

//sayHello function
// returned data type is a string - the name of the function is sayHello - no parameters
string sayHello()
  {
   //body of the function that we need the function to perform when calling it
   //create a result new variable to be assigned by the result of greeting and name addition
   string greeting= "Hello, ";
   string name= "World!";
   string result = greeting+name;
   //Print the result in the experts' tab
   Print(result);
   //returning value
   return result;
  }

Когда мы вызываем функцию, она будет выглядеть следующим образом:

sayHello();

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

Функция со значениями по умолчанию

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

//defining function with default values
string sayHello(string greeting= "Hello, ", string name="World!")
  {
   string result = greeting+name;
   Print(result);
   return result;
  }

Затем мы можем вызвать функцию дважды, чтобы определить разницу между значениями по умолчанию. Если мы не указываем параметры, функция вернет значения по умолчанию:

   sayHello();
   sayHello("Hi, ", "Developer!");

Результат:

результат функции sayhello

Передача параметров

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

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

//passing by reference
void updateNums(int &val1, int &val2)
  {
   val1*=2;
   val2/=2;
  }

Затем мы создадим новые переменные, затем распечатаем их значения, затем вызовем нашу функцию с этими новыми переменными в качестве параметров и распечатаем ее значения после вызова, чтобы увидеть разницу:

//new variables
   int firstNum = 10;
   int secondNum = 20;
   
//before calling function
   Print("before calling: ");
   Print(firstNum, " - " ,secondNum, "\n"); 
   
// calling   
   updateNums(firstNum, secondNum);

// after calling  
   Print("after calling: ");
   Print(firstNum, " - " ,secondNum, "\n"); 

В результате мы получаем значения новых переменных 10 и 20, а после вызова они меняются на 20 и 10 согласно телу функции. Результат:

передача по ссылке

Оператор return

Если у нас есть функция, возвращающая значение, у нее должен быть оператор return. В зависимости от задачи функции у нас может быть более одного оператора return в функции, но если функция возвращает значение, то в последней строке функции должен быть хотя бы один оператор return. Он может быть любого типа, но не может быть массивом. Тем не менее, мы можем вернуть элемент из массива. Если мы хотим, чтобы функция возвращала массив, мы можем передать массив в функцию по ссылке, как мы упоминали ранее.

Ниже приведен пример с оператором return.

string sayHello(string greeting= "Hello, ", string name="World!")
  {
   string result = greeting+name;
   Print(result);
   return result;
  }

Функция типа void

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

void add(int val1, int val2)
  {
   int result= val1+val2;
  }

Перегрузка функций

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

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

void overloadingFun(int val1, int val2)
{
   int result=val1+val2;
}

void overloadingFun(int val1, int val2, int val3)
{
   int result=val1+val2+val3;
}

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

void overloadingFun(int val1, int val2)
{
   int result=val1+val2;
}

void overloadingFun(string message, int val1, int val2)
{
   int result=message+val1+val2;
}

Мы также можем выбрать нужную нам функцию по параметрам при вызове функции.


Приложения

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

Оповещение о новостях

Торговля во время экономических новостей считается очень рискованной и нежелательной. Экономический календарь содержит макроэкономические новости и показатели с описаниями, датой, временем и степенью важности, а также значения этих экономических событий. Есть множество источников обновления этих важных значений. Экономический календарь также есть в торговом терминале MetaTrader 5. Вы можете найти его вкладку в окне "Инструменты" и настроить, что именно вам нужно просматривать с точки зрения важности, валют и стран. Также имеются встроенные функции для работы с экономическим календарем. Вы можете найти их в документации по MQL5:

Функции экономического календаря

Итак, нам нужно вручную проверять экономический календарь, чтобы избежать торговли во время новостей, либо создать приложение, которое будет предупреждать нас о приближении новостей. Это постоянная задача. Она понадобится нам в любой торговой системе или во многих частях программного обеспечения. Мы можем создать необходимую функцию, а затем легко вызвать ее. Именно этим мы и займемся:

Это приложение будет советником. В глобальной области видимости мы создадим тип bool для имени нашей функции (isNewsComing), параметры добавлять не будем.

bool isNewsComing()

Тело функции создает массив с именем значения, а его типом будет (MqlCalendarValue), представляющий собой новостные значения, в частности фактическое значение.

MqlCalendarValue values[];

Нам нужно определить текущий день, определив время начала дня с помощью (iTime), чтобы вернуть время открытия бара после объявления новой переменной datetime с именем (startTime) и временем окончания дня, которое будет равно определенному времени начала и количеству секунд дня с помощью функции (PeriodSeconds) после объявления новой переменной datetime для (endTime)

   datetime startTime=iTime(_Symbol,PERIOD_D1,0);
   datetime endTime=startTime+PeriodSeconds(PERIOD_D1);

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

CalendarValueHistory(values,startTime,endTime,NULL,NULL);

Создадим цикл, начинающийся со значения (0), для созданной (i) переменной int и продолжим цикл, если (i) меньше размера массива значений массива, а также увеличим (i) на одно значение

for(int i=0; i<ArraySize(values); i++)

Тело цикла for создает переменную события и ее тип (MqlCalendarEvent) для описаний событий. Ее можно использовать в (CalendarEventById).

MqlCalendarEvent event;

Получаем описание события по его идентификатору с помощью (CalendarEventById), а его параметрами являются event_id и событие.

CalendarEventById(values[i].event_id,event);

Создадим переменную страны, ее тип будет (MqlCalendarCountry) для описаний стран, и ее можно будет использовать с (CalendarCountryById).

MqlCalendarCountry country;

Получим описания страны по ее идентификатору с помощью функции (MqlCalendarCountry). Ее параметрами являются Country_id и страна.

CalendarCountryById(event.country_id,country);

Установим условия для фильтрации событий по текущему символу или новостям валюты. Важность новостей средняя или высокая

      if(StringFind(_Symbol,country.currency)<0)
         continue;

      if(event.importance==CALENDAR_IMPORTANCE_NONE)
         continue;
      if(event.importance==CALENDAR_IMPORTANCE_LOW)
         continue;

Устанавливаем условие с временным диапазоном оповещения (за 30 секунд до выхода новостей).

      if(TimeCurrent()>=values[i].time-30*PeriodSeconds(PERIOD_M1) &&
         TimeCurrent()<values[i].time+30*PeriodSeconds(PERIOD_M1))

Затем нам нужно напечатать сообщение на вкладке "Эксперты" с названием события и текстом ( is coming! Stop Trading...)

Print(event.name, " is coming! Stop Trading...");

Возвращаемое значение - true

return true;

Если условия неверны, завершим цикл и вернем false, чтобы завершить функцию.

return false;

Затем мы можем вызвать функцию в функции OnTick, и если она вернет true, нам нужно напечатать сообщение (News is coming...!)

   if(isNewsComing())
     {
      Print("News is comming...!");
     }

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

//+------------------------------------------------------------------+
//| News Alert Function                                              |
//+------------------------------------------------------------------+ 
void OnTick()
  {
   if(isNewsComing())
     {
      Print("News is comming...!");
     }
  }
//+------------------------------------------------------------------+
bool isNewsComing()
  {
   MqlCalendarValue values[];
   datetime startTime=iTime(_Symbol,PERIOD_D1,0);
   datetime endTime=startTime+PeriodSeconds(PERIOD_D1);
   CalendarValueHistory(values,startTime,endTime,NULL,NULL);
   for(int i=0; i<ArraySize(values); i++)
     {
      MqlCalendarEvent event;
      CalendarEventById(values[i].event_id,event);
      MqlCalendarCountry country;
      CalendarCountryById(event.country_id,country);
      if(StringFind(_Symbol,country.currency)<0)
         continue;
      if(event.importance==CALENDAR_IMPORTANCE_NONE)
         continue;
      if(event.importance==CALENDAR_IMPORTANCE_LOW)
         continue;
      if(TimeCurrent()>=values[i].time-30*PeriodSeconds(PERIOD_M1) &&
         TimeCurrent()<values[i].time+30*PeriodSeconds(PERIOD_M1))
        {
         Print(event.name, " is coming! Stop Trading...");
         return true;
        }
     }
   return false;
  }
//+------------------------------------------------------------------+

Расчет размера лота

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

Создадим функцию с именем OptimalLotSize в виде double. У первой функции будут два параметра - double-переменная максимального процента риска и double-переменная максимального убытка в пунктах

double OptimalLotSize(double maxRiskPrc, double maxLossInPips)

Затем мы указываем, что нам нужно выполнить для этих параметров. Сначала мы определим значение эквити счета с помощью функции (AccountInfoDouble), которая возвращает значение подходящего свойства счета. В нашем случае это идентификатор эквити счета (ENUM_ACCOUNT_INFO_DOUBLE). Создадим оповещение с необходимым значением

   double accEquity = AccountInfoDouble(ACCOUNT_EQUITY);
   Alert("accEquity: ", accEquity);

Определим размер контракта символа с помощью функции (SymbolInfoDouble), которая возвращает соответствующее свойство указанного символа с вариантом имени символа (_Symbol), чтобы вернуть текущий символ, и prop_id, равный (SYMBOL_TRADE_CONTRACT_SIZE) как одно из значений (ENUM_SYMBOL_INFO_DOUBLE). Создадим оповещение с этим возвращаемым значением

   double lotSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE);
   Alert("lotSize: ", lotSize);

Рассчитаем стоимость пункта и получим оповещение с необходимым значением

   double tickValue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
   Alert("tickValue: ", tickValue);

Рассчитаем максимальное значение убытка на основе определенного эквити счета и получим оповещение с этим значением

   double maxLossDollar = accEquity * maxRiskPrc;
   Alert("maxLossDollar: ", maxLossDollar);

Рассчитаем максимальное значение в валюте котировки на основе рассчитанного максимального значения убытка и вернем оповещение с этим значением

   double maxLossInQuoteCurr = maxLossDollar / tickValue;
   Alert("maxLossInQuoteCurr: ", maxLossInQuoteCurr);

Рассчитаем оптимальный размер лота и вернем оповещение с необходимым значением

   double OptimalLotSize = NormalizeDouble(maxLossInQuoteCurr / (maxLossInPips * 0.0001)/ lotSize,2);
   Alert("OptimalLotSize: ", OptimalLotSize);

Оператор return возвращает OptimalLotSize как значение double.

return OptimalLotSize;

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

double OptimalLotSize(double maxRiskPrc, double entryPrice, double stopLoss)

Определим максимальный убыток в пипсах как абсолютное значение на основе входных параметров цены входа и цены стоп-лосса с последующим делением на 0,0001.

double maxLossInPips = MathAbs(entryPrice - stopLoss)/0.0001;

Оператором return будет созданная функция OptimalLotSize с параметрами максимального процента риска и максимального убытка в пунктах.

return OptimalLotSize(maxRiskPrc,maxLossInPips);

Затем мы можем вызвать любую из двух функций в части OnStart() в соответствии с тем, что нам нужно.

OptimalLotSize(0.01, 1.12303, 1.11920);

Ниже приведен полный код для создания функции этого типа.

//+------------------------------------------------------------------+
//| lotSize Calc Function                                            |
//+------------------------------------------------------------------+
void OnStart()
  {
   OptimalLotSize(0.01, 1.12303, 1.11920);
  }
//+------------------------------------------------------------------+
double OptimalLotSize(double maxRiskPrc, double maxLossInPips)
  {
   double accEquity = AccountInfoDouble(ACCOUNT_EQUITY);
   Alert("accEquity: ", accEquity);
   double lotSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE);
   Alert("lotSize: ", lotSize);
   double tickValue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
   Alert("tickValue: ", tickValue);
   double maxLossDollar = accEquity * maxRiskPrc;
   Alert("maxLossDollar: ", maxLossDollar);
   double maxLossInQuoteCurr = maxLossDollar / tickValue;
   Alert("maxLossInQuoteCurr: ", maxLossInQuoteCurr);
   double OptimalLotSize = NormalizeDouble(maxLossInQuoteCurr / (maxLossInPips * 0.0001)/ lotSize,2);
   Alert("OptimalLotSize: ", OptimalLotSize);
   return OptimalLotSize;
  }
//+------------------------------------------------------------------+
double OptimalLotSize(double maxRiskPrc, double entryPrice, double stopLoss)
  {
   double maxLossInPips = MathAbs(entryPrice - stopLoss)/0.0001;
   return OptimalLotSize(maxRiskPrc,maxLossInPips);
  }
//+------------------------------------------------------------------+

Выполнив этот скрипт, мы получим следующее предупреждение

 lotSize

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

Закрытие всех приложений

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

Включим класса Trade в код с помощью предварительной обработки или #include для включения всех торговых функций в файл (Trade.mqh).

#include <Trade/Trade.mqh>

Создадим объект с типом класса CTrade, который будет использоваться в программе.

CTrade trade;

В глобальной области нам также нужно создать функцию void closeAll без аргументов.

void closeAll()

Тело функции создает цикл for для проверки открытых ордеров.

for(int i=PositionsTotal()-1; i>=0; i--)

 Тело цикла, создание переменной ulong posTicket и присвоение ей тикета открытых ордеров

ulong posTicket=PositionGetTicket(i);

Закроем открытую сделку с помощью trade.PositionClose(posTicket)

trade.PositionClose(posTicket);

Удалим отложенные ордера, создав еще один цикл for для обнаружения этих ордеров, назначив их тикеты переменной ulong posTicket и удалив отложенный ордер по его обнаруженному тикету.

   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      ulong posTicket=OrderGetTicket(i);
      trade.OrderDelete(posTicket);
     }

После этого мы можем вызвать эту функцию в OnStart().

closeAll();

Скрипт закрывает и удаляет все ордера. Ниже приведен полный код closeAllApp:

//+------------------------------------------------------------------+
//| closeAll Function                                                |
//+------------------------------------------------------------------+ 
#include <Trade/Trade.mqh>
CTrade trade;
//+------------------------------------------------------------------+
void OnStart()
  {
   closeAll();
  }
//+------------------------------------------------------------------+
void closeAll()
  {
//close all open positions
   for(int i=PositionsTotal()-1; i>=0; i--)
     {
      ulong posTicket=PositionGetTicket(i);
      trade.PositionClose(posTicket);
     }
//delete all pending orders
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      ulong posTicket=OrderGetTicket(i);
      trade.OrderDelete(posTicket);
     }
  }
//+------------------------------------------------------------------+

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


Заключение

Применение функций имеет ряд неоспоримых преимуществ:

  • Функции позволяют использовать метод DRY.
  • Это помогает упростить решение любой большой задачи, разделив ее на мелкие.
  • Делает код более читабельным.
  • Делает возможным повторное использование.
  • Абстрагирование кода.
  • Инкапсуляция кода.
  • Улучшение отладки.

Также мы рассмотрели типы функций (встроенные и пользовательские), а также их создание и определение, изучили структуру функций и их характеристики, включая функции с аргументами, а также передачу этих аргументов или параметров без аргументов и функций со значениями по умолчанию. Предполагается, что вы можете определить функцию, используя любой тип данных, и работать с оператором return, а также знаете, как создать множество функций перегрузки с одинаковым именем, но разными аргументами для выполнения одной и той же задачи.

Надеюсь, примеры приложений помогли вам глубже понять тему:

  • New Alert App - оповещения о важных новостях. Можно использовать или вызывать в любой части программы. Исходный код newsAlertApp приложен внизу.
  • Lot size Calc App - получение оптимального размера лота для открытия сделки на основе определенного процента риска, цены входа и цены стоп-лосса. Либо на основе определенного процента риска и максимального убытка в пунктах, что означает, что мы создали в этом приложении функцию перегрузки. Также можно использовать или вызывать в любой части программы. Исходный код lotSizeCalcApp приложен внизу.
  • Close All App - закрытие всех открытых и отложенных ордеров. Исходный код closeAllApp приложен внизу.

Мир функций очень интересен, и очень важно уделять ему внимание, чтобы иметь возможность легко и эффективно создавать полезные фрагменты кода. Надеюсь, статья была для вас полезной и расширила ваш арсенал торговых инструментов. Если вы хотите узнать больше о программировании или о том, как создавать торговые системы на основе самых популярных технических индикаторов, таких как скользящее среднее, RSI, MACD, Stochastic, полосы Боллинджера, Parabolic Sar... и других, вы можете прочитать мои предыдущие статьи  и, возможно, найти что-то полезное.

Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/12970

Прикрепленные файлы |
newsAlertApp.mq5 (1.37 KB)
lotSizeCalcApp.mq5 (1.45 KB)
closeAllApp.mq5 (0.86 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (19)
MrBrooklin
MrBrooklin | 12 окт. 2023 в 17:58
Grigori.S.B #:

Ну почему же? Вполне полезно ознакомиться.
Тем более что большинство из них может быть использовано и сейчас без модификации.
https://www.mql5.com/ru/forum/107476
https://www.mql5.com/ru/forum/131859

Для онлайна, тестера. Да и оформлены красиво.

Может быть и полезно, но абсолютно не знаком с языком программирования MQL4. Изучал только MQL5.

С уважением, Владимир.

fxsaber
fxsaber | 12 окт. 2023 в 18:56
MrBrooklin #:

Может быть и полезно, но абсолютно не знаком с языком программирования MQL4. Изучал только MQL5.

Они (функции Кима) все давно портированы с MQL4 на MQL5.

MrBrooklin
MrBrooklin | 12 окт. 2023 в 19:09
fxsaber #:

Они (функции Кима) все давно портированы с MQL4 на MQL5.

Извините за невежество и поверьте не ёрничаю, а что такое портированы? Переписаны на MQL5, что ли? Если они собраны где-то в одном месте, а также если Вам не трудно, то дайте ссылку на портированные в MQL5 функции Кима. Попытался пройтись поиском по сайту - портированные функции Кима, но ничего не нашёл.

С уважением, Владимир.

fxsaber
fxsaber | 13 окт. 2023 в 15:41
MrBrooklin #:

дайте ссылку на портированные в MQL5 функции Кима.

https://www.mql5.com/ru/forum/107476

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Библиотеки: MT4Orders

fxsaber, 2019.01.13 17:23

Кимовские функции под MT4 довольно популярны, поэтому скачал все исходники с его сайта и написал для них простой  "конвертер" под MT5.
#include <KimIVToMT5.mqh> // https://c.mql5.com/3/263/KimIVToMT5.mqh
MrBrooklin
MrBrooklin | 13 окт. 2023 в 15:43

Спасибо!

С уважением, Владимир.

Анализ циклов с использованием алгоритма Гёрцеля Анализ циклов с использованием алгоритма Гёрцеля
В статье представлены утилиты, реализующие алгоритм Гёрцеля в MQL5 и два способа применения этого метода при анализе ценовых котировок для разработки стратегии.
Нейросети — это просто (Часть 58): Трансформер решений (Decision Transformer—DT) Нейросети — это просто (Часть 58): Трансформер решений (Decision Transformer—DT)
Мы продолжаем рассмотрение методов обучения с подкреплением. И в данной статье я предлагаю вам познакомиться с несколько иным алгоритмом, который рассматривает политику Агента в парадигме построения последовательности действий.
Теория категорий в MQL5 (Часть 14): Функторы с линейным порядком Теория категорий в MQL5 (Часть 14): Функторы с линейным порядком
Эта статья из серии статей о реализации теории категорий в MQL5 посвящена функторам. Мы исследуем, как линейный порядок может быть отображен на множестве благодаря функторам при рассмотрении двух множеств данных, между которыми на первый взгляд отсутствует всякая связь.
Библиотека численного анализа ALGLIB в MQL5 Библиотека численного анализа ALGLIB в MQL5
В этой статье мы кратко рассмотрим библиотеку численного анализа ALGLIB 3.19, ее приложения и новые алгоритмы, позволяющие повысить эффективность анализа финансовых данных.