Bucles y cierre o eliminación de pedidos - página 5

 
Eleni Anna Branou:

Por favor, utilice el botón </> para insertar su código.


Mis disculpas... Aquí está en formato correcto..

OrdersTotal() no es correcto...

Me ha sorprendido que la secuencia de código en bucle que utiliza OrdersTotal() no da resultados correctos (observado con dos brokers diferentes).

Estoy usando MT4 versión 1090 en un escritorio Linux Ubuntu-MATE 16.04, corriendo WINE 3.0

Esto es lo que he estado usando...

Aquí está:

for(int cc = 0; cc < OrdersTotal(); cc++)
{
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderType() > 1) continue;    //--ignore pending trades

      OpenTradecnt++;    //--counts up for every live position of that symbol that exists
      Print("count of the open trades of this symbol is: ", OpenTradecnt);

He notado con dos brokers diferentes que el valor de OrdersTotal() no siempre coincide con lo que se muestra en la pestaña 'Trade' del broker de MT4. Inicialmente, pensé que era el broker el que provocaba que OrdersTotal() no funcionara correctamente. Cuando me di cuenta en el segundo broker, empecé a preguntarme si MT4 tenía un 'problema' interno, o si mi código era incorrecto O si se trataba de un problema con la sincronización correcta de MT4 con el servidor....?

Después de leer este hilo del foro, me pregunto si tendría mejores resultados alterando el bucle for..para que diga:

for(int cc = OrdersTotal() - 1; cc >= 0; cc--)
{
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderType() > 1) continue;    //--ignore pending trades

      OpenTradecnt++;    //--counts up for every live position of that symbol that exists
      Print("count of the open trades of this symbol is: ", OpenTradecnt);
O bien, ¿hay alguna bandera o línea de código que garantice que el OrdersTotal() se sincronice correctamente durante un evento OnTick()?

¡Cualquier aclaración con respecto a esto sería muy útil y sería muy apreciado!

 
Simon Gniadkowski:

Este es uno de los errores más comunes que veo, probablemente debido en parte a los gustos de la basura como Expert Advisor Builder. Así que pensé que era hora de un hilo dedicado al tema para que pueda ser vinculado para futuras referencias.

El problema

Pongamos un ejemplo sencillo, queremos una función que cierre todas las órdenes abiertas de nuestro EA, hay muchos ejemplos pero vamos a crear uno desde cero.

Necesitamos un bucle porque queremos cerrar todas nuestras órdenes para un EA específico, dentro de este bucle tendremos código para seleccionar la orden, código para comprobar que es el símbolo y el número mágico correctos y finalmente código para cerrar la orden:

Este código es malo . . . NO LO USES. . . En la siguiente sección explicaré por qué. . .

La explicación

Vamos a trabajar con el código anterior... línea por línea, orden por orden...

Supongamos que tenemos las siguientes órdenes que queremos cerrar, todas tienen el mismo número mágico y el mismo símbolo que nuestro EA, así que queremos que nuestro código las cierre todas:

Posición Número de la entrada
0111
1222
2 333
3444
4555

1ª pasada por el bucle:

el valor inicial de PositionIndex es 0 por lo que se selecciona la orden en la posición 0, número de ticket 111, esta orden se elimina con éxito y el resto de órdenes cambian de posición de la siguiente manera:

Posición Número de ticket
0222
1 333
2444
3555

Segunda pasada por el bucle:

ahora el valor de PositionIndex es 1 por lo que se selecciona la orden en la posición 1, número de ticket 333, esta orden es eliminada con éxito y el resto de órdenes cambian de posición de lasiguiente manera:

Posición Número de ticket
0222
1 444
2555

Tercera pasada por el bucle:

ahora el valor de PositionIndex es 2 por lo que se selecciona la orden en la posición 2, número de ticket 555, esta orden se elimina con éxito y el resto de órdenes cambian de posición de la siguiente manera:

Posición Número de ticket
0222
1 444

4ª ejecución del bucle:

ahorael valor de PositionIndex es 3 OrderSelect() intenta seleccionar la Orden en la posición 3 y falla, el continue lleva la ejecución del código al siguiente valor del bucle .


5ª y última ejecución del bucle:

ahora el valorde PositionIndex es 4 OrderSelect() intenta seleccionarla Orden en la posición 4 y falla, el continue lleva la ejecución del código al siguiente valor del bucle . . el bucle ha terminado.


Ahora nos quedamos con 2 Pedidos, los tickets 222 y 444 que deberían haber sido cerrados pero no lo fueron. . . a continuación, cómo resolver este problema.

La Solución

El siguiente código es el enfoque correcto cuando se cierran órdenes abiertas o se borran órdenes pendientes. . .

La diferencia clave es que el bucle disminuye de ( TotalNumberOfOrders - 1 ) a 0

Una vez más, repasemos el código anterior... línea por línea, orden por orden...

Tenemos los mismos pedidos que antes:

Posición Número de ticket
0111
1222
2333
3444
4555

1ª pasada por el bucle:

el valor inicial de PositionIndex es TotalNumberOfOrders - 1 que es igual a 5 - 1 = 4, por lo que se selecciona la orden en la posición 4, número de ticket 555, esta orden se elimina con éxito y el resto de órdenes cambian de posición de la siguiente manera:

Posición Número de ticket
0111
1222
2333
3444

Segunda pasada por el bucle:

ahora el valor de PositionIndex es 3 por lo que se selecciona la orden en la posición 3, número de ticket 444, esta orden se elimina con éxito y el resto de órdenes cambian de posición de lasiguiente manera:

Posición Número de ticket
0111
1222
2333

Tercera pasada por el bucle:

ahora el valor de PositionIndex es 2 por lo que se selecciona la orden en la posición 2, número de ticket 333, esta orden se elimina con éxito y el resto de órdenes cambian de posición de la siguiente manera:

Posición Número de ticket
0111
1222

cuarta pasada por el bucle:

ahora el valor de PositionIndex es 1 por lo que se selecciona la orden en la posición 1, número de ticket 222, esta orden se elimina con éxito y el resto de órdenes cambian de posición de lasiguiente manera:

Posición Número de ticket
0111

5ª y última pasada por el bucle:

ahora el valor de PositionIndex es 0 por lo que se selecciona la orden en la posición 0, número de ticket 111, esta orden se elimina con éxito, el valor 0 es el último valor válido para el bucle... el bucle ha terminado.

Hemos eliminado con éxito todas nuestras órdenes coincidentes. . .

Enlace a este hilo: Bucles y cierre o eliminación de órdenes

muchas gracias! es una explicación muy clara
 
Hola coders,
He revisado este hilo leyendo sobre la selección de órdenes. Efectivamente, tengo un código en el que creo haber hecho las cosas bien pero la selección no me funciona ya que no puedo leer el OpenPrice de laorden seleccionada. Todo lo demás funciona bien, sólo esa parte del código proporcionado. No estoy seguro de por qué.
Todo el código tiene 4 secciones donde necesito llamar al OrderOpenPrice justo después de que la orden sea enviada... OrderSend funciona bien, OrderSelect no me da los resultados que necesito. Refiérase a 1 sección del código si puede ayudar.
Gracias.
 if(Protection_Step_One==1)
        {
        while(Protective_Order<0)
          {
          RefreshRates();
          Protective_Order=OrderSend(Symbol(),OP_SELL,Protective_Lots,NormalizeDouble(MarketInfo(Symbol(),MODE_BID),MarketInfo(Symbol(),MODE_DIGITS)),3,0,0,"Intermediary",MN_Sell_Intermediary_Protection,0,Cyan);
          }
  //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Addition for Clamp       
          for (int i=OrdersTotal()-1; i>=0; i--)
            {if(OrderSelect(i,SELECT_BY_POS, MODE_TRADES)==true)
               {if (OrderMagicNumber()==MN_Sell_Intermediary_Protection)
                  { RefreshRates();
                  Intermediary_OpenPrice_Sell= OrderOpenPrice();
                  }
                }
             }   
               //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>..
        if(Protective_Order!=-1)
          { 
          Protection_Step_One=0;
          RealTime_Drawing=2;
          Protective_Mode_Activated=1;
          Protective_Order=-2;
          Defcon=2;

 

Gracias queridoSimon Gniadkowski,

Tu post realmente me ha salvado el tiempo.

 
Gelson Kasonia:
void OnStart()
{
     int Protective_Order=OrderSend(_Symbol,ORDER_TYPE_BUY,0.01,Ask,3,0,0,"Intermediary");
     if(Protective_Order<0)
          return;
     if(!OrderSelect(Protective_Order,SELECT_BY_TICKET, MODE_TRADES))
          return;
     Print(Protective_Order, " OrderOpenPrice: ", OrderOpenPrice());
}
 

Este es el código que sugiero para cerrar las órdenes de mercado

int MagicNo=1234;
int Slippage=10;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseOrdersBackward()
  {
   for(int i=OrdersTotal()-1; i>=0 && !IsStopped(); i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         Print("Order Select failed, order index: ",i," Error: ",GetLastError());
         continue;
        }

      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNo && OrderType()<=OP_SELL)
        {
         if(!OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage))

            Print("Order Close failed, order ticket: ",OrderTicket()," Error: ",GetLastError());
        }
     }
  }

Y sugiero que, esta es la forma correcta si se utiliza un bucle forward for (para cumplir con las reglas FIFO de los brokers de EEUU)

int MagicNo=1234;
int Slippage=10;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseOrdersForward()
  {
   for(int i=0; i<OrdersTotal() && !IsStopped(); i++)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         Print("Order Select failed, order index: ",i," Error: ",GetLastError());
         continue;
        }

      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNo && OrderType()<=OP_SELL)
        {
         if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage))
           {
            i--;
           }
         else
           {
            Print("Order Close failed, order ticket: ",OrderTicket()," Error: ",GetLastError());
           }
        }
     }
  }

En el bucle forward,

  1. La función OrderTotal() se utiliza dentro del bucle for para actualizar el número restante de órdenes abiertas con cada iteración del bucle, para evitar el índice fuera del rango del array.
  2. El índice i se decrementa con cada orden cerrada, para evitar saltarse algunas órdenes.
 
amrali: El índice i se decrementa con cada orden cerrada, para evitar saltarse algunas órdenes.
En presencia de múltiples órdenes (un EA, múltiples gráficos, múltiples EAs, trading manual,) mientras se espera a que la operación actual (cierre, borrado, modificación) se complete, cualquier número de otras operaciones en otras órdenes podría haber sucedido concurrentemente y cambiado la indexación de la posición:
  1. Para los corredores que no son FIFO (corredores de EE.UU.)(o el EA sólo abre una orden por símbolo), puede simplemente contar hacia abajo en un bucle de posición, y no perderá las órdenes. Acostúmbrese a contar siempre hacia abajo.
    Bucles y cierre o eliminación de órdenes - Foro de programación MQL4
    Para FIFO (corredores de EE.UU.,)y usted (potencialmente) procesa múltiples órdenes por símbolo, debe Encontrar la orden más temprana, cerrarla, y en una operación exitosa, reprocesar todas las posiciones restantes.
    CerrarOrdenes por Reglas FIFO - Probador de Estrategias - Foro de programación MQL4 - Página 2 #16

  2. y compruebe OrderSelect en caso de que las posiciones anteriores se hayan eliminado.
    ¿Qué son los valores de retorno de la función? ¿Cómo los utilizo? - Foro de programación MQL4
    Errores comunes en los programas MQL4 y cómo evitarlos - Artículos MQL4
  3. y si usted (potencialmente) procesa múltiples órdenes, debe llamar aRefreshRates() después de las llamadas al servidor si quiere usar, en la siguiente orden / llamada al servidor, las Variables Predefinidas(Bid/Ask) o (ser independiente de la dirección y usar) OrderClosePrice().
 

Sabrás lo mucho que me ha ayudado esto. No sólo con el código en el que estaba trabajando, sino con mi comprensión por completo. Ahora funciona perfectamente y tengo la comprensión para implementarlo de diferentes maneras.

Realmente aprecio esta información.