Ошибка 146

 

Есть прекрасная статья в которой автор создает функцию для проверки торгового потока https://www.mql5.com/ru/articles/1412 

Вот пример проверки со статьи

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

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

    return(0);
  }

  У меня советник открывает две позиции в одном направлении с разными стопами. Вопрос: нужно ставить две проверки торгового потока, так как две сделки, или можно открывать после первой проверки ???

Ошибка 146 ("Торговый поток занят") и как с ней бороться
Ошибка 146 ("Торговый поток занят") и как с ней бороться
  • 2006.05.12
  • Andrey Khatimlianskii
  • www.mql5.com
Статья посвящена бесконфликтной торговле нескольких экспертов на одном терминале МТ 4 и рассчитана на пользователя, обладающего базовыми навыками работы с терминалом и программирования на MQL 4.
 
Provider_Signal:

Есть прекрасная статья в которой автор создает функцию для проверки торгового потока https://www.mql5.com/ru/articles/1412 

Вот пример проверки со статьи

  У меня советник открывает две позиции в одном направлении с разными стопами. Вопрос: нужно ставить две проверки торгового потока, так как две сделки, или можно открывать после первой проверки ???

Перед совершением любой торговой операции нужно убедиться в том что:

  1. Автоторговля разрешена (нажата кнопка автоторговля). IsExpertsEnabled()
  2. Торговый поток свободен. IsTradeAllowed()
  3. Программа оперирует актуальным рыночным окружением. RefreshRates() и получение других рыночных параметров.
  4. Торговая операция передает корректные параметры. Проверка стопов, профитов, цен открытия времени истечения ордеров.

 
Andrey Khatimlianskii:
Эта проверка уже несколько лет не актуальна. Статья тоже.
а как делать ? Что актуально ?
 
Andrey Khatimlianskii:
Эта проверка уже несколько лет не актуальна. Статья тоже.
Андрей, актуальна. Попробуйте запустить в терминале штук 20 советников, открывающих сделки в начале каждой новой свечи. Без проверки ошибки полезут.
 
Provider_Signal:

Есть прекрасная статья в которой автор создает функцию для проверки торгового потока https://www.mql5.com/ru/articles/1412 

Вот пример проверки со статьи

  У меня советник открывает две позиции в одном направлении с разными стопами. Вопрос: нужно ставить две проверки торгового потока, так как две сделки, или можно открывать после первой проверки ???

Разве OrderSend() возвращает integer?

if(OrderSend(...) < 0)

 

По моему должно быть bool 

 
prostotrader:

Разве OrderSend() возвращает integer?

if(OrderSend(...) < 0)

 

По моему должно быть bool 

В MQL4 (о котором сейчас речь) - да, возвращается тикет открытого ордера или -1, если ордер не был открыт. В MQL5 - возвращается bool.
 
Andrey Khatimlianskii:

Никак. Просто не парьтесь торговым потоком, если у вас не 20 советников на открытии бара входят вместе.

 

Сейчас достаточно проверки IsTradeContextBusy() и маленького слипа. Городить семафоры смысла нет.

Гляньте пожалуйста функцию на открытие двух ордеров в одном направлении. Может что-то упустил ?

 

void OrderSendX(int cmd, double stoploss, double takeprofit1, double takeprofit2, string comment)
{
   double price = 0;
  
   if(IsTradeContextBusy())
   {
      Print("Торговый поток занят! Ждём, пока он освободиться...");
      while(true)
      {
         // если эксперт был остановлен пользователем, прекращаем работу
         if(IsStopped())
         {
            Print("Эксперт был остановлен пользователем!");
            return;
         }
         // если торговый поток освободился, выходим из цикла и переходим к торговле
         if(!IsTradeContextBusy())
         {
            break;
         }
         // если ни одно из условий остановки цикла не сработало, "ждём" 0,1 секунды
         // и начинаем проверку сначала
         Sleep(100);
      }
   }

   Print("Торговый поток свободен! Пытаемся открыть позицию 1...");
   // пытаемся открыть позицию
   RefreshRates();
   if(cmd == OP_BUY)  price = Ask;
   if(cmd == OP_SELL) price = Bid;
  
   int ticket1 = OrderSend(Symbol(), cmd, lot, price, 3, stoploss, takeprofit1, comment + "_1", magicNumber, 0, Red);
   if(ticket1<0)
      Print("OrderSend1 завершилась с ошибкой #",GetLastError());

   //--------------------------------------------------------------------------------------------------------------------
  
   if(IsTradeContextBusy())
   {
      Print("Торговый поток занят! Ждём, пока он освободиться...");
      while(true)
      {
         if(IsStopped())
         {
            Print("Эксперт был остановлен пользователем!");
            return;
         }
         if(!IsTradeContextBusy())
         {
            break;
         }
         Sleep(100);
      }
   }
  
   Print("Торговый поток свободен! Пытаемся открыть позицию 2...");
   // пытаемся открыть позицию
   RefreshRates();
   if(cmd == OP_BUY)  price = Ask;
   if(cmd == OP_SELL) price = Bid;
  
   int ticket2 = OrderSend(Symbol(), cmd, lot, price, 3, stoploss, takeprofit2, comment + "_2", magicNumber, 0, Green);
   if(ticket2<0)
    Print("OrderSend2 завершилась с ошибкой #",GetLastError());
  
   return;
}


 

 
Andrey Khatimlianskii:

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

М-мм.. Так ведь об этом я и веду речь - о занятости торгового потока. Возможно, Вы о чем-то другом говорите.
 
Provider_Signal:

Гляньте пожалуйста функцию на открытие двух ордеров в одном направлении. Может что-то упустил ?

Ожидание освобождения торгового потока можно описать лаконичнее:

while (IsTradeContextBusy() && !IsStopped())
{
      Print("Торговый поток занят! Ждём, пока он освободится...");
      Sleep(100);
}

и оформить все это функцией.

Ну а далее по списку. Если, конечно, необходимо сделать все "правильно", с учетом всевозможных ситуаций.

  1. Проверить достаточность средств.
  2. Проверить правильность уровней SL и ТР.
  3. Проверить разрешение торговли в выбранном направлении. Пользователь может запретить эксперту торговать в одном из направлений.
  4. Проверить тот факт, что рынок не закрыт (или разрешена торговля по выбранному символу).
 
 
Andrey Khatimlianskii:

В работе одного советника не может возникнуть конфликта доступа к торговому потоку, все торговые операции синхронные (выполняются последовательно).

Вы рассчитываете на отправку 8-ми торговых приказов из одного терминала одновременно? Тогда все правильно.

Ахах.. ну 8 это уже многовато... ну по 2 с двух разных символов принципе может быть. Но суть я понял, спасибо.

 
Ihor Herasko:

Ожидание освобождения торгового потока можно описать лаконичнее:

while (IsTradeContextBusy() && !IsStopped())
{
      Print("Торговый поток занят! Ждём, пока он освободится...");
      Sleep(100);
}


 Спасибо большое за разъяснение. 

Еще у меня вопрос... как обработать ошибки открытия ордера. Когда ticket<0. 

Цикл на несколько попыток открытия со слипом ?  Да, и можно как-то сообщить пользователю когда пропадает интернет ?

Причина обращения: