В клиентском терминале MetaTrader 4, в отличии от MetaTrader 3, нет жесткого ограничения на паузу между торговыми операциями, совершаемых советниками. Поэтому теоретически можно совершать хоть десятки сделок в секунду. Однако чрезмерное злоупотребление этим приведет к тому, что Ваш счет будет заблокирован для торговли.
Это произойдет или потому, что сервер подумает, что такое количество запросов в секунду может осуществлять только злоумышленник, который ставит перед собой лишь цель «завалить» торговый сервер. Или потому, что сотнями запросами в минуту Вы разъярите дилера — сотрудника дилингового центра, которому приходится обрабатывать Ваши запросы.
Считается правилом хорошего тона не совершать торговые операции чаще, чем 1 раз в 5-10 секунд. Конечно, в любом правиле могут быть исключения и иногда Вам крайне необходимо совершить операции с меньшим временным лагом, но старайтесь этой возможностью не злоупотреблять.
Старайтесь выдерживать паузу минимум в 5 секунд. В этом Вам поможет моя функция WaitBeforeTransaction()
//+-------------------------------------------------------------------+
//| Фунцкия WaitBeforeTransaction выдерживает паузу Secs секунд
//| между торговыми операциями эксперта (по умолчанию 5 секунд)
//|
//| Возвращает:
//| 1 - если пауза выдержена без ошибок
//| 0 - если эксперт был остановлен
//| -1 - если произошла какая-то ошибка
//+--------------------------------------------------------------------+
int WaitBeforeTransaction(int Secs = 5)
{
// если режим тестирования, то ждать необязательно
if (IsTesting()) return(1);
// если глобальная переменная 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 создана");
}
// получим время последней операции
datetime LastTradeTime;
LastTradeTime = GlobalVariableGet("LastTradeTime");
// если произошла ошибка (равна нулю), то выходим с ошибкой
if (LastTradeTime==0)
{
Print("WaitBeforeTransaction(): ошибка ",GetLastError(),
" при чтении глобальной переменной LastTradeTime");
return(-1);
}
// ждем Secs секунд
while(true)
{
// если эксперт остановлен, выйдем со значением 0
if (IsStopped())
{
Print("WaitBeforeTransaction(): эксперт остановлен. Выходим...");
return(0);
}
// если прошло меньше Secs секунд, то ждем
if ((LocalTime()-LastTradeTime)
// т.к. прошло больше Secs секунд, то попробуем изменить значение
// глобальной переменной LastTradeTime на текущее время
// используем функцию GlobalVariableSetOnCondition(), чтобы выявить
// ошибку, если уже за время ожидания другой эксперт успел совершить
// сделку и изменил значение глобальной переменной
if (GlobalVariableSetOnCondition("LastTradeTime", LocalTime(), LastTradeTime))
{
// за время ожидания глобальная переменная не изменилась, поэтому
// удалось установить ее новое значение
// пауза выдержена, обновим котировки и выйдем без ошибки
RefreshRates();
return(1);
}
else
{
// не удалось изменить значение глобальной переменной, т.к. другой
// эксперт успел совершить сделку раньше и установил новое
// значение переменной поэтому получим текущее значение глобальное
// переменной и продолжим ожидание
LastTradeTime = GlobalVariableGet("LastTradeTime");
// если произошла ошибка (равна нулю), то выходим с ошибкой
if (LastTradeTime==0)
{
Print("WaitBeforeTransaction(): ошибка ",GetLastError(),
" при чтении глобальной переменной LastTradeTime");
return(-1);
}
}
}
}
Определение режима тестирования на истории с помощью функции IsTesting()
Сам исходный код функции обладает достаточным количеством комментариев, и я уверен, что логика реализации этой функции Вам станет абсолютно понятна после изучения следующих функций:
- IsTesting()
- GlobalVariableCheck()
- GlobalVariableSet()
- GlobalVariableGet()
- LocalTime()
Начнем с рассмотрения функции IsTesting().
bool IsTesting()
Функция IsTesting() возвращает true, если эксперт работает в режиме тестирования на исторических данных, и false — если работа ведется на демо- или реальном счете.
Дело в том, что необязательно сразу заставлять эксперта торговать на демо- или реальном счете. Гораздо эффективнее вначале оттестировать эксперта на исторических данных, которые есть в клиентском терминале. После этого с определенной точностью станет понятно, на что способен этот эксперт.
Основное преимущество тестов на истории — быстрота. Вам не надо ждать месяцы или годы, чтобы оттестировать своего эксперта на реальных котировках. Вы просто «прогоняете» советника по истории. На это у Вас уходит лишь несколько минут. Однако если Вы будете каждый раз ждать 10 секунд между торговыми операциями, то Вы потеряете это преимущество. Именно поэтому в коде нашей функции присутствует строка:
if (IsTesting()) return(1);
Т.е. мы выходим из функции, если эксперт находится в режиме тестирования на историчексих данных.