Расскажем о трех функциях: IsExpertEnabled(), IsTradeContextBusy() и IsTradeAllowed().
Функция IsExpertEnabled()
bool IsExpertEnabled()
Функция IsExpertEnabled() возвращает true, если экспертам разрешено совершать сделки и управлять ордерами. Дело в том, что на уровне настроек клиентского терминала можно запретить ВСЕМ экспертам торговать. Это можно сделать, например, с помощью команды главного меню: Сервис -> Настройки. В появившемся окне выбираем вкладку «Советники», в которой ставим или убираем галочку напротив «Включить советники ».
Более простой способ отключать/включать советников — кнопка.
Если же на уровне настроек терминала работа экспертов запрещена, то функция IsExpertEnabled() вернет false.
Функция IsTradeContextBusy()
В каждый момент времени только один эксперт может торговать. Если в этот момент второй эксперт попытается совершить торговую операцию, то торговая функция вернет ошибку ERR_TRADE_CONTEXT_BUSY (146).
bool IsTradeContextBusy()
Функция IsTradeContextBusy() позволит Вам заблаговременно выявить ситуацию, когда другой эксперт уже пытается торговать (она вернет в этом случае значение true), и избежать нерезультативного вызова торговой функции (которая все равно завершиться с ошибкой). Обычно в таких случаях лучше подождать немного до того момента, когда другой эксперт закончит торговать (тогда функция IsTradeContextBusy() вернет значение false) и только после этого вызывать Вашу торговую функцию.
Функция IsTradeAllowed()
Функция IsTradeAllowed() объединяет все обе предыдущие функции. Она вернет true только в том случае, если торговля экспертов разрешена и торговый поток свободен для торговли, т.е. никакой другой эксперт не совершает в данный момент торговых операций.
bool IsTradeAllowed()
Как уже говорилось в каждый момент времени только один эксперт может торговать. Если в этот момент второй эксперт попытается совершить торговую операцию, то торговая функция вернет ошибку ERR_TRADE_CONTEXT_BUSY (146).
Что же делать, если у Вас торгует одновременно несколько экспертов?
Напишем функцию, которая возвращает:
- 0, если торговый поток свободен;
- 1, если работа эксперта была остановлена (см. причины ниже);
- 2, если торговля экспертов запрещена на уровне настроек клиентского терминала.
Если в момент обращения к функции торговый поток был занят, то функция ждет, пока он освободится. После этого она обновляет данные о текущих котировках с помощью функции RefreshRates() и возвращает 0.
Напомню возможные причины остановки эксперта:
- завершение работы MetaTrader 4,
- закрытие графика,
- удаление эксперта с графика,
- изменение инструмента или периода графика,
- удачная перекомпиляции программы в MetaEditor,
- изменение параметров эксперта,
- переключение на другой счет.
Исходный код функции, которая решает поставленную задачу:
//+-------------------------------------------------------------------+
//| Функция WaitUntilTradingIsAllowed возвращает:|
//| 0 - если торговый поток свободен |
//| 1 - если работа эксперта была остановлена |
//| 2 - если торговля экспертов запрещена на |
//| уровне настроекклиентского терминала |
//+-------------------------------------------------------------------+
int WaitUntilTradingIsAllowed()
{
// Если торговля разрешена, то вернем 0 и выйдем
if (IsTradeAllowed()) return(0);
// В цикле проверяем, как изменилась ситуация
while (!IsStopped())
{
// Если торговля экспертов запрещена на уровне настроек
// клиентского терминала, то выйдем и вернем 2
if (!IsExpertEnabled()) return(2);
// Если торговый поток освободился, то обновим данные
// о текущих курсах и вернем 0
if (!IsTradeContextBusy())
{
RefreshRates();
return(0);
}
// Если дошли до момента, то ситуация не изменилась
// Поэтому делаем паузу в 0.1 секунду
Sleep(100);
}
// Т.к. вышли из цикла, то работа эксперта была остановлена
// Вернем 1
return(1);
}
Функция IsStopped().
bool IsStopped()
Функция возвращает true, если эксперт был «остановлен», и false — в противном случае.
Эксперт получает команду на завершение в следующих случаях:
- при завершении работы клиентского терминала,
- при закрытии графика, к которому прикреплен эксперт,
- при удалении эксперта с графика,
- при изменении инструмента или периода графика,
- после перекомпиляции эксперта в MetaEditor,
- после изменения параметров советника,
- при переключении на другой счет.
Чтобы не пытаться совершить сделку по старым котировкам и не получить сообщение об ошибке, мы обновляем информацию о текущих котировках с помощью функции RefreshRates().
bool RefreshRates()
Функция возвращает true, если информация была обновлена, и false, если данные не изменились и в обновлении нет нужды. Если данные были обновлены, то вызов функции RefreshRates() также обновит время последней котировки, которое возвращается функцией CurTime().
Считается хорошим тоном вызывать функцию RefreshRates() перед вызовом торговой функции, если перед этим эксперт что-то очень долго или пересчитывал. Или же если эксперт ждал, пока другой эксперт закончит торговать и торговый поток освободиться.
Поскольку, наверняка, в своей торговле Вы будете использовать сразу несколько экспертов или одного и того же эксперта, но на разных временных промежутках или инструментах, то Ваши эксперты будут периодически ожидать освобождения торгового потока и Вы будете использовать функцию RefreshRates() практически всегда.