Inicio > Blog > Off quotes / Requote en MT5 — error 10021

MT5MQL5ErroresResolución de problemasEA

Off quotes / Requote en MT5 — error 10021

Publicado: 2026-07-07Lectura: aprox. 8 min
This article reflects information as of its publish date. EA performance figures (PF, DD, annual return) change with live trading and re-validation — check the latest on the EA pages. See the latest EA results

Off quotes / Requote (MT5/MQL5) resuelto por completo

Cuando tienes un EA en funcionamiento y aparece off quotes (10021) o requote (10004) en el Journal o en la pestaña Expert, da la impresión de que el bróker ha rechazado la ejecución, lo cual genera inquietud. Pero estos dos casos no son un problema de fondos ni de lotaje, sino de precio. Simplemente el precio que enviaste y el que el servidor tiene en ese momento no coinciden, y la mayoría de las causas se reducen a un movimiento brusco del mercado, un deslizamiento (slippage) permitido insuficiente, el modo de ejecución o la latencia de la conexión.

Este artículo está dirigido tanto a quienes usan EAs en MT5 como a quienes programan EAs en MQL5, y reúne en un solo lugar la naturaleza, las causas, las soluciones inmediatas y las medidas permanentes en el código para 10021 (TRADE_RETCODE_PRICE_OFF), 10004 (TRADE_RETCODE_REQUOTE) y los errores 136/138 de la era MT4. Para un listado general de códigos de error, consulta la guía completa de códigos de error de MQL5/MT5.

Este artículo asume MT5 (serie build 4xxx) a fecha de julio de 2026. Los detalles del comportamiento (si se devuelve un requote o se ejecuta directamente, etc.) varían según el modo de ejecución del bróker.


En qué se diferencian estos dos casos (+ los errores 136/138 de MT4)

Los rechazos del tipo "el precio no coincide" tienen dos formas de respuesta por parte del servidor.

① TRADE_RETCODE_PRICE_OFF = 10021 (no hay cotización disponible para procesar)

Es el valor que se recibe en MqlTradeResult.retcode como resultado de OrderSend(), y representa el rechazo de "no hay cotizaciones para procesar la solicitud" (There are no quotes to process the request). Indica que el servidor no dispone de un precio válido, o que el precio enviado está demasiado alejado de la cotización actual como para poder procesarse.

Significado: no hay cotización disponible para procesar la solicitud
Constante: TRADE_RETCODE_PRICE_OFF
Valor    : 10021

② TRADE_RETCODE_REQUOTE = 10004 (requote = nueva propuesta de precio)

También es un retcode de OrderSend(), pero en este caso no se trata de un simple rechazo, sino de una nueva propuesta de precio (requote): "ese precio ya no es válido, pero ¿aceptas este nuevo?". El precio que el servidor vuelve a proponer se devuelve en los campos bid / ask de MqlTradeResult.

Significado: Requote — nueva propuesta de precio
Constante: TRADE_RETCODE_REQUOTE
Valor    : 10004
// Ejemplo típico de salida que se puede ver en el log
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

③ Los errores 136 / 138 de la era MT4

En MQL4 (MT4), el mismo fenómeno se devolvía como código de error a través de GetLastError().

Constante MT4Valorretcode equivalente en MT5
ERR_OFF_QUOTES13610021 (TRADE_RETCODE_PRICE_OFF)
ERR_REQUOTE13810004 (TRADE_RETCODE_REQUOTE)

Si encuentras "error 136" o "error 138" en artículos antiguos sobre EAs o en logs de EAs para MT4, el contenido de este artículo se aplica directamente (en MT4 la práctica habitual era volver a leer el precio con RefreshRates() antes de reenviar la orden; más adelante se explica cómo hacerlo en MT5).

Distinción práctica:

retcodeLo que dice el servidorAcción que debe tomar el EA
10004 (requote)"El precio se movió. Te propongo un nuevo precio"Reenviar con el precio más reciente (o cancelar)
10021 (price off)"No hay cotización disponible para procesar"Esperar un poco y reenviar con el último tick

Ambos son errores temporales (susceptibles de reintento). No es posible "eliminarlos por completo" mediante cambios de código o de configuración, pero sí se puede reducir su frecuencia de forma considerable.


Diagnóstico rápido en 30 segundos

  1. Verifica cuándo ocurrió usando la hora del Journal
    • En el momento exacto de una publicación de indicadores (Nóminas no agrícolas, FOMC, etc.) → movimiento brusco normal del mercado. Si tu EA tiene un filtro de noticias, actívalo
    • Alrededor de la medianoche del servidor (rollover) o en la apertura del lunes → franja horaria con poca liquidez de cotización. Está dentro de lo esperado
    • Ocurre de forma aleatoria y frecuente sin relación con la hora → sospecha de la conexión, el VPS o la configuración de deviation
  2. Verifica en qué símbolo ocurrió
    • Si se concentra en pares menores, exóticos o CFDs con baja liquidez, la causa es la escasa profundidad de cotización de ese instrumento
  3. Comprueba si también ocurre con una orden manual
    • Si la orden rápida manual se ejecuta con normalidad pero solo el EA es rechazado → es muy probable que el deviation (deslizamiento permitido) del EA esté demasiado restringido

Con estos tres puntos podrás orientar la causa hacia "el mercado", "el símbolo" o "la configuración/entorno", antes de pasar a las soluciones específicas por causa.


Causas y soluciones (5 patrones)

① Movimiento brusco del mercado / pico en la publicación de un indicador (el precio enviado queda obsoleto antes de llegar)

Síntoma: los códigos 10004/10021 se concentran en el momento de publicación de indicadores económicos, declaraciones de figuras clave, o la madrugada del lunes.

Causa: el EA recibe un tick, calcula el precio, y en las decenas o cientos de milisegundos que tarda la orden en llegar al servidor, el precio se mueve varios pips. El precio enviado ya no existe, así que el servidor devuelve un requote (10004) o "sin cotización" (10021). Más que un error, es un fenómeno normal en un mercado que se mueve rápido.

Solución:

  1. Detén las nuevas entradas antes y después de las publicaciones de indicadores (filtro de noticias). Los EAs distribuidos en este sitio incluyen de forma estándar EconomicFilter
  2. Amplía el deviation (deslizamiento permitido) a un valor realista (ver punto ②)
  3. Implementa lógica de reintento (ver código más abajo)

② El deviation (deslizamiento permitido) está demasiado restringido

Síntoma: aparece de forma esporádica incluso en un mercado tranquilo. Las órdenes manuales se ejecutan, pero el EA es rechazado.

Causa: MqlTradeRequest.deviation declara "hasta cuántos points de diferencia respecto al precio enviado se aceptan". Si se restringe a 0 o a unos pocos points, incluso una diferencia normal por actualización de tick puede quedar sujeta a rechazo. Un error habitual es confundir las unidades: son points, no pips (en un bróker de 5 dígitos, 1 pip = 10 points).

Solución:

  1. Comienza probando con un deviation de 10 a 30 points (= 1 a 3 pips). Si no se trata de scalping, 20 points es un punto de partida razonable
  2. Verifica que no haya una confusión de unidades, como pensar que "deviation=5" equivale a 0.5 pips
  3. Si tu estrategia no admite ningún deslizamiento, acepta el rechazo como parte del diseño y limita solo el número de reintentos

③ Diferencia en el modo de ejecución (el requote es propio de la ejecución instant)

Síntoma: ocurre con frecuencia en el bróker A, pero nunca en el bróker B.

Causa: el requote (10004) es un fenómeno específico de la ejecución instant (instant execution). En este modo, la orden dice "ejecútame a este precio", así que si el precio se mueve, el servidor vuelve a proponer un nuevo precio (requote). En cambio, la ejecución market (market execution) significa "ejecútame al precio de mercado actual", por lo que el requote no puede producirse en principio; en su lugar, la orden se ejecuta directamente al precio desviado (deslizamiento/slippage).

Es decir, "que no aparezca el requote" no significa "que sea mejor": es un compromiso entre ser rechazado o ejecutarse con deslizamiento. El modo de ejecución de un símbolo se puede verificar en el campo Execution de las "Especificaciones del símbolo" en MT5, o en código mediante SYMBOL_TRADE_EXEMODE.

Solución:

  1. Verifica el modo de ejecución de tu cuenta (muchas cuentas estándar de brókers internacionales usan ejecución market, donde el requote como tal no aparece)
  2. Si los requotes frecuentes entorpecen tu estrategia, considera un tipo de cuenta o bróker con ejecución market
  3. Como algunos brókers respetan el deviation incluso en ejecución market y otros no, si no puedes tolerar deslizamientos extremos, verifica el deslizamiento real en el historial de operaciones ejecutadas

④ Franjas horarias o símbolos con cotización escasa o detenida

Síntoma: el código 10021 aparece alrededor de la medianoche del servidor (rollover), justo tras la apertura del lunes, en periodos de baja actividad como Navidad, o en símbolos menores.

Causa: durante el rollover, la distribución de cotizaciones puede detenerse temporalmente o el spread puede ampliarse de forma extrema debido al procesamiento de swaps. Justo tras la apertura del lunes o en símbolos de baja liquidez, la cotización disponible para procesar es, de por sí, escasa. Enviar una orden en ese estado produce el código 10021 (sin cotización).

Solución:

  1. Evita nuevas entradas entre las 23:55 y las 0:05 de la hora del servidor (filtro horario)
  2. Evita los primeros minutos tras la apertura del lunes (configuraciones del tipo AvoidMondayOpen)
  3. Incorpora un filtro de spread (MaxSpread). Como el spread se amplía cuando la cotización es escasa, esto permite evitar automáticamente esas franjas horarias

⑤ Latencia de conexión (el VPS está lejos del servidor del bróker)

Síntoma: la frecuencia es claramente mayor que en otros entornos, sin relación con la hora o el símbolo. El valor de ping es alto.

Causa: cuanto mayor sea el tiempo de ida y vuelta (latencia) que tarda la orden en llegar al servidor, mayor es la probabilidad de que el precio se mueva en ese intervalo. Si operas desde un PC doméstico o desde un VPS en una región alejada de la ubicación del servidor del bróker (con frecuencia Londres o Nueva York), la frecuencia de 10004/10021 aumenta de forma estructural. El ping que se muestra en la esquina inferior derecha de MT5 es una referencia útil (varios cientos de ms es claramente desfavorable; lo ideal es estar por debajo de unas decenas de ms).

Solución:

  1. Verifica el valor de ping en la esquina inferior derecha de MT5, y si es constantemente alto, revisa el entorno de ejecución del EA
  2. Migra a un VPS en una región cercana al servidor del bróker. La realidad es que la parte de 10004/10021 originada por la latencia no se puede reducir mediante código: la única solución es acercarse físicamente. En cómo elegir un VPS para EAs se detalla cómo elegir uno
  3. Los EAs de scalping son los más afectados por la latencia. Si tu EA opera en marcos temporales diarios o H4, esta causa tiene menor prioridad

Código en MQL5 para reducir este error (para desarrolladores de EAs)

Hay tres líneas de trabajo: (1) configurar el deviation con un valor realista, (2) si se rechaza, volver a obtener el último tick y reenviar, y (3) limitar el reintento solo a los retcodes relacionados con el precio.

Configurar el deviation con un valor adecuado en points

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;   // Deslizamiento permitido de 20 points (2.0 pips en un bróker de 5 dígitos)
// También hay que configurar req.price / req.sl / req.tp / req.magic, etc.

