Cualquier pregunta de los recién llegados sobre MQL4 y MQL5, ayuda y discusión sobre algoritmos y códigos - página 755

 

Hola. No puedo entender qué es lo que está mal.

Hay dos órdenes con menor y mayor volumen y diferente take profit. La orden con el menor volumen se abre primero, y luego la orden con el mayor volumen. Necesitamos encontrar un Take Profit para la orden con mayor volumen.

//MaxLotBuy() - функция находит ордер с наибольшим объемом (в Comment("") показывает правильные значения)
//buyTpL - в глобальных переменных
//---------------------------------------------
for(i = total-1; i >= 0; i--)
{
   if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
   {
      if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
      { 
         if(OrderType() == OP_BUY)
         { 
            if(OrderLots() == MaxLotBuy())
               buyTpL = OrderTakeProfit();
         }
      }
   }
} 

Todo parece correcto pero por alguna razón, obtenemos valores de take profit de la orden con un volumen menor (fue abierta primero). ¿Qué ocurre?

P.D. total = OrdersTotal()

 
Youri Lazurenko:

Hola. No puedo entender qué es lo que está mal.

Hay dos órdenes con menor y mayor volumen y diferente take profit. La orden con el menor volumen se abre primero, y luego la orden con el mayor volumen. Necesitamos encontrar un Take Profit para la orden con mayor volumen.

Todo parece correcto pero por alguna razón, obtenemos valores de take profit de la orden con un volumen menor (fue abierta primero). ¿Qué ocurre?

P.S. Total = OrdersTotal()

Parece que la función MaxLotBuy() contiene su propia búsqueda de órdenes y parece que se selecciona otra orden cuando volvemos a esta función. Evitar el rebote de pedidos fuera de algún ciclo de rebote de pedidos. No entiendo lo que he dicho. Pero es cierto.

En esta situación, es mejor declarar una variable antes del bucle y asignarle el valor de OrderLots() siempre que el nuevo valor sea mayor que el anterior.

double orderLot = 0;
for(i = total-1; i >= 0; i--)
{
  if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
   {
      if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
      { 
         if(OrderType() == OP_BUY)
         { 
            if(OrderLots() > orderLot)
             {
              orderLot = OrderLots();
              buyTpL = OrderTakeProfit();
             }
         }
      }
   }
} 
 
Alexey Viktorov:

La función MaxLotBuy() parece tener su propio bucle de orden y se selecciona otra orden al volver a esta función. Hay que evitar pasar por la orden fuera de cualquier bucle de orden. No entiendo lo que he dicho. Pero es cierto.

En esta situación, es mejor declarar una variable antes del bucle y asignarle el valor de OrderLots() siempre que el nuevo valor sea mayor que el anterior.

Gracias. Sí,MaxLotBuy() tiene su propia enumeración de órdenes, pero el valor de retorno es el máximo (te doy el código).

//  GetLots() - функция мани менеджмента
//------------------------
double MaxLotBuy()
{
   int    i;
   int    total  = OrdersTotal();
   double lot    = GetLots();
   
   if(CountBuy() == 0)
      lot = GetLots();
   
   if(CountBuy() >= 1)
   {   
      for(i = total-1; i >= 0; i--)
      {
         if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
            {
               if(OrderType() == OP_BUY) 
               {
                  if(lot < OrderLots())
                     lot = OrderLots();
               }
            }
         }
      }
   }
   return(lot);
}

Pero he entendido su idea, gracias. Lo probaré ahora.

 
Konstantin Nikitin:
Probablemente sea el camino correcto.

Gracias, eso parece mejor.

 
Konstantin Nikitin:
Creo que lo correcto sería

Gracias. No sólo hay que tener cuidado cuando te escribes a ti mismo.

Aunque eso es exactamente lo que dice en palabras.

declarar una variable antes del bucle


 

Chicos, muchas gracias; funciona como debería. Acaba de añadir un reinicio a la posición original también.

   int    i;     
   int    total       = OrdersTotal();
   double orderLotBuy = GetLots();

   if(CountBuy() == 0)
      orderLotBuy = GetLots();

   for(i = total-1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
         { 
            if(OrderType() == OP_BUY)
            { 
               if(OrderLots() > orderLotBuy)
               {
                  buyTpL      = OrderTakeProfit();
                  orderLotBuy = OrderLots();
               }
            }
         }
      }
   } 
   
 
Youri Lazurenko:

Chicos, muchas gracias; funciona como debería. Acaba de añadir un reinicio a la posición original también.

Bueno, sí. Mi ejemplo no está completo. Acabo de corregirlo, lo he complementado y mi corrección ha coincidido en el tiempo con tu mensaje.
 
Alexey Viktorov:
Pues sí. Mi ejemplo no está completo. Acabo de corregirlo, lo he complementado y mi corrección ha coincidido con tu mensaje en el tiempo.

No importa que no esté completo, lo que importa es la idea correcta, el enfoque correcto. Gracias a todos de nuevo.

 
Youri Lazurenko:

No importa que no esté completo, lo que importa es la idea correcta, el enfoque correcto. Gracias a todos una vez más.

Entonces es así

   int    total       = OrdersTotal();
   double orderLotBuy = GetLots();

   if(CountBuy() > 0)
      for(i = total-1; i >= 0; i--)
      {
         if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
            { 
               if(OrderType() == OP_BUY)
               { 
                  if(OrderLots() > orderLotBuy)
                  {
                     buyTpL      = OrderTakeProfit();
                     orderLotBuy = OrderLots();
                  }
               }
            }
         }
      } 
 
Konstantin Nikitin:

Entonces se ve así

Básicamente no he publicado todo el código, sino sólo una parte de encontrar el take profit de la orden con el lote más alto. La cuestión es la siguiente: cuando el precio se invierte, se coloca una orden pendiente con un lote mayor. Si funciona, se establece un stop loss en la orden opuesta, de modo que cuando la orden con lote grande se cierra en el Take Profit, la orden con beneficio negativo en el stop loss también se cierra. El código completo de la modificación con el establecimiento de un stop loss tiene el siguiente aspecto

// sp            - величина спреда
// FirstOrderBuy - дабы избежать error1
//----------------------------------------------- 
     int i;
      
      int    total        = OrdersTotal();
      double orderLotBuy  = GetLots();     
   
      static int FirstOrderBuy  = 0;     

      if(CountBuy() < FirstOrderBuy)
         FirstOrderBuy = 0; 
         
      if(CountBuy() == 0)
         orderLotBuy = GetLots();
      
      if(CountSell() >= 1 && CountBuy() > FirstOrderBuy && MaxLotBuy() > MaxLotSell())
      {
         for(i = total-1; i >= 0; i--)
         {
            if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
            {
               if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
               { 
                  if(OrderType() == OP_BUY)
                  { 
                     if(OrderLots() > orderLotBuy)
                     {
                        buyTpL      = OrderTakeProfit();
                        orderLotBuy = OrderLots();
                     }
                  }
               }
            }
         } 
                        
         for(i = total-1; i >= 0; i--)
         {
            if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
            {
               if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
               { 
                  if(OrderType() == OP_SELL)  
                  {               
                     if(OrderStopLoss() == 0 || (OrderStopLoss() != 0 && OrderStopLoss() > OrderOpenPrice()))
                     {
                        slSell = NormalizeDouble(buyTpL + sp*point, Digits);
                        
                        OrderModifyX(OrderTicket(), OrderOpenPrice(), slSell, OrderTakeProfit(), 0, 0);
                     }
                  }    
               }
            }
         }
         FirstOrderBuy = CountBuy();
      }

P.D. Durante las pruebas, hay muchos matices que deben ser "explicados" al Asesor Experto en cuanto a cómo debe comportarse en ciertos casos.