Нормализация лота
При попытке открыть сделку из кода советника или скрипта, важно правильно указать размер лота. Значение имеет даже количество цифр после запятой. Например, лот 0.12 брокер примет, а лот 0.1234 уже нет. Также есть минимальный и максимальный разрешенный лот. У каждого брокера и на каждом типе счета, значения шага лота и его минимума и максимума разные, поэтому нужно правильно нормализовать его размер, прежде чем отправить форекс брокеру ордер (приказ) на открытие сделки.
Почему предполагаемый объем сделки может измениться перед её открытием? Первое - это, просто пользователь торгового робота установит в настройках неправильный размер лота. Например, 0.01 или 0.12. При этом на торговом счете брокер установил минимальный размер лота 0.1 или минимальный шаг лота 0.05. Всё, в данном случае ни с тем, ни с другим лотом сделка не откроется. Трейдер будет сидеть и ждать открытия заветной сделки, но этого так и не произойдет.
Также, лот может постоянно меняться в коде программы, например, при использовании функции Автолот, либо при расчета лота по Мартингейлу, при различных системах мани менеджмента и во многих других случаях. И каждый раз лот нужно нормализовать, чтобы исключить сбои торгового алгоритма во время торговли на реальном счете, на рынке Форекс.
Итак, главное что нужно принять во внимание - это то, что лот имеет свой минимальный и максимальные размеры, и минимальный шаг изменения размера. Учитывая эти три параметра мы и создадим функцию, которая будет нормализовать лот. Эта функция будет принимать любой размер лота и возвращать тот размер, с которым сделка без проблем откроется на текущем торговом счете.
//+------------------------------------------------------------------+
//| Globals |
//+------------------------------------------------------------------+
double min_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN),
max_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX),
lot_step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
Первое, что мы сделаем - это сохраним в переменных значения минимального, максимального размера и шага лота, на глобальном уровне. Таким образом, объявив эти переменные на глобальном уровне, мы только один раз, за всё время работы программы, получаем значения нужных нам параметров из свойств символа текущего графика. И можем использовать эти переменные в любом месте программы и любое количество раз, не вызывая функции SymbolInfoDouble
, тем самым немного снизив нагрузку при работе программы.
Глобальные переменные могут находится в любом месте программы, но не в коде функций. Удобно располагать в начале программы входные (input) параметры и сразу после них объявить все нужные глобальные переменные.
С учетом того, что у нас уже есть переменные с необходимыми параметрами лота, напишем код функции, которая будет принимать любой размер лота и затем нормализовать его. И возвращать его таким, что при открытии сделки никогда не возникнет отказа из-за неправильного размера лота.
//+------------------------------------------------------------------+
//| Нормализует размер лота |
//+------------------------------------------------------------------+
double NormalizeLots(const double lots)
{
double volume = MathFloor(lots / lot_step) * lot_step;
//---
if(volume < min_lot)
return min_lot;
if(volume > max_lot)
return max_lot;
return volume;
//---
}
Что же происходит в теле функции? Первое что мы делаем - это нормализуем размер лота, в соответствии с минимальным шагом лота. То есть, например, из 0.12345 делаем 0.12, если минимальный шаг лота равен 0.01.
double volume = MathFloor(lots / lot_step) * lot_step;
Функция MathFloor
- встроенная математическая функция языка MQL, возвращает ближайшее снизу целое числовое значение. То есть округляет число с плавающей точкой до целого значения вниз. Например, 1.5 округлит до 1, а 23.0893 до 23.
Таким нехитрым образом, мы вначале делим лот на его шаг, далее округляем вниз до целого значения и затем обратно умножаем на шаг.
Давайте наглядно посчитаем. Пусть нам надо нормализовать лот 0.3486, шаг лота на нашем торговом счете равен 0.01. Получается: MathFloor(0.3486 / 0.01) * 0.01
= 34 * 0.01
= 0.34
. А если шаг лота равен 0.1, то получится: MathFloor(0.3486 / 0.1) * 0.1
= 3 * 0.1
= 0.3
.
Как видно из расчетов выше, мы уже получили размер лота, нормализованный в соответствии с установленным брокером минимальным шагом лота. Осталось нормализовать полученное значение, в соответствии с установленными минимальным и максимальным размером лота.
И с этим всё уже намного проще. В строках 8-14 мы делаем простую проверку: если размер лота, который мы рассчитали перед этим, меньше минимального, то возвращаем минимальный размер лота:
if(volume < min_lot)
return min_lot;
Либо, если лот больше максимального, то возвращаем максимальный разрешенный размер лота:
if(volume > max_lot)
return max_lot;
Благодаря этому мы сможем открыть сделку в любом случае, даже если у нас изначально получился лот 0.000000001 (увеличится до минимального 0.01) или 560.159456 (уменьшится до максимального 99.99).
Ну и, если лот находится в пределах допустимых значений, то просто возвращаем его значение:
return volume;
Теперь, прежде чем открыть сделку, просто нормализуйте лот с помощью функции NormalizeLots, тем самым повысив надежность своего торгового форекс робота, а значит и его прибыльность.
double lots = 0.271684;
lots = NormalizeLots(lots);
OpenBuy(lots, ....); // lots == 0.27