La unidad de deviation es points. En brókers con cotización de 5 dígitos (3 dígitos), 10 points = 1 pip. Un valor de 0 o excesivamente pequeño incrementa innecesariamente la tasa de rechazo.

Reintentar solo con los retcodes relacionados con el precio (reenviando con el último tick)

El punto clave es volver a obtener el precio con SymbolInfoTick() en cada reintento (reenviar con el precio antiguo solo produce el mismo rechazo de nuevo), y limitar el reintento a 10004/10021. Reenviar mecánicamente ante fondos insuficientes (10019) o una solicitud inválida (10013) no tiene sentido y solo ensucia el log.

bool IsRetryableRetcode(uint rc)
{
   return (rc == TRADE_RETCODE_REQUOTE       // 10004
        || rc == TRADE_RETCODE_PRICE_OFF);   // 10021
}

// Reenvía hasta un máximo de 3 veces, actualizando el precio con el último tick en cada intento
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;                          // Ejecución exitosa

      if(!IsRetryableRetcode(res.retcode))
      {
         PrintFormat("OrderSend failed (no retry): retcode=%d", res.retcode);
         return false;                         // No reintentar si no es un retcode de precio
      }
      PrintFormat("Retry %d/%d after retcode=%d", attempt + 1, maxTries, res.retcode);
      Sleep(200 + 150 * attempt);              // Espera progresiva: 200ms → 350ms → 500ms
   }
   Print("Order abandoned after retries (price kept moving).");
   return false;
}

El motivo de alargar progresivamente el tiempo de espera de Sleep() es que, en el momento de un movimiento brusco, reenviar a 0ms de forma continua solo produce el mismo rechazo una y otra vez. Por el contrario, esperar demasiado hace que el precio de entrada se aleje de lo previsto por la estrategia, así que lo más sano es abandonar tras 2 o 3 reintentos. Ten en cuenta también que, en el caso de una orden pendiente (TRADE_ACTION_PENDING), el retcode de éxito es TRADE_RETCODE_PLACED (10008).

Usar el precio reofertado del requote (10004)

Cuando ocurre 10004, el precio reofertado por el servidor está en los campos bid / ask de MqlTradeResult. Reenviar con el último tick, como se muestra arriba, suele ser suficiente en la práctica, pero si quieres implementar una lógica de "aceptar el nuevo precio si está dentro de un rango tolerable" en ejecución instant, deberías comparar en points la diferencia entre res.ask / res.bid y el precio previsto originalmente antes de reenviar.

Crear franjas horarias en las que simplemente no se envíen órdenes

El reintento en código es un tratamiento paliativo. Un filtro que detenga las nuevas entradas antes y después del rollover, antes y después de la publicación de indicadores, o cuando el spread se amplía, es más efectivo de raíz.

// Ejemplo de filtro de spread: se descartan las nuevas entradas cuando el spread está ampliado
long spreadPts = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
if(spreadPts > MaxSpreadPoints)
{
   // Se descarta la nueva entrada (evita automáticamente las franjas con cotización escasa donde suele aparecer el 10021)
   return;
}

Los EAs distribuidos por FXEA365 incluyen de forma estándar este filtro de spread, filtro de indicadores y reintento automático de retcodes de precio.


Lista de comprobación por prioridad

PrioridadVerificaciónSolución
🚨 Primero¿Se concentra en el momento de publicaciones de indicadores o movimientos brusco?Activar el filtro de noticias, aceptar esa franja como parte del diseño
🚨 Primero¿El deviation es demasiado pequeño (recuerda que la unidad es points)?Ajustar a 10-30 points, verificar confusión pips/points
⚠️ Después¿Se concentra en el rollover, la apertura del lunes o símbolos poco activos?Filtro horario + filtro de spread
⚠️ Después¿El modo de ejecución es instant?Considerar también una cuenta con ejecución market (compromiso con el deslizamiento)
⚠️ Después¿El ping es alto (varios cientos de ms)?Migrar a un VPS más cercano al servidor
🛠 Desarrollo¿El reintento está limitado a los retcodes de precio?Volver a obtener el precio con SymbolInfoTick + detener tras 2-3 intentos

