Stanislav Korotky: В контексте ситуации - несколько экземпляров советника, на каждом тике каждый из них пытается повторить отправить сделку в случае проблемы, а успешность сделки не регистрируется - у Вас нет оснований утверждать, что ошибка в терминале. Больше похоже на штатное исполнение кода, а ордер на бирже - совсем не тот, для которого вернулось false.
Большое кол-во работающих экземпляров советника, и как следствие большое кол-во ордеров и сделок, а также отсутствие положительных квитанций в журнале "Эксперты" серьезно затрудняют локализацию ошибок. Вынужден согласится с Вами, что вывод об ошибке в работе терминала был преждевременным, просто на тот момент не находилось другого объяснения такому странному поведению. В связи с этим в эксперт был добавлен дополнительный вывод в журнал положительных подтверждений и решено провести испытания только на одном экземпляре советника. По результатам отпишусь...
В ответ на отправку запроса на торговый сервер советник получил неизвестный код результата операции, retcode=10001, хотя ордер все равно был отправлен на биржу и исполнен в полном объема 2 лота. Действительно, в справочнике такого кода нет, все коды возврата торгового сервера начинаются с кода 10004.
Для подтверждения успешной передачи ордера на торговой сервер (биржу) советник ожидал получить один из двух кодов код возврата:
TRADE_RETCODE_PLACED = 10008 // Ордер размещен (возвращает биржевой рынок MOEX) TRADE_RETCODE_DONE = 10009 // Заявка выполнена (возвращает внебиржевой рынок FOREX и тестер стратегий!!!
Однако вместо этого советник получил неизвестный код возврата 10001 и посчитал, что ордер не был отправлен на биржу, и поэтому чуть позже повторил отправку ордера, который также был исполнен.
RF 018:29:18.250 RECTANGLES (Si-9.16,H4) [0034-0021 Si-9.16] *** На торговый сервер отправлен ордер ORDER_TYPE_BUY volume=2.0TRADE_ACTION_DEAL magic=#340021202002101007[B+0034-0021-202-002-101-007]
LR 018:29:18.250 RECTANGLES (Si-9.16,H4) [0034-0021 Si-9.16] *** Ошибка отправки запроса на торговый сервер: retcode=10001 Неизвестный код результата операции, ticket #37922221
EF 018:29:21.864 RECTANGLES (Si-9.16,H4) [0034-0021 Si-9.16] *** На торговый сервер отправлен ордер ORDER_TYPE_BUY volume=2.0TRADE_ACTION_DEAL magic=#340021202002101007[B+0034-0021-202-002-101-007]
MS 018:29:21.864 RECTANGLES (Si-9.16,H4) [0034-0021 Si-9.16] *** Успешно отправлен запрос на торговый сервер, код возврата #10008Ордер размещен, ticket #37922242
Вот кусок программы, которая отправляет и контролирует отправку ордера, выдает в журнал сообщения об успешном или не успешном выполнении.
//+--------------------------------------------------------------------------+//| Отправить торговый запрос на сервер (рыночный ордер)//| В случае успеха функция возвращает тикет ордера (или 0 в случае неудачи)//+--------------------------------------------------------------------------+ulong OrderSend2(const ENUM_OPER_CODE oper_code, constint order_volume, constulong magic)
{
// Подготовительные операции по заполнению структуры.... // Отправить запрос на торговый сервер и получить код результата операцииResetLastError(); // Сбросить значение предопределенной переменной _LastError в нольbool ok=OrderSend(sTradeRequest, sTradeResult); // две структуры: запроса и ответаuint retcode=sTradeResult.retcode; // код результата операции
Order.ticket=sTradeResult.order; // Тикет ордера, если он выставлен (возвращает сервер)Print(EXPERT_PREFIX, "На торговый сервер отправлен ордер ", EnumToString(sTradeRequest.type), // Тип ордера" volume=", sTradeRequest.volume, // Запрашиваемый объем сделки в лотах" ", EnumToString(sTradeRequest.action), // Тип выполняемого действия" magic=#", sTradeRequest.magic, // Штамп эксперта (идентификатор magic number)" [", sTradeRequest.comment, "]"); // Комментарий к ордеру// Анализируем код возврата торгового сервераif (Order.ticket>0 &&
(retcode==TRADE_RETCODE_PLACED || // Ордер размещен (10008) (возвращает биржевой рынок MOEX)
retcode==TRADE_RETCODE_DONE )) { // Заявка выполнена (10009) (возвращает внебирж. рынок FOREX и тестер стратегий!!!)Print(EXPERT_PREFIX, "Успешно отправлен запрос на торговый сервер, код возврата #", retcode, " ", retcode_descr(retcode), ", ticket #", Order.ticket);
}
else {
// err=GetLastError(); Print("*** Структура торгового запроса не прошла базовую проверку, err=", err, " ", ErrorToString(err));Print(EXPERT_PREFIX, "Ошибка отправки запроса на торговый сервер: retcode=", retcode, " ", retcode_descr(retcode), ", ticket #", Order.ticket);
Order.PrintToLog(); // Распечатать параметры структуры Order
Order.ticket=0;
}
return(Order.ticket);
}
Как видно из текста, советник совершенно не интересуется результатом работы функции OrderSend(), анализируется только код возврата торгового сервера, и на основе этого анализа принимаются решения. Это было сделано намерено, и похоже не зря. Скорее всего, функция OrderSend() также бы вернула значение FALSE, хотя ордер, повторюсь, был передан на биржу и исполнен в полном объеме.
В ответ на отправку запроса на торговый сервер советник получил неизвестный код результата операции, retcode=10001, хотя ордер все равно был отправлен на биржу и исполнен в полном объема 2 лота. Действительно, в справочнике такого кода нет, все коды возврата торгового сервера начинаются с кода 10004.
Для подтверждения успешной передачи ордера на торговой сервер (биржу) советник ожидал получить один из двух кодов код возврата:
TRADE_RETCODE_PLACED = 10008 // Ордер размещен (возвращает биржевой рынок MOEX) TRADE_RETCODE_DONE = 10009 // Заявка выполнена (возвращает внебиржевой рынок FOREX и тестер стратегий!!!
Однако вместо этого советник получил неизвестный код возврата 10001 и посчитал, что ордер не был отправлен на биржу, и поэтому чуть позже повторил отправку ордера, который также был исполнен.
Вот кусок программы, которая отправляет и контролирует отправку ордера, выдает в журнал сообщения об успешном или не успешном выполнении.
Как видно из текста, советник совершенно не интересуется результатом работы функции OrderSend(), анализируется только код возврата торгового сервера, и на основе этого анализа принимаются решения. Это было сделано намерено, и похоже не зря. Скорее всего, функция OrderSend() также бы вернула значение FALSE, хотя ордер, повторюсь, был передан на биржу и исполнен в полном объеме.
Без полного журнала терминала Ваше сообщение нельзя анализировать.
Karputov Vladimir: Также нет кода о заполнении структур и торгового запроса.
Хорошо, я все все пришлю на сервис-деск. Но, как Вы догадываетесь, советник отправил не одну сотню запросов, заполняя корректно структуры торгового запроса по одному и тому же алгоритму, прежде чем он вместо ожидаемого 10008 (TRADE_RETCODE_PLACED) получил неизвестный код возврата 10001. Что это за код, как его интерпретировать, и почему его нет в документации?
Хорошо, я все все пришлю на сервис-деск. Но, как Вы догадываетесь, советник отправил не одну сотню запросов, заполняя корректно структуры торгового запроса по одному и тому же алгоритму, прежде чем он получил неизвестный код возврата 10001. Что это за код, как его интерпретировать, и почему его нет в документации?
Я думаю могут быть два варианта:
код возврата 10001 - это зарезервированный код и в данном случае была какая-то непредвиденная ситуация
код возврата 10001, в данном конкретном случае, - просто "мусор", который был интерпретирован как 10001.
Eugene Myzrov: Отправил в сервис-деск полные журналы терминала и советника за 16.06.2016, а также код заполнения структуры торгового запроса.
Я не сервисдеск и хотел увидеть журналы и заполнение структур для общего развития, так сказать. Вдруг сообщество сможет найти спорный или сомнительный момент.
Karputov Vladimir: Я не сервисдеск и хотел увидеть журналы и заполнение структур для общего развития, так сказать. Вдруг сообщество сможет найти спорный или сомнительный момент.
Можно, вот кусок журнала за интересующее нас время 18:29:18.115 когда была исполнена сделка #26367967 на покупку объемом 2.00 Si-9.16 по цене 67368 согласно ордера #37922221, однако советник на отправку этого ордера вместо ожидаемого кода возврата 10008 получил код 10001. Полагаю, что в это время функция OrderSend() вернула значение FALSE, почему я и открыл эту тему на форуме. К сожалению, вывод в журнал этого значения я добавил позже, уже после того, как была обнаружена эта ошибка.
OO 017:02:22.603 Trades '00000': deal #26361397 sell 1.00 Si-9.16 at 67650 done (based on order #37911656)
GM 018:28:38.179 Trades '00000': buy limit 1.00 Si-9.16 at 67113 (67113)
JG 018:28:38.322 Trades '00000': buy limit 1.00 Si-9.16 at 67113 (67113) placed for execution in143 ms
KD 018:29:18.115 Trades '00000': exchange buy 2.00 Si-9.16 at market placed for execution in109 ms
DQ 018:29:18.115 Trades '00000': deal #26367967 buy 2.00 Si-9.16 at 67368 done (based on order #37922221)
LQ 018:29:18.250 Trades '00000': exchange buy 2.00 Si-9.16 at market
CH 018:29:21.745 Trades '00000': exchange buy 2.00 Si-9.16 at market
GP 018:29:21.860 Trades '00000': exchange buy 2.00 Si-9.16 at market placed for execution in115 ms
QM 018:29:21.860 Trades '00000': deal #26367973 buy 1.00 Si-9.16 at 67374 done (based on order #37922242)
CN 018:29:21.861 Trades '00000': deal #26367974 buy 1.00 Si-9.16 at 67374 done (based on order #37922242)
EI 018:29:21.891 Trades '00000': cancel order #37922088 buy limit 1.00 Si-9.16 at 67113 (67113)
DF 018:29:21.899 Trades '00000': cancel order #37922088 buy limit 1.00 Si-9.16 at 67113 (67113) placed for execution in8 ms
LD 018:32:48.871 Trades '00000': sell limit 1.00 Si-9.16 at 67629 (67629)
JR 018:32:48.965 Trades '00000': sell limit 1.00 Si-9.16 at 67629 (67629) placed for execution in94 ms
CS 018:59:04.461 Trades '00000': deal #26370151 sell 5.00 Si-9.16 at 67486 done (based on order #0)
KK 018:59:04.488 Trades '00000': deal #26370152 buy 5.00 Si-9.16 at 67486 done (based on order #0)
NF 019:07:04.932 Experts expert RECTANGLES (Si-9.16,H4) removed
А вот необходимые структуры и часть кода, который подготавливает и отправляет запрос на биржу
inputuint DEVIATION = 0; // Проскальзывание [п]//+-------------------------------------------+//| Структура для работа со свойствами ордера//+-------------------------------------------+struct SOrder
{
double volume ; // Объем ордера (вещественный!)double price ; // Цена ордера (открытия или закрытия)ulong ticket ; // Тикет ордераulong magic ; // Magic ордераdatetime time ; // Время формирования запросаENUM_ORDER_TYPE type ; // Тип ордера:// ORDER_TYPE_BUY - Рыночный ордер на покупку// ORDER_TYPE_SELL - Рыночный ордер на продажу// ORDER_TYPE_BUY_LIMIT - Отложенный ордер Buy Limit// ORDER_TYPE_SELL_LIMIT - Отложенный ордер Sell Limit// ORDER_TYPE_BUY_STOP - Отложенный ордер Buy Stop// ORDER_TYPE_SELL_STOP - Отложенный ордер Sell Stop// ORDER_TYPE_BUY_STOP_LIMIT - По достижении цены ордера выставляется отложенный ордер Buy Limit по цене StopLimit// ORDER_TYPE_SELL_STOP_LIMIT - По достижении цены ордера выставляется отложенный ордер Sell Limit по цене StopLimit
ENUM_OPER_CODE oper_code ; // код операции "open buy";"open sell";"close buy";"close sell";string oper_name ; // название операции "open buy";"open sell";"close buy";"close sell";string symbol ; // Имя символа, по которому подготовлен запросstring comment ; // Комментарий к ордеру// Вывести на печать параметры ордераvoid PrintToLog();
// Распечатать параметры структуры Ordervoid Print2();
};
//+--------------------------------------------------------------------------+//| Отправить торговый запрос на сервер (рыночный ордер)//| В случае успеха функция возвращает тикет ордера (или 0 в случае неудачи)//+--------------------------------------------------------------------------+ulong OrderSend2(const ENUM_OPER_CODE oper_code, constint order_volume, constulong magic)
{
// if (TRADE_MODE==TRADE_MODE_VIRTUAL) {VIRTUAL_TICKET+=1; return(VIRTUAL_TICKET);}// Преобразовать MAGIC в строку - комментарий к ордеруstring sMagic = MagicToString(magic);
// Для быстрого получения наиболее востребованной информации о текущих ценахSymbolInfoTick(_Symbol, sTick); // ссылка на структуру// Очистить 2 структурыZeroMemory(Order);
ZeroMemory(Deal );
Order.oper_code = oper_code; // код операции
Order.symbol = _Symbol; // Имя символа, по которому подготовлен запрос
Order.time = TimeCurrent(); // время формирования запроса
Order.magic = magic; // Magic ордера
Order.ticket = 0; // тикет ордера (возвращает сервер)
Order.volume = MathAbs(order_volume); // Объем ордераswitch (oper_code) {
case OPER_BUY_IN:
Order.type = ORDER_TYPE_BUY; // ордер на покупку
Order.oper_name = "buy/in"; // название операции
Order.comment = "B+"+sMagic; // Комментарий к ордеру
Order.price = NormalizeDouble(sTick.ask, _Digits); // Текущая цена Askbreak;
case OPER_BUY_OUT:
Order.type = ORDER_TYPE_SELL; // ордер на продажу
Order.oper_name = "buy/out"; // название операции
Order.comment = "B-"+sMagic; // Комментарий к ордеру
Order.price = NormalizeDouble(sTick.bid, _Digits); // Текущая цена Bidbreak;
case OPER_SELL_IN:
Order.type = ORDER_TYPE_SELL; // ордер на продажу
Order.oper_name = "sell/in"; // название операции
Order.comment = "S+"+sMagic; // Комментарий к ордеру
Order.price = NormalizeDouble(sTick.bid, _Digits); // Текущая цена Bidbreak;
case OPER_SELL_OUT:
Order.type = ORDER_TYPE_BUY; // ордер на покупку
Order.oper_name = "sell/out"; // название операции
Order.comment = "S-"+sMagic; // Комментарий к ордеру
Order.price = NormalizeDouble(sTick.ask, _Digits); // Текущая цена Askbreak;
}
// Очистить 3 структурыZeroMemory(sTradeRequest ); // запросZeroMemory(sTradeResult ); // результатZeroMemory(sTradeCheckResult); // структура ответа// Подготовить запрос
sTradeRequest.action = TRADE_ACTION_DEAL; // рыночный ордер - немедленное исполнение
sTradeRequest.type = Order.type; // Рыночный ордер на покупку/продажу
sTradeRequest.magic = Order.magic; // Штамп эксперта (идентификатор magic number)
sTradeRequest.symbol = Order.symbol; // Имя торгового инструмента (не требуется при закрытии позиций)
sTradeRequest.volume = Order.volume; // Запрашиваемый объем сделки в лотах
sTradeRequest.price = 0; // Order.price; // Текущая цена (для типа TRADE_ACTION_DEAL указание цены не требуется!)
sTradeRequest.comment = Order.comment; // Комментарий к ордеру
sTradeRequest.deviation = DEVIATION; // Максимально приемлемое отклонение от запрашиваемой цены
sTradeRequest.type_filling = ORDER_FILLING_FOK; // Тип ордера по исполнению - все или ничего
sTradeRequest.type_time = ORDER_TIME_GTC; // Ордер будет находится в очереди до тех пор, пока не будет снят// sTradeRequest.expiration = 0; // Срок истечения ордера (для ордеров типа ORDER_TIME_SPECIFIED)// sTradeRequest.order = 0; // Тикет ордера (только для модификации отложенных ордеров)// sTradeRequest.stoplimit = 0; // Уровень StopLimit ордера// sTradeRequest.sl = 0; // Уровень Stop Loss ордера// sTradeRequest.tp = 0; // Уровень Take Profit ордераint err;
ResetLastError(); // Сбросить значение предопределенной переменной _LastError в ноль// Проверить достаточность средств для совершения требуемой торговой операции. // Результаты проверки помещаются в поля структуры MqlTradeCheckResult.if (!OrderCheck(sTradeRequest, sTradeCheckResult)) {
err=GetLastError();
Print("*** Торговый запрос не прошел предварительную проверку перед отправкой, err=", err, " ", ErrorToString(err));
// Распечатать параметры структуры ответа MqlTradeCheckResult
PrintTradeCheckResult(sTradeCheckResult);
return(0);
}
// Отправить запрос на торговый сервер и получить код результата операцииResetLastError(); // Сбросить значение предопределенной переменной _LastError в нольbool ok=OrderSend(sTradeRequest, sTradeResult); // две структуры: запроса и ответаuint retcode=sTradeResult.retcode; // код результата операции
Order.ticket=sTradeResult.order; // Тикет ордера, если он выставлен (возвращает сервер)Print(EXPERT_PREFIX, "На торговый сервер отправлен ордер ", EnumToString(sTradeRequest.type), // Тип ордера" volume=", sTradeRequest.volume, // Запрашиваемый объем сделки в лотах" ", EnumToString(sTradeRequest.action), // Тип выполняемого действия" magic=#", sTradeRequest.magic, // Штамп эксперта (идентификатор magic number)" [", sTradeRequest.comment, "]"); // Комментарий к ордеру// Анализируем код возврата торгового сервераif (Order.ticket>0 &&
(retcode==TRADE_RETCODE_PLACED || // Ордер размещен (10008) (возвращает биржевой рынок MOEX)
retcode==TRADE_RETCODE_DONE )) { // Заявка выполнена (10009) (возвращает внебирж. рынок FOREX и тестер стратегий!!!)Print(EXPERT_PREFIX, "Успешно отправлен запрос на торговый сервер, код возврата #", retcode, " ", retcode_descr(retcode), ", ticket #", Order.ticket);
}
else {
// err=GetLastError(); Print("*** Структура торгового запроса не прошла базовую проверку, err=", err, " ", ErrorToString(err));Print(EXPERT_PREFIX, "Ошибка отправки запроса на торговый сервер: retcode=", retcode, " ", retcode_descr(retcode), ", ticket #", Order.ticket, " OrderSend()=", ok);
Order.PrintToLog(); // Распечатать параметры структуры Order
Order.ticket=0; // под вопросом, возможно придется удалить эту строчку!!!
}
return(Order.ticket);
}
Для авторизации и пользования сайтом MQL5.com необходимо разрешить использование файлов Сookie.
Пожалуйста, включите в вашем браузере данную настройку, иначе вы не сможете авторизоваться.
Вы вошли в аккаунт. Двухфакторная аутентификация отключена. Настройте её заново и отсканируйте новый QR-код или продолжите с отключённой двухфакторной аутентификацией.
Большое кол-во работающих экземпляров советника, и как следствие большое кол-во ордеров и сделок, а также отсутствие положительных квитанций в журнале "Эксперты" серьезно затрудняют локализацию ошибок. Вынужден согласится с Вами, что вывод об ошибке в работе терминала был преждевременным, просто на тот момент не находилось другого объяснения такому странному поведению. В связи с этим в эксперт был добавлен дополнительный вывод в журнал положительных подтверждений и решено провести испытания только на одном экземпляре советника. По результатам отпишусь...
Сегодня обнаружилась следующая ошибка.
В ответ на отправку запроса на торговый сервер советник получил неизвестный код результата операции, retcode=10001, хотя ордер все равно был отправлен на биржу и исполнен в полном объема 2 лота. Действительно, в справочнике такого кода нет, все коды возврата торгового сервера начинаются с кода 10004.
Для подтверждения успешной передачи ордера на торговой сервер (биржу) советник ожидал получить один из двух кодов код возврата:
TRADE_RETCODE_PLACED = 10008 // Ордер размещен (возвращает биржевой рынок MOEX)
TRADE_RETCODE_DONE = 10009 // Заявка выполнена (возвращает внебиржевой рынок FOREX и тестер стратегий!!!
Однако вместо этого советник получил неизвестный код возврата 10001 и посчитал, что ордер не был отправлен на биржу, и поэтому чуть позже повторил отправку ордера, который также был исполнен.
Вот кусок программы, которая отправляет и контролирует отправку ордера, выдает в журнал сообщения об успешном или не успешном выполнении.
Как видно из текста, советник совершенно не интересуется результатом работы функции OrderSend(), анализируется только код возврата торгового сервера, и на основе этого анализа принимаются решения. Это было сделано намерено, и похоже не зря. Скорее всего, функция OrderSend() также бы вернула значение FALSE, хотя ордер, повторюсь, был передан на биржу и исполнен в полном объеме.
Сегодня обнаружилась следующая ошибка.
В ответ на отправку запроса на торговый сервер советник получил неизвестный код результата операции, retcode=10001, хотя ордер все равно был отправлен на биржу и исполнен в полном объема 2 лота. Действительно, в справочнике такого кода нет, все коды возврата торгового сервера начинаются с кода 10004.
Для подтверждения успешной передачи ордера на торговой сервер (биржу) советник ожидал получить один из двух кодов код возврата:
TRADE_RETCODE_PLACED = 10008 // Ордер размещен (возвращает биржевой рынок MOEX)
TRADE_RETCODE_DONE = 10009 // Заявка выполнена (возвращает внебиржевой рынок FOREX и тестер стратегий!!!
Однако вместо этого советник получил неизвестный код возврата 10001 и посчитал, что ордер не был отправлен на биржу, и поэтому чуть позже повторил отправку ордера, который также был исполнен.
Вот кусок программы, которая отправляет и контролирует отправку ордера, выдает в журнал сообщения об успешном или не успешном выполнении.
Как видно из текста, советник совершенно не интересуется результатом работы функции OrderSend(), анализируется только код возврата торгового сервера, и на основе этого анализа принимаются решения. Это было сделано намерено, и похоже не зря. Скорее всего, функция OrderSend() также бы вернула значение FALSE, хотя ордер, повторюсь, был передан на биржу и исполнен в полном объеме.
Хорошо, я все все пришлю на сервис-деск. Но, как Вы догадываетесь, советник отправил не одну сотню запросов, заполняя корректно структуры торгового запроса по одному и тому же алгоритму, прежде чем он вместо ожидаемого 10008 (TRADE_RETCODE_PLACED) получил неизвестный код возврата 10001. Что это за код, как его интерпретировать, и почему его нет в документации?
Хорошо, я все все пришлю на сервис-деск. Но, как Вы догадываетесь, советник отправил не одну сотню запросов, заполняя корректно структуры торгового запроса по одному и тому же алгоритму, прежде чем он получил неизвестный код возврата 10001. Что это за код, как его интерпретировать, и почему его нет в документации?
Я думаю могут быть два варианта:
Отправил в сервис-деск полные журналы терминала и советника за 16.06.2016, а также код заполнения структуры торгового запроса.