IsTradeAllowed versus IsTradeContextBusy

 
Тема старая. Никак не найдет своего завершения.

Как же, все-таки, узнать, разрешено-ли советнику торговать, или IsTradeAllowed() натыкается на залоченный мутекс торгового потока?

Документация:
bool IsTradeContextBusy( )
Возвращается TRUE, если поток для выполнения торговых операций занят, иначе возвращает FALSE.
См. также IsTradeAllowed().
bool IsTradeAllowed( )
Возвращается TRUE, если эксперту разрешено торговать и поток для выполнения торговых операций свободен, иначе возвращает FALSE.
См. также IsDllsAllowed(), IsLibrariesAllowed(), IsTradeContextBusy().
Последний вызов, очевидно, обладает избыточностью и может выдать неверную информацию, вернее, не ту, которую можно было бы от него ожидать, в случае одновременной торговли несколькими экспертами в одном терминале.

Можно, конечно, сделать уточнение типа
if (!IsTradeAllowed() && !IsTradeContextBusy())
   Print("Trade flag is not set");



Но, во-первых, это не позволяет с уверенностью отловить обратную ситуацию, когда торговля запрещена вне зависимости от состояния торгового потока;

Во-вторых, thread safety. Мутекс может быть залочен между вызовами (теоретически), в результате имеем undefined behaviour, источник очень многих "необъяснимых" ошибок;

Ну и, в-третьих, просто криво.

Почему бы не разделить функции? Одна строго читает состояние флага, другая - состояние мутекса?

 
bool IsExpertEnabled( )
Возвращает TRUE, если в клиентском терминале разрешен запуск экспертов, иначе возвращает FALSE.
Пример:
while(!IsStopped())
{
...
if(!IsExpertEnabled()) break;
}


 
Функциональность IsTradeAllowed не тронута из соображений совместимости. Через несколько билдов мы это поправим. Кстати, Ваш код
if (!IsTradeAllowed() && !IsTradeContextBusy())
   Print("Trade flag is not set");


правильный и будет работать в любом случае. Лично я его немного изменил бы из-за расширенной функциональности IsTradeAllowed

if (!IsTradeContextBusy() && !IsTradeAllowed())
   Print("Trade flag is not set");
 
bool IsExpertEnabled( )

Нет, этот запрещает запуск хандлера тиков.

А мне нужен тот, который не дает торговать, заставляя торговые функции вываливаться по
ERR_TRADE_NOT_ALLOWED 4109 Торговля не разрешена
а эксперт продолжает все считать и рисовать.


Через несколько билдов мы это поправим. Кстати, Ваш код правильный и будет работать в любом случае. Лично я его немного изменил бы из-за расширенной функциональности IsTradeAllowed

Спасибо.
Хотя MQL в любом случае делает оба вызова, порядок здесь, в отличие от си, не важен, так ведь?
 

Чтобы избавиться от ошибки "Торговый поток занят", перед каждой торговой операцией в советнике добавил проверку:

 while(IsTradeContextBusy()) {Print("Торговый поток занят. Ждём 300мс"); Sleep(300);}

 Однако ошибка всё равно возникает. И в журнале такого сообщения я не нашёл ни одного. В чём может быть ошибка и как исправить?

 
Vladimir Erofeev:

 Однако ошибка всё равно возникает.

Какая именно ошибка? Как проверяете, что возникает какая-то ошибка?

И в журнале такого сообщения я не нашёл ни одного.

Какого "такого"? Если имеете в виду, что возникает ошибка 146, то как Вы это поняли при том, что "такого сообщения не нашел"?

 
Ihor Herasko:

Какая именно ошибка? Как проверяете, что возникает какая-то ошибка?

Какого "такого"? Если имеете в виду, что возникает ошибка 146, то как Вы это поняли при том, что "такого сообщения не нашел"?

В журнале искал своё сообщение "Торговый поток занят. Ждём 300мс" - не нашёл. Но сообщения об ошибке при модификации/устновке/удалении "[Trade context is busy]" возникают, в журнале они есть.
 
Vladimir Erofeev:
В журнале искал своё сообщение "Торговый поток занят. Ждём 300мс" - не нашёл. Но сообщения об ошибке при модификации/устновке/удалении "[Trade context is busy]" возникают, в журнале они есть.
По всей видимости, не перед каждой торговой операцией производится проверка доступности торгового потока. Посмотрите еще раз внимательно или приложите более полный код. Возможно, со стороны будет виднее.
 
Ihor Herasko:
По всей видимости, не перед каждой торговой операцией производится проверка доступности торгового потока. Посмотрите еще раз внимательно или приложите более полный код. Возможно, со стороны будет виднее.

Давайте посмотрим. На счёте работает один советник, но на многих графиках. Блок советника для модификации ордеров:

 

while(IsTradeContextBusy()) {Print("Торговый поток занят. Ждём 300мс"); Sleep(300);}
            
            res=OrderModify(ticket,newSL_and_TP[i][3],newSL_and_TP[i][1],newSL_and_TP[i][2],0);
            if(!res)// не удалось модифицировать
              {
               Print("Ордер #",ticket," модифицировать не удалось. Ошибка ",GetLastError());
               // дальнейшая обработка ситуации
              }

Записи журнала:

2016.04.07 14:59:34.113 '3197085': modification of order #95887288 sell 1.25 GBPUSD at 1.41068 sl: 1.41048 tp: 0.00000 -> sl: 1.40840 tp: 0.00000 failed [Trade context is busy]

2016.04.07 14:59:34.113 '3197085': modification of pending order #95914768 buy stop 0.35 GBPUSD at 1.41576 sl: 1.41318 tp: 0.00000 -> price: 1.41580 sl: 1.41318 tp: 0.00000 failed [Trade context is busy]

2016.04.07 14:59:34.133 '3197085': modification of pending order #95870277 sell stop 0.18 GBPUSD at 1.40050 sl: 1.40560 tp: 0.00000 -> price: 1.40050 sl: 1.40562 tp: 0.00000 failed [Trade context is busy]

Соответствующие записи журнала экспертов:

2016.04.07 14:59:34.113 ТС3 GBPUSD,H1: Ордер #95887288 модифицировать не удалось. Ошибка 146

2016.04.07 14:59:34.113 ТС3 GBPUSD,H1: Ордер #95914768 модифицировать не удалось. Ошибка 146

2016.04.07 14:59:34.133 ТС3 GBPUSD,H4: Ордер #95870277 модифицировать не удалось. Ошибка 146

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

 
Vladimir Erofeev:

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

В своё время специально для таких случаев мы добавили функцию GlobalVariableSetOnCondition

Захватываете переменную в монопольное использование. Проводите торговую операцию. Отпускаете переменную

 
Vladimir Erofeev:

2016.04.07 14:59:34.113 '3197085': modification of order #95887288 sell 1.25 GBPUSD at 1.41068 sl: 1.41048 tp: 0.00000 -> sl: 1.40840 tp: 0.00000 failed [Trade context is busy]

2016.04.07 14:59:34.113 '3197085': modification of pending order #95914768 buy stop 0.35 GBPUSD at 1.41576 sl: 1.41318 tp: 0.00000 -> price: 1.41580 sl: 1.41318 tp: 0.00000 failed [Trade context is busy]

2016.04.07 14:59:34.133 '3197085': modification of pending order #95870277 sell stop 0.18 GBPUSD at 1.40050 sl: 1.40560 tp: 0.00000 -> price: 1.40050 sl: 1.40562 tp: 0.00000 failed [Trade context is busy]

Соответствующие записи журнала экспертов:

2016.04.07 14:59:34.113 ТС3 GBPUSD,H1: Ордер #95887288 модифицировать не удалось. Ошибка 146

2016.04.07 14:59:34.113 ТС3 GBPUSD,H1: Ордер #95914768 модифицировать не удалось. Ошибка 146

2016.04.07 14:59:34.133 ТС3 GBPUSD,H4: Ордер #95870277 модифицировать не удалось. Ошибка 146

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

Понятно, в чем дело. Один и тот же советник, представленный несколькими копиями, работает на одном и том же символе. В итоге все копии начинают обрабатывать событие Tick одновременно. Логично, что перед совершением торговой операции все они получают информацию о свободности торгового потока. Затем первые 8 (в МТ4 вроде бы расширили количество торговых потоков до 8) из них успешно модифицируют свои ордера, а остальные получают отказ.

Решить проблему можно  только путем уведомления других экспертов о том, что другая копия совершает торговую операцию. Например, можно сделать счетчик экспертов, совершающих в данный момент торговую операцию. Если счетчик равен 8, то другие эксперты не должны пытаться совершать торговые операции.
Причина обращения: