Bucles y cierre o eliminación de pedidos

 

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:

int PositionIndex;    //  <-- this variable is the index used for the loop

int TotalNumberOfOrders;   //  <-- this variable will hold the number of orders currently in the Trade pool

TotalNumberOfOrders = OrdersTotal();    // <-- we store the number of Orders in the variable

for(PositionIndex = 0; PositionIndex < TotalNumberOfOrders; PositionIndex++)  //  <-- for loop to loop through all Orders
   {
   if( ! OrderSelect(PositionIndex, SELECT_BY_POS, MODE_TRADES) ) continue;   // <-- if the OrderSelect fails advance the loop to the next PositionIndex
   
   if( OrderMagicNumber() == MagicNo       // <-- does the Order's Magic Number match our EA's magic number ? 
      && OrderSymbol() == Symbol()         // <-- does the Order's Symbol match the Symbol our EA is working on ? 
      && ( OrderType() == OP_BUY           // <-- is the Order a Buy Order ? 
      ||   OrderType() == OP_SELL ) )      // <-- or is it a Sell Order ?

      if ( ! OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), Slippage ) )               // <-- try to close the order
         Print("Order Close failed, order number: ", OrderTicket(), " Error: ", GetLastError() );  // <-- if the Order Close failed print some helpful information 
      
   } //  end of For loop

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

int PositionIndex;    //  <-- this variable is the index used for the loop

int TotalNumberOfOrders;   //  <-- this variable will hold the number of orders currently in the Trade pool

TotalNumberOfOrders = OrdersTotal();    // <-- we store the number of Orders in the variable

for(PositionIndex = TotalNumberOfOrders - 1; PositionIndex >= 0 ; PositionIndex --)  //  <-- for loop to loop through all Orders . .   COUNT DOWN TO ZERO !
   {
   if( ! OrderSelect(PositionIndex, SELECT_BY_POS, MODE_TRADES) ) continue;   // <-- if the OrderSelect fails advance the loop to the next PositionIndex
   
   if( OrderMagicNumber() == MagicNo       // <-- does the Order's Magic Number match our EA's magic number ? 
      && OrderSymbol() == Symbol()         // <-- does the Order's Symbol match the Symbol our EA is working on ? 
      && ( OrderType() == OP_BUY           // <-- is the Order a Buy Order ? 
      ||   OrderType() == OP_SELL ) )      // <-- or is it a Sell Order ?
   
      if ( ! OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), Slippage ) )               // <-- try to close the order
         Print("Order Close failed, order number: ", OrderTicket(), " Error: ", GetLastError() );  // <-- if the Order Close failed print some helpful information 
      
   } //  end of For loop

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

 

Tomemos un ejemplo más complejo...

Supongamos que tenemos las siguientes órdenes que queremos cerrar, todas tienen el mismo número mágico pero algunas tienen un símbolo diferente al de nuestro EA, queremos que nuestro código cierre las órdenes para el mismo símbolo que nuestro EA, EURUSD:

Posición Número de Ticket Símbolo
0111 EURUSD
1222 EURUSD
2333GBPUSD
3444 EURUSD
4555 EURUSD


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 coincide con el número mágico y el símbolo por lo que se elimina con éxito y el resto de órdenes cambian de posición de la siguiente manera:

Posición Número de billete Símbolo
0111EURUSD
1222EURUSD
2333GBPUSD
3444EURUSD

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 coincide con el número mágico y el símbolo por lo que se elimina con éxito y el resto de órdenes cambian de posición de lasiguiente manera:

Posición Número de billete Símbolo
0111EURUSD
1222EURUSD
2333GBPUSD


3ª 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 coincide con el número mágico pero NO conel símbolo por lo que no se elimina, el resto de órdenes no cambian:

Posición Número de billete Símbolo
0111EURUSD
1222EURUSD
2333GBPUSD

4ª ejecución del 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 coincide con el número mágico y el Símbolo por lo que se elimina con éxito y el resto de órdenes cambian de posición de lasiguiente manera:

Posición Número de billete Símbolo
0111EURUSD
1333GBPUSD

5ª y última pasada por el bucle:

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

Hemos eliminado con éxito todas las órdenes que coincidían, dejando la única orden que no coincidía con nuestro símbolo, el ticket número 333 ahora en la posición 0. .

Posición Número de billete Símbolo
0333GBPUSD


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

 
Vea también por qué debe contar y probar el estado de OrderSelect
 

Gracias Raptor por esta importante explicación.

Y.

 
Esto es extremadamente útil para mí, ¡el rey del constructor de asesores expertos de la basura! Oh, cómo disfruto hackeando el código resultante. Muchas gracias.
 

Vaya. Toda esa información para cerrar una orden.

Me pregunto cuánta información se necesitaría para obtener más de 50 pips al día, consistentemente, todos los días (en promedio) - sin fallar, a través de las últimas 137 operaciones.

Muéstrame cómo hacer algo así, y lo consideraría información extremadamente útil y Gurú, será tu título, por los siglos de los siglos, Amén.

 
CFx:

Vaya. Toda esa información para cerrar una orden.

Me pregunto cuánta información se necesitaría para obtener más de 50 pips al día, consistentemente, todos los días (en promedio) - sin falta, a través de las últimas 137 operaciones.

No me interesan los pips... ¿qué puedo hacer con ellos? No puedo gastarlos, ¿cuál es la tasa de GBPPIPS ? usted muestra su ignorancia al contar el éxito en pips .
 
CFx:

Me pregunto cuánta información se necesitaría para obtener más de 50 pips al día, de forma consistente, todos los días (en promedio) - sin falta, a través de las últimas 137 operaciones.

Muéstrame cómo hacer algo así, y lo consideraré información extremadamente útil y Gurú, será tu título, por los siglos de los siglos, Amén.

  1. No secuestrar el hilo con la información fuera de tema
  2. NO vamos a mostrarte eso porque no has leído las reglas Cualquier discusión excepto la relacionada con MetaQuotes Language 4 y el auto trading está prohibida
 

Raptor, sé a primera vista de su puesto que u r bastante n experto en mql4.this hilo de nuevo ayuda a aclarar mis dudas! mantener el buen trabajo.tnx

 

Sólo una idea más:

for(PositionIndex = 0; PositionIndex < OrdersTotal() ; PositionIndex ++)  //  <-- for loop to loop through all Orders . .   COUNT DOWN TO ZERO !
   {
   if( ! OrderSelect(PositionIndex, SELECT_BY_POS, MODE_TRADES) ) continue;   // <-- if the OrderSelect fails advance the loop to the next PositionIndex
   
   if( OrderMagicNumber() == MagicNo       // <-- does the Order's Magic Number match our EA's magic number ? 
      && OrderSymbol() == Symbol()         // <-- does the Order's Symbol match the Symbol our EA is working on ? 
      && ( OrderType() == OP_BUY           // <-- is the Order a Buy Order ? 
      ||   OrderType() == OP_SELL ) )      // <-- or is it a Sell Order ?
   
         add_trade_to_close_queue( OrderTicket());  // <--  You need to model the queue mechanism ...
      
   } //  end of For loop


Saludos.

 
abstract_mind:


Sólo una idea más:


Saludos.

sí, entender la lógica detrás de MT4, es hasta usted para codificar aumento o disminución de contador.