Resumen

  • El 10021 (TRADE_RETCODE_PRICE_OFF) significa "no hay cotización disponible para procesar", y el 10004 (TRADE_RETCODE_REQUOTE) significa "nueva propuesta de precio". Pertenecen a la misma familia de rechazo de precio que los códigos 136/138 de la era MT4, y no se trata de un problema de fondos ni de lotaje.
  • Las causas se resumen en cinco: movimiento brusco del mercado, deviation insuficiente, ejecución instant, franjas horarias/símbolos con cotización escasa, y latencia de conexión.
  • El requote es un fenómeno específico de la ejecución instant; en la ejecución market se manifiesta en su lugar como deslizamiento. "Que no aparezca" no significa "que sea mejor": es un compromiso.
  • Los desarrolladores de EAs deben aplicar medidas permanentes mediante 2-3 reintentos con el último tick (limitados a 10004/10021) + ajuste adecuado del deviation + filtros de horario/spread. La parte originada por la latencia solo se puede reducir con una medida física (un VPS más cercano al bróker).

Para el listado general de códigos de error, consulta la guía completa de códigos de error de MQL5/MT5, y para los EAs gratuitos que implementan estas medidas de forma estándar, consulta el listado de EAs.


Preguntas frecuentes

P: ¿Cuál es más grave, el 10004 o el 10021?

Ambos son errores temporales relacionados con el precio, y no hay una gran diferencia en gravedad entre ellos. El 10004 significa "se propuso un nuevo precio" y el 10021 significa "no había cotización disponible para procesar". Si ocurre de forma aislada, no representa un problema; solo cuando se repite con frecuencia en una franja horaria o símbolo determinado conviene atacar la causa (indicadores, rollover, deviation, conexión).

P: ¿Un bróker en el que nunca aparece el requote es mejor?

Es muy probable que se trate simplemente de una diferencia en el modo de ejecución. En las cuentas con ejecución market, el requote no puede producirse en principio, y cuando el precio se mueve, la orden se ejecuta directamente al precio desviado (deslizamiento). Es un compromiso entre ser rechazado o sufrir deslizamiento, así que conviene revisar el deslizamiento real en el historial de operaciones antes de sacar conclusiones.

P: Mi EA de MT4 muestra los errores 136 / 138. ¿Aplican las mismas soluciones?

Sí. El 136 (ERR_OFF_QUOTES) equivale al 10021, y el 138 (ERR_REQUOTE) equivale al 10004; tanto las causas como las soluciones son las mismas. En MQL4, la práctica habitual era llamar a RefreshRates() antes de reenviar para actualizar Bid / Ask, lo cual sigue la misma lógica que volver a obtener el precio con SymbolInfoTick() en MQL5.

P: No aparece en el backtest, pero sí en real.

Es normal. El Strategy Tester no reproduce (o simplifica en exceso) "el retraso hasta que la orden llega al servidor" ni "el movimiento de precio durante ese intervalo", por lo que 10004/10021 solo se manifiestan en forward. Aunque el backtest muestre buenos resultados, en real es necesario ajustar por separado la configuración del deviation, el reintento y el entorno de ejecución (VPS).

📧 Avisos antes de subidas de precio + curso gratuito de 5 días por email

Todos los EAs están a precio de lanzamiento y suben por escalones según las ventas. Reciba aviso antes de cada subida, más un email diario sobre trading algorítmico, cómo leer backtests y elegir bróker.

* Privacidad estrictamente protegida. Puedes darte de baja en cualquier momento.

Comentarios y preguntas