Что возвращает функция OrderSend() и стоит ли доверять возвращаемому значению?

 

Я знал о том, что если функция OrderSend() возвращает true, то это не свидетельствует об успешном выполнении торговой операции. Но оказалось, что верно и обратное утверждение, если функция OrderSend() возвращает false, то это не свидетельствует также и о неуспешном выполнении торговой операции. Получается, неважно что возвращает функция OrderSend(), все равно надо копать глубже, анализировать поля структуры result. и выяснять уже по вторичным половым признакам — состоялась или нет передача ордера на биржу.

Недавний пример, 2 июня 2016 г., в 13:45:54, робот отправляет на сервер рыночный ордер на продажу 1 лот  Si-6.16 с помощью функции OrderSend(). Однако функция OrderSend() возвращает false. Вот небольшой код, который выполняет и контролирует отправку ордера на биржу:

   ResetLastError();

   if (!OrderSend(sTradeRequest, sTradeResult)) {
      err=GetLastError();
      Print("Структура торгового запроса не прошла базовую проверку, error=",  err, " ", ErrorToString(err));
      return(0);
   }



В результате в журнал поступает сообщение: "13:45:54.611 Si-6.16 sell 1 лот. Структура торгового запроса не прошла базовую проверку, error=4756 Не удалось отправить торговый запрос."

Однако, каким-то непонятным способом ордер все-таки попадает на биржу, что подтверждается приведенными ниже выписками из таблицы ордеров и сделок:


2016.06.02 13:45:59 #36796287 Si-6.16 sell 1.00 / 1.00 market 2016.06.02 13:45:59 filled

2016.06.02 13:45:59 #25905779 sell 1.00  67159 #36796287

Вопрос разработчикам, исправление функции OrderSend() в анонсированной бете-версии на MetaQuotes-Demo от пятницы 3 июня, решает эту проблему или она остается?

 

 

Есть одна непонятка. Данный код, по-хорошему, должен бы быть обложен некоторой логикой обработки ошибок и в случае ошибки с данным кодом, по идее запрос должен повторяться. К сожалению, про этот контекст ничего не сказано.

 
Stanislav Korotky: Есть одна непонятка. Данный код, по-хорошему, должен бы быть обложен некоторой логикой обработки ошибок и в случае ошибки с данным кодом, по идее запрос должен повторяться. К сожалению, про этот контекст ничего не сказано.
Советник на следующем тике вновь проверит условия для входа в рынок и если условия сохраняются, советник повторит отправку ордера. Кстати, в тот день так и произошло, через несколько секунд советник повторил отправку ордера, функция OrderSend() вернула как и должна была true и ордер был успешно принят и исполнен. В результате вместо планового открытия одного лота, открылось два...

Но речь сейчас не про контекст, а про то, почему функция OrderSend() вернула false, если ордер все таки попал на биржу и был исполнен. Получается, что сервер дезинформировал робота...

 
Eugene Myzrov:
...

В результате в журнал поступает сообщение: "13:45:54.611 Si-6.16 sell 1 лот. Структура торгового запроса не прошла базовую проверку, error=4756 Не удалось отправить торговый запрос."

Однако, каким-то непонятным способом ордер все-таки попадает на биржу, что подтверждается приведенными ниже выписками из таблицы ордеров и сделок:


2016.06.02 13:45:59 #36796287 Si-6.16 sell 1.00 / 1.00 market 2016.06.02 13:45:59 filled

2016.06.02 13:45:59 #25905779 sell 1.00  67159 #36796287

Вопрос разработчикам, исправление функции OrderSend() в анонсированной бете-версии на MetaQuotes-Demo от пятницы 3 июня, решает эту проблему или она остается?

 

А Вы точно уверены, что идёт речь об одном и том-же ордере? Посмотрите на время - разница ПЯТЬ секунд. И это на бирже. Очень много, это больше похоже на повторную отправку. И, ещё, когда Вы успешно совершаете торговую операция через OrderSend() Вы это не протоколируете.

Можно посмотреть журнал терминала начиная со времени  2016.06.02 13:45:50? И ещё: на каком сервере идёт торговля: на реальном или демо?

 
Karputov Vladimir: А Вы точно уверены, что идёт речь об одном и том-же ордере? Посмотрите на время - разница ПЯТЬ секунд. И это на бирже. Очень много, это больше похоже на повторную отправку. И, ещё, когда Вы успешно совершаете торговую операция через OrderSend() Вы это не протоколируете. Можно посмотреть журнал терминала начиная со времени  2016.06.02 13:45:50? И ещё: на каком сервере идёт торговля: на реальном или демо?
Торговля ведется через брокера "OPEN" на реальном счете. Вот запрашиваемый кусок журнала, сделка, о которой идет речь, выделена синим цветом. 


JL    0    13:45:21.783    Trades    'XXXXX': exchange buy 2.00 Si-6.16 at market
GD    0    13:45:21.911    Trades    'XXXXX': exchange buy 2.00 Si-6.16 at market placed for execution in 128 ms
GQ    0    13:45:21.932    Trades    'XXXXX': cancel order #36795985 buy limit 1.00 Si-6.16 at 67101 (67101)
HM    0    13:45:21.959    Trades    'XXXXX': deal #25905759 buy 2.00 Si-6.16 at 67187 done (based on order #36796236)
JO    0    13:45:21.959    Trades    'XXXXX': cancel order #36795985 buy limit 1.00 Si-6.16 at 67101 (67101) placed for execution in 27 ms
HN    0    13:45:22.135    Trades    'XXXXX': sell limit 1.00 Si-6.16 at 67277 (67277)
KD    0    13:45:22.216    Trades    'XXXXX': sell limit 1.00 Si-6.16 at 67277 (67277) placed for execution in 80 ms
JM    0    13:45:54.519    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market placed for execution in 98 ms
GM    0    13:45:54.521    Trades    'XXXXX': deal #25905779 sell 1.00 Si-6.16 at 67159 done (based on order #36796287)
OS    0    13:45:54.611    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market
LH    0    13:45:54.614    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market
JQ    0    13:45:54.682    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market placed for execution in 68 ms
GQ    0    13:45:54.740    Trades    'XXXXX': deal #25905780 sell 1.00 Si-6.16 at 67160 done (based on order #36796288)
IG    0    13:45:55.026    Trades    'XXXXX': buy limit 1.00 Si-6.16 at 67148 (67148)
QN    0    13:45:55.104    Trades    'XXXXX': buy limit 1.00 Si-6.16 at 67148 (67148) placed for execution in 77 ms
JR    0    13:46:51.640    Trades    'XXXXX': deal #25905798 buy 1.00 Si-6.16 at 67148 done (based on order #36796289)
HP    0    13:46:51.939    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market
RI    0    13:46:51.944    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market
ON    0    13:46:51.969    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market placed for execution in 30 ms
HR    0    13:46:51.969    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market placed for execution in 24 ms


Теперь что касается уверенности в том, что речь идет об одном и том же ордере. Дело в том, что чуть выше приведенного выше кода, непосредственно перед отправкой ордера на сервер, советник выводит в свой журнал параметры структуры sTradeRequest с помощью функции PrintTradeRequest(sTradeRequest). Поэтому в журнал попали две строчки друг за другом.

RH    0    13:45:54.611    RECTANGLES (Si-6.16,D1)    TRADE_ACTION_DEAL magic=#680007104005201001, Si-6.16 volume=1.0 price=0.0 Тип ордера ORDER_TYPE_SELL
JP    0    13:45:54.611    RECTANGLES (Si-6.16,D1)    *** Структура торгового запроса не прошла базовую проверку, error=4756 Не удалось отправить торговый запрос

И еще, каждый ордер, отправляемый из эксперта,  получает уникальный идентификационный номер (magic), в данном случае magic=#680007104005201001.

По поводу протоколирования успешной отправки ордера. Поскольку советник торгует часто, то чтобы не забивать журнал малоинформативными сообщениями было решено выводить в журнал только сообщения о неудачной отправке ордера на биржу.

 

Представляется странным вот это место:

GM    0    13:45:54.521    Trades    '24430': deal #25905779 sell 1.00 Si-6.16 at 67159 done (based on order #36796287)
OS    0    13:45:54.611    Trades    '24430': exchange sell 1.00 Si-6.16 at market
LH    0    13:45:54.614    Trades    '24430': exchange sell 1.00 Si-6.16 at market
JQ    0    13:45:54.682    Trades    '24430': exchange sell 1.00 Si-6.16 at market placed for execution in 68 ms

имеет место двойная отправка ордера по рынку, с интервалом 3 миллисекунды. А вот откуда это взялось, нужно искать. Подождём понедельника, если не будет комментариев, тогда в сервисдеск за разъяснениями.

 
Karputov Vladimir: Представляется странным вот это место: имеет место двойная отправка ордера по рынку, с интервалом 3 миллисекунды. А вот откуда это взялось, нужно искать. Подождём понедельника, если не будет комментариев, тогда в сервисдеск за разъяснениями.

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

 
Eugene Myzrov:

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

В таком случае нужно более точное расследование:

  • журналы всех советников.
Иначе правды не найти, так как если это дубликаты советников, то и логика у них одинакова и может быть такая ситуация: OrderSend() для одного советника действительно вернула false и сделки не было, а в это время другая копия "продавила" и отослала ордер.
 
Karputov Vladimir: В таком случае нужно более точное расследование:

  • журналы всех советников.
Иначе правды не найти, так как если это дубликаты советников, то и логика у них одинакова и может быть такая ситуация: OrderSend() для одного советника действительно вернула false и сделки не было, а в это время другая копия "продавила" и отослала ордер.
Но у каждого советника свой маджик, и перед выводом сообщения об ошибке в журнале идет строка, уточняющая какой советник с каким маджиком делал запрос на отправку ордера.
 
 


JL    0    13:45:21.783    Trades    'XXXXX': exchange buy 2.00 Si-6.16 at market
GD    0    13:45:21.911    Trades    'XXXXX': exchange buy 2.00 Si-6.16 at market placed for execution in 128 ms
GQ    0    13:45:21.932    Trades    'XXXXX': cancel order #36795985 buy limit 1.00 Si-6.16 at 67101 (67101)
HM    0    13:45:21.959    Trades    'XXXXX': deal #25905759 buy 2.00 Si-6.16 at 67187 done (based on order #36796236)
JO    0    13:45:21.959    Trades    'XXXXX': cancel order #36795985 buy limit 1.00 Si-6.16 at 67101 (67101) placed for execution in 27 ms
HN    0    13:45:22.135    Trades    'XXXXX': sell limit 1.00 Si-6.16 at 67277 (67277)
KD    0    13:45:22.216    Trades    'XXXXX': sell limit 1.00 Si-6.16 at 67277 (67277) placed for execution in 80 ms
JM    0    13:45:54.519    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market placed for execution in 98 ms
GM    0    13:45:54.521    Trades    'XXXXX': deal #25905779 sell 1.00 Si-6.16 at 67159 done (based on order #36796287)

OS    0    13:45:54.611    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market
LH    0    13:45:54.614    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market
JQ    0    13:45:54.682    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market placed for execution in 68 ms
GQ    0    13:45:54.740    Trades    'XXXXX': deal #25905780 sell 1.00 Si-6.16 at 67160 done (based on order #36796288)

IG    0    13:45:55.026    Trades    'XXXXX': buy limit 1.00 Si-6.16 at 67148 (67148)
QN    0    13:45:55.104    Trades    'XXXXX': buy limit 1.00 Si-6.16 at 67148 (67148) placed for execution in 77 ms
JR    0    13:46:51.640    Trades    'XXXXX': deal #25905798 buy 1.00 Si-6.16 at 67148 done (based on order #36796289)
HP    0    13:46:51.939    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market
RI    0    13:46:51.944    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market
ON    0    13:46:51.969    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market placed for execution in 30 ms
HR    0    13:46:51.969    Trades    'XXXXX': exchange sell 1.00 Si-6.16 at market placed for execution in 24 ms


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

Дальше видно, что идут два рыночных ордера Sell. При этом только один был успешно размещён и выполнен. 

 
Eugene Myzrov:

Но речь сейчас не про контекст, а про то, почему функция OrderSend() вернула false, если ордер все таки попал на биржу и был исполнен. Получается, что сервер дезинформировал робота...

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