GlobalVariableCheck(): проверка существования глобальной переменной
Для человека, имеющего уже опыт написания экспертов, выражение «глобальные переменные» может внести небольшую путанницу. Дело в том, что на самом деле существует два вида «глобальных переменных»:
- переменные, которые видны из любой функции ОДНОГО эксперта (т.е. являются глобальными в пределах этого эксперта); и
- переменные, которые являются общими для ВСЕХ экспертов.
О глобальных переменных первого типа — тех, которые являются общими для всех функций ОДНОГО эксперта, — я рассказывал ранее, в выпуске «Глобальные переменные».
Сейчас же речь пойдет именно о глобальных переменных второго типа — общих для ВСЕХ экспертов.
Глобальная переменная второго типа — это переменная, к которой можно обратиться из любого эксперта. Если в течение четырех недель не было сделано попытки прочесть значение глобальной переменной или записать в нее новое значение, то глобальная переменная автоматически удаляется клиентским терминалом.
Для работы с глобальными переменными используются следующие функции:
- GlobalVariableCheck()
- GlobalVariableDel()
- GlobalVariableGet()
- GlobalVariableName()
- GlobalVariableSet()
- GlobalVariableSetOnCondition()
- GlobalVariablesDeleteAll()
- GlobalVariablesTotal()
Вначале я хотел бы рассказать о функции GlobalVariableCheck().
bool GlobalVariableCheck(string name)
Эта функция возвращает true, если глобальная переменная с именем name существует, и false, если такой переменной нет.
В нашей функции WaitBeforeTransaction() мы храним время и дату совершения последней торговой операции в глобальной переменной «LastTradeTime».
Перед тем, как узнать время последней операции, прочитав значение этой переменной, мы проверяем, существует ли она вообще:
// если глобальная переменная LastTradeTime не существует,
// то создать ее
if (!GlobalVariableCheck("LastTradeTime"))
{
... создаем переменную ...
}
Проверять существование глобальной переменной и создавать ее в случае отсутствия можно в двух местах: при инициализации эксперта — в функции init() — или на каждом тике — в функции start().
Несмотря на то, что на первый взгляд напрашивается осуществлять эти действия в функции init(), я бы советовал Вам делать это все-таки в функции start(). Дело в том, что если пользователь при работающем эксперте удалит глобальную переменную, а проверка на ее существование делается только при инициализации эксперта, то дальнейшее поведение такого советника сложно спрогнозировать. Скорее всего, такой советник просто перестанет торговать и начнет выдавать ошибки при обращении к удаленной глобальной переменной.
GlobalVariableSet() — установка нового значения глобальной переменной
Предположим, что ее не существует или же нам надо изменить ее значение. В этом случае надо использовать функцию GlobalVariableSet().
datetime GlobalVariableSet(string name, double value)
Функция GlobalVariableSet() устанавливает новое значение value глобальной переменной с именем name и в случае успеха возвращает время последнего доступа к глобальной переменной. Если произошла какая-то ошибка, то функция возвращает 0. Код ошибки, как обычно, можно получить с помощью функции GetLastError().
Если глобальная переменная с именем name отсутствовала, то она создается и она принимает значение value.
Пример использования функции GlobalVariableSet() можно найти в написанной нами функции WaitBeforeTransaction():
// если глобальная переменная LastTradeTime не существует,
// то создать ее
if (!GlobalVariableCheck("LastTradeTime"))
{
// Если произошла какя-то ошибка при вызове функции
// GlobalVariableCheck(), выйдем с ошибкой
if (GetLastError()!=0)
{
Print("WaitBeforeTransaction(): ошибка ",GetLastError(),
" при проверке глобальной переменной LastTradeTime");
return(-1);
}
// глобальная переменная не существует, создадим ее
if (GlobalVariableSet("LastTradeTime", 1)==0)
{
// произошла ошибка при создании глобальной переменной
Print("WaitBeforeTransaction(): ошибка ",GetLastError(),
" при создании глобальной переменной LastTradeTime");
return(-1);
}
// глобальная переменная успешно создана
Print("WaitBeforeTransaction(): глобальная переменная ",
"LastTradeTime создана");
}
GlobalVariableSetOnCondition() — установка нового значения глобальной переменной, если текущее ее значение равно заданному значению
К счастью, создатели языка MetaQuotes Language 4 являются профессиональными программистами и заранее могут предугадать, что может понадобиться трейдеру при написании экспертов. Я им очень благодарен, что они включили в список функций языка MetaQuotes Language 4 функцию GlobalVariableSetOnCondition().
Давайте же рассмотрим, чем так полезна эта функция.
bool GlobalVariableSetOnCondition(string name, double value,
double check_value)
Прежде всего эта функция проверяет, существует ли глобальная переменная с именем name. В документации по MetaQuotes Language 4 написано, что если такой глобальной переменной нет, то функция возвращает false и генерит ошибку ERR_GLOBAL_VARIABLE_NOT_FOUND (4058), которую можно получить с помощью функции GetLastError().
Однако при экспериментах с функцией GlobalVariableSetOnCondition() мне не удалось добиться того, чтобы функция вернула ошибку ERR_GLOBAL_VARIABLE_NOT_FOUND (4058). Почему-то даже в случае отсутствия глобальной переменной функция возвращает false и код ошибки ERR_NO_ERROR (т.е. 0). Вот кусок кода, который я использовал для этой цели:
string name = "MyGlobalVariable";
double value = 1;
double check_value = 2;
if (GlobalVariableSetOnCondition(name, value, check_value))
{
Print("Глобальная переменная ", name, " существует.",
" Ее значение изменено с ", check_value, " на ", value);
}
else
{
int Err=0;
Err = GetLastError();
Print(Err);
switch (Err)
{
case 0: Print("Глобальная переменная ", name," изменена не была",
" т.к. ее значение не равно ", check_value); break;
case 4058: Print("Глобальной переменной ", name,
" не существует"); break;
default: Print("Неизвестная ошибка: ", Err);
}
}
Если это баг, то думаю, что в следующих версиях MetaTrader 4 его исправят.
Вернемся к описанию функции GlobalVariableSetOnCondition(). Если же глобальная переменная name существует, то функция не изменит ее текущего значения и вернет false, если текущее значение этой глобальной переменной не равно check_value. Если потом запросить код последней ошибки, то функция GetLastError()вернет ERR_NO_ERROR (т.е. 0), т.к. реально никакой ошибки не было.
Если же текущее значение глобальной переменной name равно значению check_value, то функция GlobalVariableSetOnCondition() присвоит этой глобальной переменной новое значение: value.