English 中文 Español Deutsch 日本語 Português
Ошибка 146 ("Торговый поток занят") и как с ней бороться

Ошибка 146 ("Торговый поток занят") и как с ней бороться

MetaTrader 4Примеры | 12 мая 2006, 17:37
7 043 27
Andrey Khatimlianskii
Andrey Khatimlianskii

1. Понятие "Торгового потока" в терминале MetaTrader 4

Из справки MetaEditor:

Для проведения торговых операций из экспертов и скриптов предусмотрен всего один поток, который запускается в программном торговом контексте  (контекст  автоматической торговли из экспертов и скриптов).  Поэтому, если этот контекст  занят  торговой  операцией  какого-либо эксперта, то  другой эксперт или скрипт не может в этот момент вызывать торговые функции из-за ошибки 146 (ERR_TRADE_CONTEXT_BUSY)

Проще говоря, проводить торговые операции одновременно может только один эксперт (скрипт). Все остальные эксперты, пытающиеся торговать, будут "остановлены" ошибкой № 146. Данная статья посвящена решению этой проблемы.


2. Функция IsTradeAllowed()

Самый простой способ определить, свободен ли торговый поток - использовать функцию IsTradeAllowed().
    Из справки MetaEditor:

"bool IsTradeAllowed()

Возвращает TRUE, если эксперту разрешено торговать, и поток для выполнения торговых операций свободен, иначе возвращает FALSE

    Т.е. пытаться торговать можно только в том случае, если функция IsTradeAllowed() возвращает TRUE.
    Проверку надо делать непосредственно перед торговой операцией.

    Пример неправильного использования функции:

int start()
  {
    // проверяем, свободен ли торговый поток
    if(!IsTradeAllowed())
      {
        // если функция IsTradeAllowed() вернула FALSE, сообщаем об этом пользователю,
        Print("Торговый поток занят! Эксперт не может открыть позицию!");
        // и прекращаем работу эксперта. Она будет возобновлена с приходом следующего 
        // тика
        return(-1);
      }
    else
      {
        // если функция IsTradeAllowed() вернула TRUE, сообщаем об этом пользователю 
        // и продолжаем работу
        Print("Торговый поток свободен! Продолжаем работу...");
      }
    // определяем необходимость входа в рынок
    ...
    // рассчитываем уровни Стоп Лосс, Тейк Профит и размер лота
    ...
    // открываем позицию
    if(OrderSend(...) < 0) 
        Alert("Ошибка открытия позиции № ", GetLastError());
    return(0);
  }
В этом примере проверка состояния торгового потока происходит в самом начале функции start(). Это ошибочное решение - за время, потраченное экспертом на расчёты (необходимость входа в рынок, уровни Стоп Лосс, Тейк Профит, размер лота и т.п.), торговый поток может быть занят другим экспертом. В этом случае попытка открыть позицию не увенчается успехом.


Пример правильного использования функции:

int start()
  {
    // определяем необходимость входа в рынок
    ...
    // рассчитываем уровни Стоп Лосс, Тейк Профит и размер лота
    ...
    // и только теперь проверяем, свободен ли торговый поток
    if(!IsTradeAllowed())
      {
        Print("Торговый поток занят! Эксперт не может открыть позицию!");
        return(-1);
      }
    else
        Print("Торговый поток свободен! Пытаемся открыть позицию...");
    // если проверка прошла успешно, открываем позицию
    if(OrderSend(...) < 0) 
        Alert("Ошибка открытия позиции № ", GetLastError());
    return(0);
  }
 

    Здесь проверка происходит непосредственно перед открытием позиции, и вероятность того, что другой эксперт "вклинится" между этими двумя действиями намного меньше (но всё равно есть. Об этом будет сказано чуть позже).

    В этом методе есть два существенных недостатка:

  • остаётся вероятность того, что эксперты одновременно сделают проверку, и, получив "зелёный свет", будут одновременно пытаться торговать
  • если проверка завершится неудачно, следующий раз эксперт будет пытаться торговать только на следующем тике. А такая задержка ничем не оправдана.

    Вторую проблему решить достаточно просто - просто надо "ждать", пока торговый поток освободится. Тогда эксперт начнёт торговать сразу после того, как закончит другой эксперт.

    Выглядеть это будет примерно так:

