Полное решение Off quotes / Requote (MT5/MQL5) — 10021
Содержание
- В чём разница между этими двумя ошибками (и 136/138 из MT4)
- ① TRADE_RETCODE_PRICE_OFF = 10021 (нет котировок для обработки запроса)
- ② TRADE_RETCODE_REQUOTE = 10004 (requote — повторное предложение новой цены)
- ③ Ошибки 136 / 138 из эпохи MT4
- Быстрая диагностика за 30 секунд
- Причины и решения (5 сценариев)
- ① Резкое движение рынка, всплеск на новостях (отправленная цена устарела до того, как дошла до сервера)
- ② Слишком узкий deviation (допустимое проскальзывание)
- ③ Разница в типе исполнения (requote — явление, характерное для instant-исполнения)
- ④ Периоды или инструменты с разреженными или остановленными котировками
- ⑤ Задержка соединения (VPS расположен далеко от сервера брокера)
- Код на MQL5 для снижения частоты ошибки (для разработчиков EA)
- Правильная настройка deviation в пунктах
- Повтор запроса только для retcode, связанных с ценой (с обновлением по последнему тику)
- Использование цены, повторно предложенной в ответе на requote (10004)
- Создание временных промежутков, когда ордер вообще не отправляется
- Чек-лист приоритетов
- Итоги
- Часто задаваемые вопросы
- В: Что серьёзнее — 10004 или 10021?
- В: Значит ли отсутствие requote у брокера, что он хороший?
- В: На советнике для MT4 появляются ошибки 136 / 138. Подходят ли те же решения?
- В: В бэктесте ошибка не появляется, а в реальной торговле — да.
Полное решение Off quotes / Requote (MT5/MQL5)
Когда во время работы советника в журнале или на вкладке Expert появляется off quotes (10021) или requote (10004), это выглядит так, будто брокер отказал в исполнении сделки, и вызывает беспокойство. Но обе эти ошибки связаны не с деньгами или лотом, а с ценой. Цена, которую отправили вы, и цена, которая в этот момент есть на сервере, не совпали — вот и всё. Практически все причины сводятся к одному из четырёх факторов: резкое движение рынка, допустимое проскальзывание, тип исполнения ордера или задержка соединения.
Эта статья адресована как трейдерам, использующим советники в MT5, так и разработчикам, пишущим EA на MQL5. Здесь собрано всё в одном месте: суть, причины, быстрые решения и постоянные меры на уровне кода для 10021 (TRADE_RETCODE_PRICE_OFF), 10004 (TRADE_RETCODE_REQUOTE), а также ошибок 136/138 из эпохи MT4. Полный список кодов ошибок смотрите в сводном руководстве по обработке ошибок MQL5 / MT5.
Статья написана по состоянию на июль 2026 года для MT5 (сборки серии 4xxx). Детали поведения (возвращает ли сервер requote или исполняет ордер как есть) зависят от типа исполнения, применяемого конкретным брокером.
В чём разница между этими двумя ошибками (и 136/138 из MT4)
Отказы из-за «несовпадения цены» бывают двух видов — в зависимости от того, как отвечает сервер.
① TRADE_RETCODE_PRICE_OFF = 10021 (нет котировок для обработки запроса)
Это значение попадает в MqlTradeResult.retcode как результат OrderSend() и означает отказ «нет котировок для обработки запроса» (There are no quotes to process the request). Это указывает на то, что на сервере нет действующей цены, либо отправленная цена слишком далеко ушла от текущей котировки, чтобы её можно было обработать.
Значение: нет котировок для обработки запроса
Константа: TRADE_RETCODE_PRICE_OFF
Код : 10021
② TRADE_RETCODE_REQUOTE = 10004 (requote — повторное предложение новой цены)
Тоже retcode из OrderSend(), но в этом случае сервер не просто отклоняет запрос, а предлагает новую цену вместо отправленной («по этой цене нельзя, но вот эта подойдёт?») — это и называется requote. В полях bid / ask структуры MqlTradeResult возвращается та самая новая цена, предложенная сервером.
Значение: Requote — повторное предложение новой цены
Константа: TRADE_RETCODE_REQUOTE
Код : 10004
// Типичный пример вывода, который можно увидеть в логе
2026.07.07 21:30:02.118 EA_NAME EURUSD,M5: OrderSend error 10004 (requote)
2026.07.07 21:30:02.310 EA_NAME EURUSD,M5: OrderSend error 10021
③ Ошибки 136 / 138 из эпохи MT4
В MQL4 (MT4) то же самое явление возвращалось как код ошибки функции GetLastError().
| Константа MT4 | Код | Соответствующий retcode MT5 |
|---|---|---|
ERR_OFF_QUOTES | 136 | 10021 (TRADE_RETCODE_PRICE_OFF) |
ERR_REQUOTE | 138 | 10004 (TRADE_RETCODE_REQUOTE) |
Если вы встречаете «error 136» или «error 138» в старых статьях о советниках или в логах EA для MT4, содержание этой статьи применимо к ним напрямую (в MT4 стандартной практикой было заново запрашивать цену через RefreshRates() перед повторной отправкой ордера; о том, как это делается в MT5, — ниже).
Практическое разграничение:
| retcode | Что говорит сервер | Что должен сделать советник |
|---|---|---|
| 10004 (requote) | «Цена изменилась. Предлагаю новую цену» | Отправить запрос заново по актуальной цене (или отказаться от сделки) |
| 10021 (price off) | «Нет котировок для обработки запроса» | Немного подождать и отправить заново по последнему тику |
Обе ошибки являются временными (их можно устранить повтором запроса), и полностью избавиться от них правкой кода или настроек невозможно, но их частоту можно значительно снизить.
Быстрая диагностика за 30 секунд
- Проверьте время появления ошибки по временной метке в журнале
- Момент выхода важных новостей (нонфармы, заседание ФРС и т.п.) → нормальная реакция на резкое движение рынка. Если у советника есть фильтр новостей — включите его
- Около полуночи по времени сервера (роловер) или гэп в начале недели → период разреженных котировок. Это в пределах нормы
- Возникает случайно, вне зависимости от времени суток → стоит проверить соединение, VPS и настройку deviation
- Проверьте, на каком инструменте возникает ошибка
- Если ошибка концентрируется на низколиквидных инструментах — второстепенных валютных парах, экзотике, CFD — причина в разреженности котировок именно по этому инструменту
- Проверьте, возникает ли ошибка при ручном выставлении ордера
- Если ручной ордер (Quick Trade) проходит нормально, а советнику отказывают — велика вероятность, что у EA слишком узко задан
deviation(допустимое проскальзывание)
- Если ручной ордер (Quick Trade) проходит нормально, а советнику отказывают — велика вероятность, что у EA слишком узко задан
Эти три шага помогут понять, где искать причину — в самом рынке, в конкретном инструменте или в настройках/окружении, — и перейти к разбору по конкретным причинам ниже.
Причины и решения (5 сценариев)
① Резкое движение рынка, всплеск на новостях (отправленная цена устарела до того, как дошла до сервера)
Симптом: 10004/10021 концентрируются во время выхода экономических новостей, заявлений официальных лиц, ранним утром в понедельник.
Причина: советник получает тик, рассчитывает цену, и за десятки-сотни миллисекунд, пока ордер идёт до сервера, цена успевает сдвинуться на несколько пунктов. Отправленной цены уже не существует, поэтому сервер возвращает либо requote (10004), либо «нет котировок» (10021). Это не столько ошибка, сколько естественное явление на быстром рынке.
Решение:
- Остановить открытие новых сделок вокруг времени выхода новостей (фильтр новостей). Советники, распространяемые на этом сайте, по умолчанию оснащены модулем
EconomicFilter - Расширить
deviation(допустимое проскальзывание) до реалистичного значения (см. пункт ②) - Добавить логику повторной отправки запроса (код ниже)
② Слишком узкий deviation (допустимое проскальзывание)
Симптом: ошибка периодически появляется даже на спокойном рынке. Ручные ордера проходят, а советнику отказывают.
Причина: MqlTradeRequest.deviation — это заявленное значение того, на сколько пунктов отправленная цена может отличаться от текущей, чтобы запрос всё ещё был принят. Если задать здесь значение от 0 до нескольких пунктов, отказ будет происходить даже при обычном обновлении тика. Классическая ошибка — путаница между points и pips (для 5-значных брокеров 1 pip = 10 points).
Решение:
- Начать с
deviationв диапазоне 10–30 points (= 1–3 pips) и понаблюдать за результатом. Если стратегия не скальперская, 20 points — разумная отправная точка - Проверить, нет ли путаницы единиц измерения — например, задумывалось deviation=5, а по факту получилось 0.5 pips
- Если проскальзывание недопустимо в принципе по логике стратегии, стоит воспринимать отказ как норму и контролировать только число повторных попыток
③ Разница в типе исполнения (requote — явление, характерное для instant-исполнения)
Симптом: у брокера А ошибка встречается часто, а у брокера Б её вообще нет.
Причина: requote (10004) — явление, характерное именно для instant execution (мгновенного исполнения). При instant-исполнении ордер требует «исполнить именно по этой цене», поэтому при изменении цены сервер предлагает новую (requote). В то же время при market execution (рыночном исполнении) ордер требует «исполнить по текущей рыночной цене», поэтому requote в принципе невозможен — вместо этого сделка исполняется по изменившейся цене (то есть с проскальзыванием).
Иными словами, «нет requote» не означает «брокер лучше» — это компромисс между отказом в исполнении и исполнением со скольжением. Тип исполнения по инструменту можно посмотреть в спецификации символа (Specification) в MT5, в поле Execution, либо в коде — через SYMBOL_TRADE_EXEMODE.
Решение:
- Проверить тип исполнения на своём счёте (у многих зарубежных брокеров на стандартных счетах используется market-исполнение, и requote там в принципе не возникает)
- Если частые requote мешают работе стратегии, рассмотреть тип счёта или брокера с market-исполнением
- Даже при market-исполнении разные брокеры по-разному учитывают
deviation, поэтому если недопустимо сильное скольжение — стоит проверить фактическое проскальзывание по истории сделок
④ Периоды или инструменты с разреженными или остановленными котировками
Симптом: ошибка 10021 возникает около полуночи по времени сервера (роловер), сразу после открытия рынка в начале недели, в период затишья на Рождество и т.п., а также на второстепенных инструментах.
Причина: во время роловера подача котировок может временно приостанавливаться или спред резко расширяться из-за начисления свопа. Сразу после открытия рынка в начале недели или на низколиквидных инструментах котировок для обработки запроса попросту недостаточно. Отправка ордера в такой момент приводит к 10021 («нет котировок»).
Решение:
- Избегать открытия новых сделок примерно с 23:55 до 00:05 по времени сервера (временной фильтр)
- Избегать первых нескольких минут после открытия рынка в начале недели (настройки вроде
AvoidMondayOpen) - Добавить фильтр по спреду (
MaxSpread). В периоды разреженных котировок спред расширяется, поэтому такой фильтр фактически автоматически исключает эти отрезки времени
⑤ Задержка соединения (VPS расположен далеко от сервера брокера)
Симптом: частота ошибок заметно выше, чем в других окружениях, независимо от времени суток и инструмента. Высокий пинг.
Причина: чем дольше время прохождения сигнала до сервера и обратно (задержка), тем выше вероятность, что цена успеет измениться за это время. Если советник работает на домашнем ПК или на VPS в регионе, удалённом от местонахождения сервера брокера (часто это Лондон, Нью-Йорк и т.п.), частота 10004/10021 структурно возрастает. Ориентиром может служить значение пинга, отображаемое в правом нижнем углу MT5 (несколько сотен миллисекунд — явно невыгодно, желательно держаться в пределах нескольких десятков миллисекунд).
Решение:
- Проверить значение пинга в правом нижнем углу MT5; если оно стабильно высокое — пересмотреть окружение, в котором работает советник
- Перенести VPS в регион ближе к серверу брокера. По-честному, частоту 10004/10021, вызванную задержкой, кодом не уменьшить — единственное решение — физически приблизиться к серверу. О том, как выбрать VPS, подробно рассказано в руководстве по выбору VPS для советников
- Чем более скальперская стратегия, тем сильнее влияние задержки. Для советников на дневном или H4 таймфрейме эта причина менее приоритетна
Код на MQL5 для снижения частоты ошибки (для разработчиков EA)
Стратегия состоит из трёх пунктов: (1) задать реалистичное значение deviation, (2) при отказе заново запросить последний тик и повторить отправку, (3) повторять запрос только для retcode, связанных с ценой.
Правильная настройка deviation в пунктах
MqlTradeRequest req; MqlTradeResult res;
ZeroMemory(req); ZeroMemory(res);
req.action = TRADE_ACTION_DEAL;
req.symbol = _Symbol;
req.type = ORDER_TYPE_BUY;
req.volume = lots;
req.deviation = 20; // допустимое проскальзывание 20 points (для 5-значных котировок это 2.0 pips)
// также нужно задать req.price / req.sl / req.tp / req.magic и т.д.
Единица измерения deviation — points. У брокеров с 5-значным (3-значным) отображением котировок 10 points = 1 pip. Нулевое или чрезмерно маленькое значение неоправданно повышает вероятность отказа.
Повтор запроса только для retcode, связанных с ценой (с обновлением по последнему тику)
Ключевые моменты: при каждой повторной попытке заново получать цену через SymbolInfoTick() (повторная отправка со старой ценой приведёт к тому же отказу), а также ограничивать повтор только кодами 10004/10021. Механически повторять запрос при нехватке средств (10019) или некорректном запросе (10013) бессмысленно — это лишь засоряет лог.
bool IsRetryableRetcode(uint rc)
{
return (rc == TRADE_RETCODE_REQUOTE // 10004
|| rc == TRADE_RETCODE_PRICE_OFF); // 10021
}
// Повторяем отправку до 3 раз, каждый раз обновляя цену по последнему тику
bool SendWithRetry(MqlTradeRequest &req, MqlTradeResult &res, int maxTries = 3)
{
for(int attempt = 0; attempt < maxTries; attempt++)
{
MqlTick tick;
if(!SymbolInfoTick(req.symbol, tick))
{
Print("SymbolInfoTick failed: ", GetLastError());
return false;
}
req.price = (req.type == ORDER_TYPE_BUY) ? tick.ask : tick.bid;
if(OrderSend(req, res) && res.retcode == TRADE_RETCODE_DONE)
return true; // сделка исполнена успешно
if(!IsRetryableRetcode(res.retcode))
{
PrintFormat("OrderSend failed (no retry): retcode=%d", res.retcode);
return false; // не связанные с ценой ошибки не повторяем
}
PrintFormat("Retry %d/%d after retcode=%d", attempt + 1, maxTries, res.retcode);
Sleep(200 + 150 * attempt); // небольшая пауза: 200мс → 350мс → 500мс
}
Print("Order abandoned after retries (price kept moving).");
return false;
}
Постепенное увеличение времени ожидания в Sleep() нужно потому, что при мгновенных повторных попытках без паузы в момент резкого движения рынка будет раз за разом приходить тот же отказ. С другой стороны, если ждать слишком долго, цена входа всё сильнее отклоняется от изначального замысла стратегии, поэтому разумно отказаться от попыток после 2–3 повторов. Также учтите: при отложенном ордере (TRADE_ACTION_PENDING) успешный retcode будет другим — TRADE_RETCODE_PLACED (10008).
Использование цены, повторно предложенной в ответе на requote (10004)
При коде 10004 в полях bid / ask структуры MqlTradeResult содержится цена, повторно предложенная сервером. Повторной отправки с актуальным тиком, как показано выше, обычно достаточно на практике, но если для instant-исполнения требуется логика вида «принимать повторно предложенную цену, если она в допустимых пределах», нужно сравнить res.ask / res.bid с изначально предполагаемой ценой в пунктах и уже потом решать, отправлять ли запрос заново.
Создание временных промежутков, когда ордер вообще не отправляется
Повторная отправка в коде — это симптоматическое решение. Гораздо эффективнее в корне устранить проблему с помощью фильтра, который останавливает открытие новых сделок вокруг роловера, вокруг выхода новостей и при расширении спреда.
// Пример фильтра по спреду: пропускаем открытие новой сделки, если спред расширен
long spreadPts = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
if(spreadPts > MaxSpreadPoints)
{
// пропускаем открытие новой сделки (это автоматически исключает периоды разреженных котировок, где часто возникает 10021)
return;
}
Советники, распространяемые FXEA365, по умолчанию включают фильтр по спреду, фильтр новостей и автоматический повтор запроса для retcode, связанных с ценой.
Чек-лист приоритетов
| Приоритет | Проверка | Решение |
|---|---|---|
| 🚨 Сначала | Концентрируется ли ошибка вокруг выхода новостей или резкого движения рынка | Включить фильтр новостей, воспринимать этот период как норму |
| 🚨 Сначала | Не слишком ли мал deviation (единица измерения — points) | Задать 10–30 points, проверить путаницу pips/points |
| ⚠️ Далее | Концентрируется ли ошибка вокруг роловера, начала недели, низколиквидных инструментов | Временной фильтр + фильтр по спреду |
| ⚠️ Далее | Используется ли instant-исполнение | Рассмотреть счёт с market-исполнением (это компромисс со скольжением) |
| ⚠️ Далее | Высокий ли пинг (несколько сотен мс) | Перенести на VPS ближе к серверу |
| 🛠 Разработка | Ограничен ли повтор запроса только retcode, связанными с ценой | Обновлять цену через SymbolInfoTick и прекращать попытки после 2–3 раз |
Итоги
- 10021 (TRADE_RETCODE_PRICE_OFF) означает «нет котировок для обработки запроса», а 10004 (TRADE_RETCODE_REQUOTE) — «повторное предложение новой цены». Это то же семейство ошибок отклонения цены, что и 136/138 из эпохи MT4, и оно не связано с проблемами денег или лота.
- Причины сводятся к пяти факторам: резкое движение рынка, слишком узкий deviation, instant-исполнение, периоды/инструменты с разреженными котировками и задержка соединения.
- Requote — явление, характерное именно для instant-исполнения; при market-исполнении вместо него возникает проскальзывание. «Отсутствие ошибки» не значит «хорошо» — это компромисс.
- Разработчикам советников стоит принять постоянные меры: 2–3 повторные попытки с обновлением по последнему тику (только для 10004/10021), правильная настройка deviation и фильтры по времени/спреду. Единственное, что снижает частоту ошибок, вызванных задержкой соединения, — физическое решение (VPS ближе к серверу брокера).
Полный список кодов ошибок смотрите в сводном руководстве по обработке ошибок MQL5 / MT5, а бесплатных советников с этими мерами по умолчанию — в списке EA.
Часто задаваемые вопросы
В: Что серьёзнее — 10004 или 10021?
Обе ошибки являются временными и связаны с ценой, серьёзной разницы между ними нет. 10004 означает «была предложена новая цена», 10021 — «не нашлось котировок для обработки запроса». Единичные случаи можно спокойно игнорировать, а вот если ошибка часто повторяется в определённое время или на определённом инструменте, стоит устранить причину (новости, роловер, deviation, соединение).
В: Значит ли отсутствие requote у брокера, что он хороший?
Скорее всего, дело в разнице типов исполнения. На счетах с market-исполнением requote в принципе невозможен, и при изменении цены сделка исполняется по изменившейся цене как есть (то есть с проскальзыванием). Это компромисс между отказом и скольжением, поэтому выводы стоит делать на основе фактического проскальзывания по истории сделок.
В: На советнике для MT4 появляются ошибки 136 / 138. Подходят ли те же решения?
Да. 136 (ERR_OFF_QUOTES) соответствует 10021, а 138 (ERR_REQUOTE) — 10004, причины и меры для них общие. В MQL4 стандартной практикой было вызывать RefreshRates() перед повторной отправкой, чтобы обновить Bid / Ask — это тот же подход, что и повторное получение цены через SymbolInfoTick() в MQL5.
В: В бэктесте ошибка не появляется, а в реальной торговле — да.
Это нормально. В Strategy Tester отсутствует (или сильно упрощена) «задержка до момента, пока ордер дойдёт до сервера» и «изменение цены за это время», поэтому 10004/10021 проявляются только на форвард-тестах и в реальной торговле. Даже если бэктест показывает хорошие результаты, для реальной торговли отдельно требуется настройка deviation, логика повторных попыток и подготовка окружения исполнения (VPS).
По теме
📧 Оповещения до повышения цен + бесплатный 5-дневный email-курс
Все советники продаются по стартовой цене, которая растёт ступенями по мере продаж. Получайте уведомление перед каждым повышением, плюс ежедневное письмо об алготрейдинге, чтении бэктестов и выборе брокера.
* Конфиденциальность строго защищена. Отписаться можно в любое время.