Список значений в одном входном параметре
Иногда нужно иметь возможность указывать в настройках торгового робота список из нескольких значений. Например, это может быть последовательность увеличивающихся размеров лота, с которым будет открываться каждая последующая сделка, при закрытии предыдущей в убыток.
input string Lots = "0.01, 0.02, 0.04, 0.07, 0.1"; // Последовательность лотов
Мы задаем входной параметр Lots
, в котором и будет указываться список значений. Параметр Lots
имеет тип string
- строка, в которой по сути можно написать что угодно. Поэтому нужно заранее предупреждать пользователей вашей mql программы для Metatrader, о том как правильно указывать значения в этом параметре.
Так, в нашем случае, необходимо соблюдать две условности: указывать размер лота с точкой, в качестве разделителя десятичной части числа, и разделять значения лотов запятой.
При этом мы снизим количество условностей и не будем делать такое условие, что лоты должны быть разделены не только запятой, но и пробелом после запятой, как это принято в правилах орфографии при написании обычных строк. Пользователь сам решит использовать ему пробелы или нет, а мы в коде просто очистим значения от пробелов.
Также нужно обратить внимание на разделитель значений - в данном случае мы используем в этом качестве знак запятой. При этом разделитель может быть любым знаком, или даже значением из нескольких знаков. И даже может быть указан во входных параметрах в настройках советника или индикатора.
Вернемся к написанию кода. После создания необходимого входного параметра, нам нужно создать глобальную переменную - массив типа double
, в котором будут храниться уже преобразованные и готовые к использованию в любом месте программы, значения размеров лота.
double lots_array[];
Далее создадим функцию, которая будет конвертировать список лотов из строки параметра Lots
, в массив lots_array
.
//+------------------------------------------------------------------+
//| Устанавливает последовательность лотов в массив lots_array |
//+------------------------------------------------------------------+
bool InitLots(void)
{
// Очищаем массив лотов от предыдущих значений
ArrayFree(lots_array);
//---
// Получаем символьный код разделителя
ushort u_sep = StringGetCharacter(",", 0);
// Создаем массив для хранения строк,
// полученных после разделения исходной строки Lots
string result[];
// Разделяем строку Lots на отдельные строки
int k = StringSplit(Lots, u_sep, result);
// Получаем размер массива с результатами разделения строки Lots
int total = ArraySize(result);
// Делаем проверку на количество полученных строк после разделения строки Lots
if(total == 0)
{
// Если значения в Lots не были указаны, либо использовался другой разделитель,
// то сообщим об этом пользователю и прервем инициализацию программы.
Alert("Необходимо указать хотя бы один лот");
return false;
}
// Перебираем все строки, получившиеся после разделения
for(int i=0; i<total; i++)
{
// Сохраняем строку из массива во временную переменную
string s_tmp = result[i];
// Очищаем строку от пробелов
#ifdef __MQL4__
s_tmp = StringTrimLeft(s_tmp);
s_tmp = StringTrimRight(s_tmp);
#endif
#ifdef __MQL5__
StringTrimLeft(s_tmp);
StringTrimRight(s_tmp);
#endif
// Преобразуем строку в число типа double
double lot = StringToDouble(s_tmp);
// Добавляем готовый к использованию лот в массив лотов
ArrayAdd(lots_array, lot); // кастомная функция, код в статье не приводится
}
//---
return true;
}
Первое, что мы делаем - это разделяем строку Lots
на подстроки, которые сохраняются в массив result
. Строка Lots имеет такое значение: "0.01, 0.02, 0.04, 0.07, 0.1"
, после её разделения по символу разделителю - запятой в данном случае, содержимое массива result
будет выглядеть так: ["0.01", " 0.02", " 0.04", " 0.07", " 0.1"]
.
Так как это всё еще строки, то пробелы также сохранились.
Затем мы проходимся в цикле по всем строкам массива result
, очищаем каждую строку от пробелов слева и справа, преобразуем строку в число double
и добавляем его в массив lots_array
.
Обратите внимание, что встроенные в язык программирования mql функции StringTrimLeft и StringTrimRight, работают по разному в mql4 и в mql5. В mql4 они принимают строку, очищают и возвращают её. Тогда как в mql5 они принимают строку по ссылке и очищают её, но не возвращают, а просто преобразуют.
Знаете ли вы, что: директивы #ifdef __MQL4__ ... #endif и #ifdef __MQL5__ ... #endif используются, чтобы разделить код mql4 и mql5 в одной программе. Выше мы создали функцию InitLots, которая может работать как в МТ4, так и в МТ5, но при этом она содержит код зависимый от версии торгового терминала и от версии языка программирования mql.
Так, при компилировании программы для МТ4, код написанный внутри #ifdef __MQL5__ ... #endif будет просто пропущен компилятором и исключен из программы. Также и наоборот: код внутри #ifdef __MQL4__ ... #endif будет удален для программы работающей в Metatrader 5 версии.
Функция InitLots
готова, как мы будем её использовать? Чтобы иметь всегда актуальный список лотов, мы вызываем функцию InitLots
в функции OnInit
форекс робота или индикатора. Благодаря этому, при каждом изменении входных параметров программы, мы будем иметь актуальный список лотов.
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
if(!InitLots())
return INIT_FAILED;
//---
}
А если пользователь неправильно укажет размеры лотов, то функция InitLots
вернет false
и инициализация советника прервется, что защитит от ошибок работы программы в дальнейшем.
После того как список лотов создан, мы можем использовать его (массив lots_array
) в любом месте программы. Например, у нас есть функция, которая открывает сделку, но перед этим она проверяет количество предыдущих сделок закрытых в убыток. И в соответствии с этим количеством берет следующий лот из списка лотов и открывает сделку на форекс с этим лотом.
//+------------------------------------------------------------------+
//| Открывает сделку после закрытия предыдущих сделок в убыток |
//+------------------------------------------------------------------+
void OpenAfterLoss(void)
{
// Получаем количество предыдущих сделок, закрытых подряд в убыток
int num_loss = NumLossDeals(); // Вымышленная функция, приведена для примера
// Получаем размер массива с лотами
int lots_total = ArraySize(lots_array);
// Если размер массива с лотами меньше, чем количество убыточных сделок,
// то берем последнее значение лота из массива,
// иначе произойдет ошибка и программа прекратит работу.
int lot_index = MathMin(lots_total-1, num_loss);
// Получаем размер лота из списка
double lot = lots_array[lot_index];
// Открываем сделку с полученным лотом
OpenBuy(lot, ...); // Вымышленная функция, приведена для примера
}