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 Стан з'єднання, внизу, праворуч, міняю і не допомагає.