Помилка 146 (- торговий потік зайнятий -) і як з нею боротися - статті по mql4

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

З довідки MetaEditor:

Для проведення торгових операцій з експертів і скриптів передбачено всього один потік, який запускається в програмному торговому контексті (контекст автоматичної торгівлі з експертів і скриптів). Тому, якщо цей контекст зайнятий торговою операцією будь-якого експерта, то інший експерт або скрипт не може в цей момент викликати торгові функції через помилку 146 (ERR_TRADE_CONTEXT_BUSY)


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

Найпростіший спосіб визначити, чи вільний торговий потік - використовувати функцію IsTradeAllowed ().
З довідки MetaEditor:

Повертає TRUE, якщо експерту дозволено торгувати, і потік для виконання торгових операцій вільний, інакше повертає FALSE

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

Приклад неправильного використання функції:

У цьому прикладі перевірка стану торгового потоку відбувається в самому початку функції start (). Це помилкове рішення - за час, витрачений експертом на розрахунки (необхідність входу в ринок, рівні Стоп Лосс, Тейк Профіт, розмір лота і т.п.), торговий потік може бути зайнятий іншим експертом. В цьому випадку спроба відкрити позицію не увінчається успіхом.

Приклад правильного використання функції:

Тут перевірка відбувається безпосередньо перед відкриттям позиції, і ймовірність того, що інший експерт "уклиниться" між цими двома діями набагато менше (але все одно є. Про це буде сказано трохи пізніше).

У цьому методі є два суттєвих недоліки:

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

Другу проблему вирішити досить просто - просто треба "чекати", поки торговий потік звільниться. Тоді експерт почне торгувати відразу після того, як закінчить інший експерт.

Виглядати це буде приблизно так:

У поточній реалізації у нас знову є проблемні місця:
  • по-перше, оскільки функція IsTradeAllowed () відповідає не тільки за стан торгового потоку, а й за "галочку", що дозволяє експерту торгувати, експерт може "зависнути" в нескінченному циклі, і зупиниться, тільки якщо його вручну видалять з графіка
  • по-друге, якщо експерт чекатиме звільнення торгового потоку хоча б секунду, ціни можуть змінитися і торгувати по ним вже не можна - необхідно оновити дані і перерахувати рівні відкриття, Стоп Лосс і ТейкПрофіт майбутньої позиції.

Код, з урахуванням виправлень, буде виглядати так:

У цьому прикладі додано:
  • оновлення ринкової інформації (RefreshRates ()) і подальший перерахунок рівнів СЛ і ТП
  • максимальний час очікування MaxWaiting_sec, при перевищенні якого експерт припинить роботу

У такому вигляді цей код вже можна використовувати в своїх експертів.

Останній штрих - "винесемо" все, що стосується перевірки, в окрему функцію. Це полегшить її інтеграцію в експерти і спростить використання.

Шаблон експерта, котрий використовує функцію:

Зробимо деякі висновки:

Функція 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 () експерта. Але тоді існувала б ймовірність, що користувач її видалить, і всі, хто працює в той момент експерти не зможуть торгувати. Тому ми розмістимо її в тілі створюваної функції.

Всі ці дії повинні бути супроводжені висновком інформації і обробкою помилок, що виникли при роботі з глобальної змінної. Також не гає забувати про "зависанні" - час роботи функції повинно бути обмежено.

Ось, що у нас повинно вийти:

Тут начебто все зрозуміло:

  • перевірка існування глобальної змінної і, в разі невдачі, її створення
  • спроба змінити значення глобальної змінної з 0 на 1. Чи спрацює тільки якщо її значення буде = 0.

Ця функція може працювати максимум MaxWaiting_sec секунд і не перешкоджає видаленню експерта з графіка.
Інформація про всіх виникаючих помилках виводиться в журнал.

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

Функція TradeIsNotBusy виконує зворотну задачу - включає "зелене світло".

Вона не має обмеження за часом роботи і не може бути зупинена користувачем. Мотивація досить проста - якщо не включити "зелене світло", жоден експерт не зможе торгувати.

Природно, і кодів повернення у неї немає - результатом може бути тільки успішне завершення.

Ось як вона виглядає:

7. Інтеграція в експертів і використання

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

Шаблон експерта, котрий використовує функції TradeIsBusy () і TradeIsNotBusy ():

У використанні функцій TradeIsBusy () і TradeIsNotBusy () може виникнути тільки одна проблема - якщо після того, як торговий потік буде зайнятий, експерта видалити з графіка, змінна TradeIsBusy залишиться рівною 1. Інші експерти після цього торгувати не зможуть.

Вирішується проблема просто - не треба видаляти експерта з графіка, якщо він торгує;)

Також можлива ситуація, що змінна TradeIsBusy НЕ обнуляється при критичному завершення роботи терміналу. У цьому випадку допомагає використання функції TradeIsNotBusy () з функції init () експерта.

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

Навіщо такий великий шрифт? Наскільки мені відомо, помилку 146 генерує термінал, брокеру запит не надсилається. Але навіщо її отримувати, якщо є механізм перевірки торгового потоку?

- З приводу шрифту - це до адміну, так сайт іноді працює з Хромом (Google Chrome) - zoom in вікна сприймає за великий шрифт. - Я додав умова перевірки чи вільний потік, по робітничо-селянському, без проблем, але є зовсім маленький шанс що два Радника з різних валютних пар зіткнуться в один і той же мить. Якщо один з них буде зупинений терміналом (НЕ брокером) то це прийнятно. Зараз торгую на Демо (6 Радників, здається 7 угод + зміни ордерів) - за день, після додавання перевірки, поки жодної помилки. Дякуємо!

Здравствуйте.Помогіте ласка зрозуміти причину помилок. На VPS у мене встановлений один термінал з одним радником. Руками не працюю, радник сам працює. Коли придбала VPS і перевстановити термінал (так як в forex4you було оновлення терміналів) стали з'являтися дуже, дуже часто помилки. Звернулася forex4you, послали на VPS. Звернулася в VPS, вони не знають проблему і послали сюди, на цей сайт.Что може викликати такі помилки, VPS або термінал? Допоможіть будь ласка зрозуміти проблему, так як я несу через цих збоїв збитки. 1 помилка- TradeDispatcher: trade context is busy 2 помилка- can not login connection Стан з'єднання, внизу, праворуч, міняю і не допомагає.

Схожі статті