int start()
  {
    // определяем необходимость входа в рынок
    ...
    // рассчитываем уровни Стоп Лосс, Тейк Профит и размер лота
    ...
    // проверяем, свободен ли торговый поток
    if(!IsTradeAllowed())
      {
        Print("Торговый поток занят! Ждём, пока он освободиться...");
        // бесконечный цикл
        while(true)
          {
            // если эксперт был остановлен пользователем, прекращаем работу
            if(IsStopped()) 
              { 
                Print("Эксперт был остановлен пользователем!"); 
                return(-1); 
              }
            // если торговый поток освободился, выходим из цикла и переходим к торговле
            if(IsTradeAllowed())
              {
                Print("Торговый поток освободился!");
                break;
              }
            // если ни одно из условий остановки цикла не сработало, "ждём" 0,1 секунды
            // и начинаем проверку сначала
            Sleep(100);
          }
      }
    else
        Print("Торговый поток свободен! Пытаемся открыть позицию...");
    // пытаемся открыть позицию
    if(OrderSend(...) < 0) 
        Alert("Ошибка открытия позиции № ", GetLastError());
    return(0);
  }
    В текущей реализации у нас опять есть проблемные места:
  •  во-первых, поскольку функция IsTradeAllowed() отвечает не только за состояние торгового потока, но и за "галочку", разрешающую эксперту торговать, эксперт может "зависнуть" в бесконечном цикле, и остановится, только если его вручную удалят с графика
  •  во-вторых, если эксперт будет ждать освобождения торгового потока хотя бы секунду, цены могут измениться и торговать по ним уже нельзя - необходимо обновить данные и пересчитать уровни открытия, Стоп Лосс и ТейкПрофит будущей позиции.

    Код, с учётом исправлений, будет выглядеть так:

// время (в секундах), в течение которого эксперт будет ждать освобождения торгового 
// потока (если он занят)
int MaxWaiting_sec = 30;
int start()
  {
    // определяем необходимость входа в рынок
    ...
    // рассчитываем уровни Стоп Лосс, Тейк Профит и размер лота
    ...
    // проверяем, свободен ли торговый поток
    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("Торговый поток освободился!");
                // обновляем рыночную информацию
                RefreshRates();
                // пересчитываем уровни Стоп Лосс и Тейк Профит
                ...
                // выходим из цикла и переходим к торговле                
                break;
              }
            // если ни одно из условий остановки цикла не сработало, "ждём" 0,1 
            // секунды и начинаем проверку сначала
            Sleep(100);
          }
      }
    else
        Print("Торговый поток свободен! Пытаемся открыть позицию...");

    // пытаемся открыть позицию
    if(OrderSend(...) < 0) 
        Alert("Ошибка открытия позиции № ", GetLastError());
 
    return(0);
  }
    В этом примере добавлено:
  • обновление рыночной информации (RefreshRates()) и последующий пересчёт уровней СЛ и ТП
  • максимальное время ожидания MaxWaiting_sec, при превышении которого эксперт прекратит работу

    В таком виде этот код уже можно использовать в своих экспертах.

    Последний штрих - "вынесем" всё, что касается проверки, в отдельную функцию. Это облегчит её интеграцию в эксперты и упростит использование.

/////////////////////////////////////////////////////////////////////////////////
// int _IsTradeAllowed( int MaxWaiting_sec = 30 )
//
// функция определяет состояние торгового потока. Коды возвратов:
//  1 - торговый поток свободен, можно торговать
//  0 - торговый поток был занят, но освободился. Торговать можно только после 
//      обновления рыночной информации.
// -1 - торговый поток занят, ожидание прервано пользователем (эксперт удалён с 
//      графика, закрыт терминал, изменился период и/или символ графика, ... )
// -2 - торговый поток занят, истекло максимальное время ожидания (MaxWaiting_sec). 
//      Возможно, эксперту запрещена торговля (галочка "Разрешить эксперту торговать" 
//      в настройках эксперта).
//
// MaxWaiting_sec - время (в секундах), в течении которого функция будет ждать 
// освобождения торгового потока (если он занят). По умолчанию = 30.
/////////////////////////////////////////////////////////////////////////////////
int _IsTradeAllowed(int 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);
      }
  }

 

Шаблон эксперта, использующего функцию:

int start()
  {
    // определяем необходимость входа в рынок
    ...
    // рассчитываем уровни Стоп Лосс, Тейк Профит и размер лота
    ...
    // проверяем, свободен ли торговый поток
    int TradeAllow = _IsTradeAllowed();
    if(TradeAllow < 0) 
      { 
        return(-1); 
      }
    if(TradeAllow == 0)
      {
        RefreshRates();
        // пересчитываем уровни Стоп Лосс и Тейк Профит
        ...
      }
    // открываем позицию
    if(OrderSend(...) < 0) 
        Alert("Ошибка открытия позиции № ", GetLastError());
    return(0);
  }
    Сделаем некоторые выводы:

    Функция IsTradeAllowed() проста в использовании, и идеально подходит для разграничения доступа к торговому потоку при одновременной работе двух-трёх экспертов. Из-за недостатков, которые в ней присутствуют, её использование при работе большего количества экспертов не гарантирует отсутствие ошибки 146 и может вызвать "зависание" эксперта при отключённой галочке "Разрешить эксперту торговать".

    Именно поэтому мы рассмотрим альтернативный способ решения этой проблемы - использование глобальной переменной в качестве "семафора".

 

3. Глобальные переменные клиентского терминала

    Сначала немножко о понятиях...

    Глобальные переменные клиентского терминала - переменные, доступ к которым есть у всех экспертов, скриптов и индикаторов. Т.е. глобальная переменная, созданная одним экспертом, может быть использована в других экспертах (в нашем случае, для разграничения доступа).

    Для работы с глобальными переменными в языке MQL 4 предусмотрено несколько функций:

  • GlobalVariableCheck() - для проверки, существует ли глобальная переменная
  • GlobalVariableDel() - для удаления глобальной переменной
  • GlobalVariableGet() - для получения значения глобальной переменной
  • GlobalVariableSet() - для создания и изменения значения глобальной переменной
  • GlobalVariableSetOnCondition() - для изменения глобальной переменной с одного значения (указываемого пользователем) на другое. Т.е. отличие от GlobalVariableSet() заключается в том, что новое значение будет присвоено только при определённом старом значении. Именно эта функция и является ключевой для создания семафора.
  • GlobalVariablesDeleteAll() - для удаления всех глобальных переменных (не знаю, кому может такое понадобиться:)

    Почему необходимо использовать функцию GlobalVariableSetOnCondition(), а не комбинацию функций GlobalVariableGet() и GlobalVariableSet()? Да всё по тем же причинам - между использованием 2-х функций может пройти какое-то время. И другой эксперт имеет шанс "вклиниться" в процесс переключения семафора. Нам же этого допустить нельзя.

 

4. Основная идея семафора

    Эксперт, который хочет торговать, должен проверить состояние семафора. Если на семафоре "красный свет" (глобальная переменная = 1), значит уже торгует другой эксперт, и надо подождать. Если же на семафоре "зелёный свет" (глобальная переменная = 0), можно сразу приступать к торговле (не забыв установить "красный свет" для других экспертов).

    Итого, нам надо создать 2 функции - одну для установки "красного света", и одну для установки "зелёного света". Задача на первый взгляд простая. Но не будем торопиться с выводами, а лучше попробуем сформулировать последовательность выполняемых действий для каждой функции (назовём их TradeIsBusy() и TradeIsNotBusy()) и, собственно, реализуем их.

 

5. Функция TradeIsBusy()

    Как уже говорилось, основной задачей функции будет ожидание появления "зелёного света" и включение "красного света". Кроме того, нам необходимо проверять, существует ли глобальная переменная, и создавать её, в случае, если её нет. Эту проверку логичнее (и экономнее) было бы делать из функции init() эксперта. Но тогда существовала бы вероятность, что пользователь её удалит, и все работающие в тот момент эксперты не смогут торговать. Поэтому мы разместим её в теле создаваемой функции.

    Все эти действия должны быть сопровождены выводом информации и обработкой ошибок, возникших при работе с глобальной переменной. Также не стоит забывать о "зависании" - время работы функции должно быть ограничено.

    Вот, что у нас должно получиться:

/////////////////////////////////////////////////////////////////////////////////
// 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)
/////////////////////////////////////////////////////////////////////////////////
int TradeIsBusy( int MaxWaiting_sec = 30 )
  {
    // при тестировании нет смысла в разделении торгового потока - просто завершаем 
    // работу функции
    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);
          }
        // проверяем, существует ли гл. переменная
        // если она есть, выходим из этого цикла и переходим к блоку изменения 
        // значения TradeIsBusy
        if(GlobalVariableCheck( "TradeIsBusy" )) 
            break;
        else
        // если GlobalVariableCheck вернула FALSE, значит либо переменной нет, либо 
        // при проверке возникла ошибка
          {
            _GetLastError = GetLastError();
            // если это всё таки ошибка, выводим информацию, ждём 0,1 секунды и 
            // начинаем проверку сначала
            if(_GetLastError != 0)
             {
              Print("TradeIsBusy()-GlobalVariableCheck(\"TradeIsBusy\")-Error #",
                    _GetLastError );
              Sleep(100);
              continue;
             }
          }
        // если ошибки нет, значит глобальной переменной просто нет, пытаемся создать
        // её
        // если GlobalVariableSet > 0, значит глобальная переменная успешно создана. 
        // Выходим из ф-ции
        if(GlobalVariableSet( "TradeIsBusy", 1.0 ) > 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
     // если нам это удаётся, выходим из ф-ции, возвращая 1 - "успешное завершение"
     if(GlobalVariableSetOnCondition( "TradeIsBusy", 1.0, 0.0 )) 
         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);
     Comment("");
    }
  }

    Тут вроде бы всё понятно:

  • проверка существования глобальной переменной и, в случае неудачи, её создание
  • попытка изменить значение глобальной переменной с 0 на 1. Сработает только если её значение будет = 0.

    Функция может работать максимум MaxWaiting_sec секунд и не препятствует удалению эксперта с графика.
    Информация о всех возникающих ошибках выводится в журнал.

 

6. Функция TradeIsNotBusy()

    Функция TradeIsNotBusy выполняет обратную задачу - включает "зелёный свет".

    Она не имеет ограничения по времени работы и не может быть остановлена пользователем. Мотивация достаточно простая - если не включить "зелёный свет", ни один эксперт не сможет торговать.

    Естественно, и кодов возврата у неё нет - результатом может быть только успешное завершение.

    Вот как она выглядит:

