Математические функции в MQL4 на примерах

Программирование прибыли: от азов к секретам мастерства. Читайте, спрашивайте, делитесь опытом.
Бонус за сообщение 0.5$
Ответственный Модератор - Haos

Математические функции в MQL4 на примерах

Сообщение Kalkin » 24 апр 2016, 17:49

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

В первую очередь поговорим о нормализации данных. Нормализация - это приведение точности числа к необходимому значению.
Для этого существует функция
Код: выделить все
double  NormalizeDouble(
   double  value,      // нормализуемое число
   int     digits      // кол-во знаков после запятой
   );

В первый параметр функции NormalizeDouble() передаем число, которое хотим нормализовать, во второй параметр - до скольких десятичных знаков после запятой округлять число. Да, функция не только отсекает "лишние" знаки, но ещё и округляет по общепризнанным правилам математики. Например:
Код: выделить все
  Result = NormalizeDouble(12.75234, 2); // Переменная Result примет значение 12.75
  Result = NormalizeDouble(12.75234, 1); // Переменная Result примет значение 12.8


На практике нормализация необходима чаще всего в трех случаях:
1. При вычислении ценового уровня. Например, вычислили значение стоп-лосса или тейк-профита по какой-либо формуле. После выполнения действий с плавающей запятой результат необходимо округлить до количества знаков после запятой для торгуемого инструмента, иначе функция открытия или модификации позиции не сработает и вернет ошибку. Количество знаков после запятой для инструмента, на котором работает советник (скрипт, индикатор), определяется значением предопределенной переменной Digits или _Digits, а также функцией Digits(). Эту переменную и подставляем во второй параметр функции NormalizeDouble(). Например:
Код: выделить все
  // TakeProfitPips - количество пунктов для тейк-профита
  double TakeProfit = NormalizeDouble(Ask+TakeProfitPips*Point, Digits); // вычислить значение тейк-профита и нормализовать его

2. При вычислении размера лота. Точность лота - величина строго заданная, и если после арифметических действий получить недопустимое значение лота, то торговая функция вернет ошибку 131 (Неправильный объем). Количество знаков после запятой для величины лота в явном виде нигде не задано, поэтому его надо или задавать вручную, или вычислять. Несколько способов вычисления точности лота можно увидеть в ветке Расчет величины лота в зависимости от размера СЛ

3. Для вывода информационных сообщений. Очень часто сообщения выводятся в текстовые метки, а для них данные подготавливаются как строки, а не как числа. Поэтому, для нормализации вещественного числа и преобразования его в строку в MQL4 существует функция
Код: выделить все
string  DoubleToStr(
   double  value,     // величина
   int     digits     // формат точности
   );

Как видно, параметры функции DoubleToStr() аналогичны функции NormalizeDouble() с той лишь разницей, что результат выполнения - строка символов:
Код: выделить все
  string value=DoubleToStr(1.35473418, 5);
  // содержимое строки value - "1.35473"
Аватар пользователя
Kalkin
 
Сообщений: 1589
Зарегистрирован: 05 мар 2015, 06:51
Средств на руках: 108.80 Доллар
Награды: 2
Ветеран I (1) Медаль за научный вклад (1)
Группа: Базовая
Благодарил (а): 633 раз.
Поблагодарили: 1190 раз.
Ace Register Votive

Математические функции в MQL4 на примерах

Сообщение Kalkin » 12 май 2016, 08:22

Функция возведения в степень MathPow()
Код: выделить все
double  MathPow(
   double  base,         // основание 
   double  exponent      // показатель степени
   );

возводит основание в указанную степень.

Зачем она нужна для в общем-то простых повседневных задач трейдера - купить или продать? Но тем не менее, функция используется при вычислениях полиномов для построения, например, регрессионных каналов с произвольной степенью да и для многих других задач, связанных с математическими вычислениями.
Более приближенный к простым задачам вариант - расчет величины лота для очередного колена Мартингейла. Так, если имеем в наличии N позиций, то величина следующей позиции будет равна
Lot*(k в степени N)

где Lot - начальный лот;
k - коэффициент Мартингейла;
N - количество позиций.

Например, при отсутствии позиций показатель степени будет равен нулю, а все значение степени, независимо от коэффициента, примет значение единицы. Поэтому первоначальный лот будет равен Lot*1=Lot, что нам и требовалось. С увеличением количества позиций также будет увеличиваться значение рассчитанной степени.
Казалось бы, почему нельзя просто взять последнюю позицию и умножить на коэффициент, вместо того, чтобы рассчитывать степень? Есть ответ на этот вопрос, но интересно было бы услышать мнение читателей.

Для проверки напишем скрипт, который бы вычислял лот для следующего колена:
Код: выделить все
//+------------------------------------------------------------------+
//|                                           KS_MartinNextLevel.mq4 |
//|                                       Kalkin, www.investforum.ru |
//|                                       https://www.investforum.ru |
//+------------------------------------------------------------------+
#property copyright "Kalkin, www.investforum.ru"
#property link      "https://www.investforum.ru"
#property version   "1.00"
#property strict
#property script_show_inputs
//--- input parameters
input double   Lot=0.1;       // начальный лот
input double   Koeff=1.5;     // коэффициент Мартингейла
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
//---
   int CountBuy = 0;    // количество позиций на покупку
   int CountSell = 0;   // количество позиций на продажу
   for (int i=0;i<OrdersTotal();i++)
   {
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if (OrderSymbol()!=Symbol()) continue;       // выбираем только символ, на котором запущен скрипт
      if (OrderType()==OP_BUY) CountBuy++;         // увеличиваем счетчик позиций на покупку
      else if (OrderType()==OP_SELL) CountSell++;  // увеличиваем счетчик позиций на продажу
   }
   
   double NextLotBuy = Lot * MathPow(Koeff, CountBuy);       // вычисляем лот для позиций на покупку
   double NextLotSell = Lot * MathPow(Koeff, CountSell);     // вычисляем лот для позиций на продажу
   Alert(Symbol(),": Следующий лот BUY=",DoubleToStr(NextLotBuy,2),"   SELL=",DoubleToStr(NextLotSell,2)); 
}
//+------------------------------------------------------------------+



Работает скрипт следующим образом: при запуске в окне настроек указываются параметры начального лота и коэффициента Мартингейла. Далее скрипт в цикле перебирает все позиции и подсчитывает количество открытых позиций для каждого из направлений (покупок и продаж) по тому инструменту, на котором был скрипт запущен.
Далее, по вышеприведенной формуле рассчитывается лот для следующего колена и выводится сообщение с указанием рассчитанных значений. Как выводить сообщения типа Alert() на экран, подробно рассказано в статье Использование функции Alert() в коде советника.
Сам скрипт также можно скачать из вложения ниже:
Вложения
KS_MartinNextLevel.zip
(6.49 KB) Скачиваний: 69
Аватар пользователя
Kalkin
 
Сообщений: 1589
Зарегистрирован: 05 мар 2015, 06:51
Средств на руках: 108.80 Доллар
Награды: 2
Ветеран I (1) Медаль за научный вклад (1)
Группа: Базовая
Благодарил (а): 633 раз.
Поблагодарили: 1190 раз.
Ace Register Votive


Вернуться в MQL – теория и практика

Кто сейчас на форуме?

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 72

Права доступа к форуму

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения