//+------------------------------------------------------------------+ //| TradeContext.mq4 | //| komposter | //| komposterius@mail.ru | //+------------------------------------------------------------------+ #property copyright "komposter" #property link "komposterius@mail.ru" ///////////////////////////////////////////////////////////////////////////////// /**/ int _IsTradeAllowed( int MaxWaiting_sec = 30 ) ///////////////////////////////////////////////////////////////////////////////// // функция определяет состояние торгового потока. Коды возвратов: // 1 - торговый поток свободен, можно торговать // 0 - торговый поток был занят, но освободился. Торговать можно только после обновления рыночной информации. // -1 - торговый поток занят, ожидание прервано пользователем (эксперт удалён с графика, закрыт терминал, изменился // период и/или символ графика, ... ) // -2 - торговый поток занят, истекло максимальное время ожидания (MaxWaiting_sec). Возможно, эксперту запрещена // торговля (галочка "Разрешить эксперту торговать" в настройках эксперта). // // MaxWaiting_sec - время (в секундах), в течении которого функция будет ждать освобождения торгового потока (если он // занят). По умолчанию = 30. ///////////////////////////////////////////////////////////////////////////////// { // проверяем, свободен ли торговый поток if ( !IsTradeAllowed() ) { int StartWaitingTime = GetTickCount(); Print( "Торговый поток занят! Ждём, пока он освободиться..." ); // бесконечный цикл while ( true ) { // если эксперт был остановлен пользователем, прекращаем работу if ( IsStopped() ) { Print( "Эксперт был остановлен пользователем!" ); return(-1); } // если ожидание длится дольше времени, указанного в переменной MaxWaiting_sec, тоже прекращаем работу if ( GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000 ) { Print( "Превышен лимит ожидания (" + MaxWaiting_sec + " сек.)!" ); return(-2); } // если торговый поток освободился, if ( IsTradeAllowed() ) { Print( "Торговый поток освободился!" ); return(0); } // если ни одно из условий остановки цикла не сработало, "ждём" 0,1 секунды и начинаем проверку сначала Sleep(100); } } else { Print( "Торговый поток свободен!" ); return(1); } } /* Шаблон эксперта, использующего функцию _IsTradeAllowed: int start() { // определяем необходимость входа в рынок ... // расчитываем уровни Стоп Лосс, Тейк Профит и размер лота ... // проверяем, свободен ли торговый поток int TradeAllow = _IsTradeAllowed(); if ( TradeAllow < 0 ) { return(-1); } if ( TradeAllow == 0 ) { RefreshRates(); // пересчитываем уровни Стоп Лосс и Тейк Профит ... } // открываем позицию OrderSend(.....); return(0); } */ ///////////////////////////////////////////////////////////////////////////////// /**/ int TradeIsBusy ( int MaxWaiting_sec = 30 ) ///////////////////////////////////////////////////////////////////////////////// // Функция меняет значение глобальной переменной TradeIsBusy с 0 на 1. // Если в момент запуска TradeIsBusy = 1, функция ждёт, пока TradeIsBusy станет = 0, и только потом меняет. // Если глобальной переменной TradeIsBusy не существует, функция создаёт её. // Коды возвратов: // 1 - успешное завершение. Глобальной переменной TradeIsBusy присвоено значение 1 // -1 - в момент запуска функции TradeIsBusy = 1, ожидание было прервано пользователем (эксперт удалён с графика, закрыт // терминал, изменился период и/или символ графика, ... ) // -2 - в момент запуска функции TradeIsBusy = 1, истекло максимальное время ожидания (MaxWaiting_sec) ///////////////////////////////////////////////////////////////////////////////// { // при тестировании нет смысла в разделении торгового потока - просто завершаем работу функции if ( IsTesting() ) { return(1); } int _GetLastError = 0, StartWaitingTime = GetTickCount(); //+------------------------------------------------------------------+ //| Проверяем, существует ли гл. переменная и, если нет, создаём её //+------------------------------------------------------------------+ while( true ) { // если эксперт был остановлен пользователем, прекращаем работу if ( IsStopped() ) { Print( "Эксперт был остановлен пользователем!" ); return(-1); } // если ожидание длится дольше времени, указанного в переменной MaxWaiting_sec, тоже прекращаем работу if ( GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000 ) { Print( "Превышен лимит ожидания (" + MaxWaiting_sec + " сек.)!" ); return(-2); } // проверяем, существует ли гл. переменная if ( GlobalVariableCheck( "TradeIsBusy" ) ) // если она есть, выходим из этого цикла и переходим к блоку изменения значения TradeIsBusy { break; } else // если GlobalVariableCheck вернула FALSE, значит либо переменной нет, либо при проверке возникла ошибка { _GetLastError = GetLastError(); // если это всё таки ошибка, выводим информацию, ждём 0,1 секунды и начинаем проверку сначала if ( _GetLastError != 0 ) { Print( "TradeIsBusy() - GlobalVariableCheck ( \"TradeIsBusy\" ) - Error #", _GetLastError ); Sleep(100); continue; } } // если ошибки нет, значит глобальной переменной просто нет, пытаемся создать её if ( GlobalVariableSet ( "TradeIsBusy", 1.0 ) > 0 ) // если GlobalVariableSet > 0, значит глобальная переменная успешно создана. Выходим из ф-ции { return(1); } else // если GlobalVariableSet вернула значение <= 0, значит при создании переменной возникла ошибка { _GetLastError = GetLastError(); // выводим информацию, ждём 0,1 секунды и начинаем попытку сначала if ( _GetLastError != 0 ) { Print( "TradeIsBusy() - GlobalVariableSet ( \"TradeIsBusy\", 0.0 ) - Error #", _GetLastError ); Sleep(100); continue; } } } //+------------------------------------------------------------------+ //| Если выполнение функции дошло до этого места, значит глобальная переменная существует. //| Ждём, пока TradeIsBusy станет = 0 и меняем значение TradeIsBusy с 0 на 1 //+------------------------------------------------------------------+ while( true ) { // если эксперт был остановлен пользователем, прекращаем работу if ( IsStopped() ) { Print( "Эксперт был остановлен пользователем!" ); return(-1); } // если ожидание длится дольше времени, указанного в переменной MaxWaiting_sec, тоже прекращаем работу if ( GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000 ) { Print( "Превышен лимит ожидания (" + MaxWaiting_sec + " сек.)!" ); return(-2); } // пытаемся менять значение TradeIsBusy с 0 на 1 if ( GlobalVariableSetOnCondition( "TradeIsBusy", 1.0, 0.0 ) ) // если нам это удаётся, выходим из ф-ции, возвращая 1 - "успешное завершение" { return(1); } else // если нет, возможны 2 причины: TradeIsBusy = 1 (тогда надо ждать), либо возникла ошибка (это мы и проверим) { _GetLastError = GetLastError(); // если это всё таки ошибка, выводим информацию и пробуем ещё раз if ( _GetLastError != 0 ) { Print( "TradeIsBusy() - GlobalVariableSetOnCondition ( \"TradeIsBusy\", 1.0, 0.0 ) - Error #", _GetLastError ); continue; } } // если ошибки нет, значит TradeIsBusy = 1 (другой эксперт торгует) - выводим информацию и ждём... Comment ( "Ждём, пока другой эксперт закончит торговать..." ); Sleep(1000); } } ///////////////////////////////////////////////////////////////////////////////// /**/ void TradeIsNotBusy () ///////////////////////////////////////////////////////////////////////////////// // Функция устанавливает значение глобальной переменной TradeIsBusy = 0. // Если глобальной переменной TradeIsBusy не существует, функция создаёт её. // Функция не прекращает работу, пока не сможет выполнить свою задачу. ///////////////////////////////////////////////////////////////////////////////// { // при тестировании нет смысла в разделении торгового потока - просто завершаем работу функции if ( IsTesting() ) { return(0); } int _GetLastError; while( true ) { // пытаемся установить значение гл. переменной = 0 (или создать гл. переменную) if ( GlobalVariableSet( "TradeIsBusy", 0.0 ) > 0 ) // если GlobalVariableSet вернула значение > 0, значит всё закончилось хорошо. Выходим из ф-ции { return(1); } else // если GlobalVariableSet вернула значение <= 0, значит возникла ошибка. Выводим информацию, ждём, и пробуем ещё раз { _GetLastError = GetLastError(); if ( _GetLastError != 0 ) { Print( "TradeIsNotBusy() - GlobalVariableSet ( \"TradeIsBusy\", 0.0 ) - Error #", _GetLastError ); } } Sleep(100); } } /* Шаблон эксперта, использующего функции TradeIsBusy() и TradeIsNotBusy(): #include int start() { // определяем необходимость входа в рынок ... // расчитываем уровни Стоп Лосс, Тейк Профит и размер лота ... // ждём освобождения торгового потока и занимаем его (если произошла ошибка, выходим) if ( TradeIsBusy() < 0 ) { return(-1); } // обновляем рыночную информацию RefreshRates(); // пересчитываем уровни Стоп Лосс и Тейк Профит ... // открываем позицию OrderSend(.....); // освобождаем торговый поток TradeIsNotBusy(); return(0); } */deIsNotBusy(); return(0); } */