Mi EA hace una doble entrada - página 7

 

¿si uso el sueño, perderé las garrapatas?

¿cuáles serán las consecuencias? ¿puede compartir conmigo?

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 
doshur:

¿si uso el sueño, perderé las garrapatas?

¿cuáles serán las consecuencias? ¿puede compartirlo conmigo?

Depende de su estrategia. Como este problema de "dobles operaciones" sólo puede ocurrir cuando tu código de trading se ejecuta en cada tick, probablemente tienes una estrategia que depende del tick. Así que depende de usted para evaluar lo que puede ser la consecuencia si la pérdida de los ticks que llega durante su retraso (sueño).

 
angevoyageur:

Depende de su estrategia. Como este problema de "dobles operaciones" sólo puede ocurrir cuando su código de trading se ejecuta en cada tick, probablemente tiene una estrategia que depende del tick. Así que depende de usted para evaluar lo que puede ser la consecuencia si la pérdida de los ticks que llega durante su retraso (sueño).

Así que si duermo durante 800

¿significa que pierdo los ticks durante los siguientes 800ms? Después de entrar en mi comercio, mi EA no hace nada, sólo se sienta allí hasta TP o SL o esperar el tiempo para salir.

¿Así que mi estrategia está bien si uso el sleep?

¿llamar a refreshrates() recupera los ticks?

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 
doshur:

Así que si duermo durante 800

significa que pierdo ticks durante los siguientes 800ms? Después de entrar en mi comercio, mi EA no hace nada, sólo se sienta allí hasta TP o SL o esperar el tiempo para salir.

¿Así que mi estrategia está bien si uso el sleep?

¿llamar a refreshrates() recupera los ticks?

doshur, los ticksque se pierden, se pierden, no hay máquina de retroceso.

Respecto a la documentación enhttps://www.mql5.com/en/docs/common/sleep la funciónsuspende la ejecución del Asesor Experto actual o del script en un intervalo especificado.

Por lo tanto, incluso los eventos OnTimer se suspenderá, probablemente porque la EA utiliza sólo un hilo.

Por lo tanto, el uso de un sueño fijo no es una solución definitiva, es sólo "numerología", es decir, una solución si el retraso es menor que su valor.

Y es por eso que propongo un bucle de prueba PositionSelect después de abrir el comercio, para comprobar la ejecución PositionOpen y volver como una mejor solución que sólo Sleep(), y que también comprobar la causa del problema (de acuerdo con las pruebasangevoyageur).

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 

Esto es lo que estoy usando ahora. ¿Dónde debería codificar la solución proporcionada por figurelli de una manera más elegante

//
         {
            Price = SymbolInfoDouble(Symbol(), SYMBOL_ASK);

            if(m_Trade.PositionOpen(Symbol(), ORDER_TYPE_BUY, LotSize, Price, 0, 0))
            {
               Sleep(800);

               if(m_Trade.ResultRetcode() == 10009)
               {
                  Print("Position opened in ", Symbol());

                  return;
               }
               else
               {
                  Print("Error opening position in ", Symbol(), " - ", m_Trade.ResultComment(), "\n", "Return Code Desc - ", m_Trade.ResultRetcodeDescription());
               }
            }
            else
            {
               Print("Error with PositionOpen in ", Symbol(), " - ", m_Trade.ResultComment(), "\n", "Return Code Desc - ", m_Trade.ResultRetcodeDescription());
            }
         }
 
doshur:

Esto es lo que estoy usando ahora. ¿Dónde debería codificar la solución proporcionada por figurelli de una manera más elegante

Hola doshur, yo también estaba teniendo problemas con las entradas dobles en uno de mis EA's. En realidad, estos problemas ocurrían sólo cuando operaba con activos muy líquidos. Incluso después de configurar las órdenes para ser enviadas en modo asíncrono, el EA estaba "aparentemente" esperando demasiado tiempo para una respuesta del servidor para actualizar PositionsTotal()... mientras tanto, otros ticks entrantes estaban activando las condiciones para enviar una segunda orden... en el foro portugués publiqué una solución, que me gustaría compartir aquí.

La idea es simple:

//--- global variables
CTrade trade;
bool position_opened=false;

//--- inside OnTick()
if( conditions to open && position_opened==false )
  {
   //--- set the global variable to true to avoid duplicate orders
   position_opened=true;
   trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment");
  }

El único problema con este código es el caso en que la orden no es aceptada por el servidor, por lo que hay que "reiniciar" la variable global... Podrías usar esto:

MqlTradeResult mresult;

//--- 
if(mresult.retcode==10009 || mresult.retcode==10008)
  {Print("Success!");}
else 
  {
   Print("Error = ",GetLastError());
   ResetLastError();
   //--- Sets the global variable to false
   position_opened=false;
   return;
  }

Así, en el caso de que la primera orden enviada devolviera un error, la variable global se pondría en falso para que el EA pudiera enviar otra orden. Sin embargo, tengo que decir que he probado este código sólo en acciones y futuros, pero no en el mercado de divisas... :-(

 
Malacarne:

Hola doshur, yo también estaba teniendo problemas con las entradas dobles en uno de mis EA's. En realidad, estos problemas ocurrían sólo cuando operaba con activos muy líquidos. Incluso después de configurar las órdenes para ser enviadas en modo asíncrono, el EA estaba "aparentemente" esperando demasiado tiempo para una respuesta del servidor para actualizar PositionsTotal()... mientras tanto, otros ticks entrantes estaban activando las condiciones para enviar una segunda orden... en el foro portugués publiqué una solución, que me gustaría compartir aquí.

La idea es simple:

El único problema con este código es el caso de que la orden no sea aceptada por el servidor, por lo que hay que "resetear" la variable global... Podrías usar esto:

Así, en el caso de que la primera orden enviada devolviera un error, la variable global se pondría en falso para que el EA pudiera enviar otra orden. Sin embargo, tengo que decir que he probado este código sólo en acciones y futuros, pero no en el mercado de divisas... :-(

Esto parece viable. A ver sifigurelli yangevoyageur tienen algún comentario sobre esta solución...
 
doshur:
Esto parece viable. Vamos a ver sifigurelli yangevoyageur tiene algún comentario sobre esta solución...

Esta solución propuesta por Malacarne (con algunos ajustes que propondré) es genial, ya que para mí no es un workaround (como modestamente refiere Malacarne), sino una forma elegante y correcta de abordar esta cuestión.

En mi opinión, el problema original de la doble entrada no es un error de MT5, sino un error de codificación, ya que la ayuda indica:

"Lafinalización con éxito del método PositionOpen(...) no siempre significa la ejecución con éxito de la operación comercial. Es necesario comprobar el resultado de la solicitud de comercio (código de retorno del servidor de comercio) utilizandoResultRetcode() y el valor, devuelto porResultDeal()."

Por lo tanto, sugiero algunos pequeños cambios para ser más resistente a cualquier condición del mercado:

1) Probar el retorno de PostionOpen() también, como el código original, por ejemplo:

if (trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment")) position_opened=true;

2) Un tratamiento más completo de ResultRetcode(), ya que se pueden abrir otras posiciones relevantes, como 10010 -TRADE_RETCODE_DONE_PARTIAL - Sólo se completó una parte de la solicitud. Además, 10008 - TRADE_RETCODE_PLACED - Orden colocada no es un éxito para mí, sólo 10009 -TRADE_RETCODE_DONE -Solicitud completada, y esto son mensajes asíncronos, por lo que la segunda parte del código de Malacarne podría considerar esto y / obillete de acuerdo, después de que el acuerdo se ejecuta,también.

De todos modos, me parece que estamos en el camino correcto y el corte final ahora.

 
Malacarne:

Hola doshur, yo también estaba teniendo problemas con las entradas dobles en uno de mis EA's. En realidad, estos problemas ocurrían sólo cuando operaba con activos muy líquidos. Incluso después de configurar las órdenes para ser enviadas en modo asíncrono, el EA estaba "aparentemente" esperando demasiado tiempo para una respuesta del servidor para actualizar PositionsTotal()... mientras tanto, otros ticks entrantes estaban activando las condiciones para enviar una segunda orden... en el foro portugués publiqué una solución, que me gustaría compartir aquí.

La idea es simple:

El único problema con este código es el caso de que la orden no sea aceptada por el servidor, por lo que hay que "resetear" la variable global... Podrías usar esto:

Así, en el caso de que la primera orden enviada devolviera un error, la variable global se pondría en falso para que el EA pudiera enviar otra orden. Sin embargo, tengo que decir que he probado este código sólo en acciones y futuros, pero no en el mercado de divisas... :-(

Es un enfoque válido, sin embargo usted tiene que restablecer su variable global position_opened a false cuando su posición se cierra. ¿Dónde está haciendo eso?

Sobre su implementación, algunos detalles :

  1. No hay necesidad de establecer position_opened a true y luego a false si hay un error.
  2. Usted está utilizando un objeto de la clase CTrade, por lo que no es necesario utilizar una nueva estructura MqlTradeResult.
  3. Como figuralli señaló en su post, usted tiene que comprobar el valor devuelto de PositionOpen.
  4. El nombre de la clase es CTrade, no Ctrade. mql5 distingue entre mayúsculas y minúsculas.
  5. position_opened es un bool, no es necesario compararlo con false. Si lo haces, tienes que usar '==' y no '='.

Así que, aquí está el código modificado(Compilado pero no probado) :

//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2012, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>

//--- global variables
CTrade trade;
bool position_opened=false;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
   bool conditions_to_open;
   ENUM_ORDER_TYPE order_type;
   double lot;
   double price,sl,tp;

//---...set variables

//--- inside OnTick()
   if(conditions_to_open && !position_opened) //-- Or position_opened==false
     {
      if(trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment")
         && 
         (trade.ResultRetcode()==10009 || trade.ResultRetcode()==10008)) //-- Or others condition according to your needs
        {
         //--- set the global variable to true to avoid duplicate orders
         position_opened=true;
         Print("Success!");
        }
      else
        {
         Print("Error = ",GetLastError(), "trade error = ", trade.ResultRetcode());
         //--- Sets the global variable to false
         // position_opened=false;                                         //-- Not needed as position_opened is already false
         return;
        }

     }
//--- 
  }
//+------------------------------------------------------------------+
 
figurelli:

...

En mi opinión, el problema original de la doble entrada no es un error de MT5, sino un error de codificación, ya que la ayuda indica:

"Lafinalización exitosa del método PositionOpen(...) no siempre significa la ejecución exitosa de la operación de comercio. Es necesario comprobar el resultado de la solicitud de comercio (código de retorno del servidor de comercio) utilizandoResultRetcode() y el valor, devuelto porResultDeal()."

No creo que esté relacionado con la cuestión de este tema. El problema que tenemos es en el caso de que una solicitud se rellene con éxito y se abra una posición. Pero esta posición se abre en el servidor de operaciones, el problema que nos encontramos es cuando hay un retraso más importante de lo habitual y el terminal MT5 es notificado de esta nueva posición DESPUÉS de que un nuevo tick ya está procesado.

No es un error, ya que está diseñado de esta manera. PERO en mi opinión es un mal diseño para una plataforma que permite explícitamente peticiones de trading sincrónicas y asincrónicas. Estamos hablando aquí de una solicitud que se supone que es sincrónica, pero de hecho no es realmente sincrónica ya que cuando se obtiene la respuesta del servidor para la solicitud (trade.ResultRetCode en el código anterior) todavía tenemos que esperar a que la plataforma MT5 sea informada y actualizada sobre los resultados de la negociación. (He entendido todo esto con este hilo).

Por lo tanto, sugiero algunos pequeños cambios para ser más resistente a cualquier condición del mercado:

1) Prueba PostionOpen() retorno también, como el código original, por ejemplo:

2) Un tratamiento más completo de ResultRetcode(), ya que se pueden abrir otras posiciones relevantes, como la 10010 -TRADE_RETCODE_DONE_PARTIAL - Sólo se completó una parte de la solicitud. Además, 10008 - TRADE_RETCODE_PLACED - Orden colocada no es un éxito para mí, sólo 10009 -TRADE_RETCODE_DONE -Solicitud completada, y esto son mensajesasíncronos, porlo que la segunda parte del código de Malacarne podría considerar esto y / obillete de acuerdo, después de que el acuerdo se ejecuta,también.

De todos modos, me parece que estamos en el camino correcto y el corte final ahora.

Por supuesto, tienes toda la razón en que hay que comprobar el valor devuelto de PositionOpen Y el código devuelto del resultado de la operación. Sin embargo el ResultRetCode es síncrono, es la actualización de la base de datos de MT5 sobre la posición (trato y orden) que es asíncrona. La prueba que hice con su propuesta demostró esto, ya que uso por supuesto un código que comprueba el valor devuelto de la solicitud de comercio.