/////////////////////////////////////////////////////////////////////////////////
// void TradeIsNotBusy()
//
// Функция устанавливает значение глобальной переменной TradeIsBusy = 0.
// Если глобальной переменной TradeIsBusy не существует, функция создаёт её.
/////////////////////////////////////////////////////////////////////////////////
void TradeIsNotBusy()
  {
    int _GetLastError;
    // при тестировании нет смысла в разделении торгового потока - просто завершаем 
    // работу функции
    if(IsTesting()) 
      { 
        return(0); 
      }
    while(true)
      {
        // если эксперт был остановлен пользователем, прекращаем работу
        if(IsStopped()) 
          { 
            Print("Эксперт был остановлен пользователем!"); 
            return(-1); 
          }
        // пытаемся установить значение гл. переменной = 0 (или создать гл. 
        // переменную)
        // если GlobalVariableSet вернула значение > 0, значит всё закончилось 
        // хорошо. Выходим из ф-ции
        if(GlobalVariableSet( "TradeIsBusy", 0.0 ) > 0) 
            return(1);
        else
        // если GlobalVariableSet вернула значение <= 0, значит возникла ошибка. 
        // Выводим информацию, ждём, и пробуем ещё раз
         {
         _GetLastError = GetLastError();
         if(_GetLastError != 0 )
           Print("TradeIsNotBusy()-GlobalVariableSet(\"TradeIsBusy\",0.0)-Error #", 
                 _GetLastError );
         }
        Sleep(100);
      }
  }

7. Интеграция в экспертов и использование

    Теперь у нас есть 3 функции для разграничения доступа к торговому потоку. Для облегчения их интеграции в экспертов можно создать файл TradeContext.mq4 и включать его директивой #include (файл прикреплён).

    Шаблон эксперта, использующего функции TradeIsBusy() и TradeIsNotBusy():

#include <TradeContext.mq4>
 
int start()
  {
    // определяем необходимость входа в рынок
    ...
    // рассчитываем уровни Стоп Лосс, Тейк Профит и размер лота
    ...
    // ждём освобождения торгового потока и занимаем его (если произошла ошибка, 
    // выходим)
    if(TradeIsBusy() < 0) 
        return(-1); 
    // обновляем рыночную информацию
    RefreshRates();
    // пересчитываем уровни Стоп Лосс и Тейк Профит
    ...
    // открываем позицию
    if(OrderSend(...) < 0) 
      { 
        Alert("Ошибка открытия позиции № ", GetLastError()); 
      }

    // освобождаем торговый поток
    TradeIsNotBusy();

    return(0);
  }
 

    В использовании функций TradeIsBusy() и TradeIsNotBusy() может возникнуть только одна проблема - если после того, как торговый поток будет занят, эксперта удалить с графика, переменная TradeIsBusy останется равной 1. Другие эксперты после этого торговать не смогут.

    Решается проблема просто - не надо удалять эксперта с графика, если он торгует ;)

    Также возможна ситуация, что переменная TradeIsBusy не обнуляется при критическом завершении работы терминала. В этом случае помогает использование функции TradeIsNotBusy() из функции init() эксперта.

    Ну, и в любой момент значение переменной можно поменять вручную - кнопка F3 в терминале ( это недокументированная возможность запретить всем экспертам торговать ;)


komposter (komposterius@mail.ru), 2006.04.11

Прикрепленные файлы |
TradeContext.mqh (11.54 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (27)
Andrey Khatimlianskii
Andrey Khatimlianskii | 22 сент. 2009 в 01:06
MrSoros:
Andrey:
В использовании функций TradeIsBusy() и TradeIsNotBusy() может возникнуть только одна проблема - если после того, как торговый поток будет занят, эксперта удалить с графика, переменная TradeIsBusy останется равной 1. Другие эксперты после этого торговать не смогут.
А если в deinit прописать освобождение торгового потока? Разве эта проблема не решится?

Если удаление с графика будет штатным, сработает функция TradeIsNotBusy() и торговый поток освободится.

Речь об аварийном завершении работы - в случае ожидания ответа от торгового сервера или при жесткой перезагрузке компьютера (reset).

Oleg
Oleg | 3 янв. 2010 в 20:47

Допустим два Советника торгуют одновременно (по разным валютам).

В какой-то момент времени 1-й начал открывать новый ордер, заняв поток, а второй в это время

должен изменить уже открытый ордер. В результате, если нет проверок свободен ли поток,

появится ошибка (кажется) 146.

- Что именно происходит в этот момент с потоком? Ошибку выдает сервер брокера или МТ4 на

компьютере трейдера? (чем останавливается сигнал второго Советника?)


Спрашиваю, т.к. если это локальная ошибка и брокеру не мешает, то видимо в худшем случае

это приведет лишь к задержке сигнала 2-го Советника? (интересует лишь насколько подобное

явление может помешать брокеру)

Спасибо!

Andrey Khatimlianskii
Andrey Khatimlianskii | 4 янв. 2010 в 23:01
chief2000:

Допустим два Советника торгуют одновременно (по разным валютам).

В какой-то момент времени 1-й начал открывать новый ордер, заняв поток, а второй в это время

должен изменить уже открытый ордер. В результате, если нет проверок свободен ли поток,

появится ошибка (кажется) 146.

- Что именно происходит в этот момент с потоком? Ошибку выдает сервер брокера или МТ4 на

компьютере трейдера? (чем останавливается сигнал второго Советника?)


Спрашиваю, т.к. если это локальная ошибка и брокеру не мешает, то видимо в худшем случае

это приведет лишь к задержке сигнала 2-го Советника? (интересует лишь насколько подобное

явление может помешать брокеру)

Спасибо!

Зачем такой крупный шрифт?

Насколько мне известно, ошибку 146 генерирует терминал, брокеру запрос не отправляется.

Но зачем ее получать, если есть механизм проверки торгового потока?

Oleg
Oleg | 5 янв. 2010 в 02:23
komposter:
chief2000:


Зачем такой крупный шрифт?

Насколько мне известно, ошибку 146 генерирует терминал, брокеру запрос не отправляется.

Но зачем ее получать, если есть механизм проверки торгового потока?


- По поводу шрифта - это к админу, так сайт иногда работает с Хромом (Google Chrome) - "zoom in" окна воспринимает за крупный шрифт.

- Я добавил условие проверки свободен ли поток, по рабоче-крестьянски, без заморочек, но есть совсем маленький шанс что два Советника с разных

валютных пар столкнутся в одно и то же мгновение. Если один из них будет остановлен терминалом (не брокером) то это приемлемо.

Сейчас торгую на Демо (6 Советников, кажется 7 сделок + изменения ордеров) - за день, после добавления проверки, пока ни одной ошибки.

Спасибо!

[Удален] | 31 мая 2012 в 09:52
Здравствуйте.Помогите пожалуйста понять причину ошибок. На VPS у меня установлен один терминал с одним советником. Руками не работаю,советник сам работает. Когда приобрела VPS и переустановила терминал (так как в forex4you было обновление терминалов) стали появляться очень,очень часто ошибки. Обратилась forex4you,послали на VPS. Обратилась в VPS,они не знают проблему и послали сюда,на этот сайт.Что может вызывать такие ошибки, VPS или терминал? Помогите пожалуйста понять проблему,так как я несу из за этих сбоев убытки. 1 ошибка- TradeDispatcher: trade context is busy 2 ошибка- "cannot login connection" Состояние соединения,внизу,справа, меняю и не помогает.
Требования к статьям для публикации на MQL4.com Требования к статьям для публикации на MQL4.com
Требования к статьям для публикации на сайте MQL 4 Community
Оценка качества моделирования минутных данных Оценка качества моделирования минутных данных
Формула расчёта и оценка качества моделирования минутных данных.
Пауза между торговыми операциями Пауза между торговыми операциями
Статья посвящена организации паузы между торговыми операциями при работе нескольких экспертов на одном терминале МТ 4 и рассчитана на пользователя, обладающего базовыми навыками работы с терминалом и программирования на MQL 4.
Пример создания эксперта Пример создания эксперта
Принципы построения пользовательских программ на языке MQL 4 рассматриваются на примере создания простейшей экспертной системы на основе стандартного индикатора MACD.