asesor experto - preguntas varias - página 24

 

Ya está en el ejemplo.

Cuando se cierra la orden se utiliza el valor de retorno booleano de la función OrderClose(), y si la función tuvo éxito, se pueden eliminar los objetos relacionados con la orden.

                           bool close=OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),3,clrBlue);
                             {
                              if(close==0)
                                {
                                 Alert(" Order Close Error! # "+IntegerToString(OrderTicket()));
                                }
                              if(close==1)
                                {
                                 Alert(" Order: "+IntegerToString(OrderTicket())+" Closed due to TP Profit = "+DoubleToString(OrderProfit(),2));
                                 ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-TP");
                                 ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-SL");
                                }
                             }
 
Marco vd Heijden:

Ya está en el ejemplo.
Cuando cierras la orden utilizas el valor de retorno booleano de la función OrderClose(), y si la función tuvo éxito, puedes eliminar los objetos relacionados con la orden.

Ya lo sé, ya lo he probado. Tal vez hice algo mal. Lo intentaré una vez más, pero antes quiero preguntar que no me gustaría usar OrderClose(). ( a veces cierro órdenes por el manualmente )
P: Entonces, ¿puedo borrar los objetos de la orden después de cerrarla sin OrderClose()?

Gracias de antemano.

 

Bueno, el valor de retorno de la función Order Close() decide si la acción fue exitosa o no, así que si usted cierra la orden manualmente tendrá que diseñar y usar un mecanismo ligeramente diferente.

Puedes hacer una copia en la sombra de la lista de pedidos y compararla con la lista actual, y siempre que algo cambie porque has cerrado un pedido manualmente, buscar lo que ha cambiado y luego eliminar esos objetos.

Pero una forma más fácil podría ser comprobar si el OrderTicket() todavía existe en el pool de pedidos activo, de modo que cuando desaparezca porque has cerrado el pedido manualmente, los objetos se eliminarán automáticamente.

Así que depende de cómo quieras configurarlo.

En este punto yo diría que tendrías que tratar de ver más allá de lo que quieres hacer con él eventualmente porque la dirección que tomes está de alguna manera relacionada con las tareas adicionales que podrías querer agregar más adelante.


Dado que la creación de los objetos ya está totalmente automatizada, te sugiero que hagas lo mismo para la eliminación de objetos y así no tendrás que preocuparte por ello en el futuro.

Para ello puede utilizar simplemente

OrdersHistoryTotal()

Y el pool de historial

MODE_HISTORY

Es sencillo, se escanea el pool de historial de pedidos, y en cada ciclo el código buscará si existe algún objeto relacionado con el número de OrderTicket(), y si hay una coincidencia, los objetos se eliminan automáticamente.

Para ello sólo hay que añadir otro bucle pero esta vez sobre el pool de históricos.

Ver ejemplo.

//+------------------------------------------------------------------+
//|                                                ObjectsRemove.mq4 |
//|      Copyright 2017, Marco vd Heijden, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Marco vd Heijden, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

static input int takeprofit=500;// Take Profit
static input int stoploss=500;  // Stop Loss
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetTimer(1);

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   for(int order=OrdersTotal(); order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS);
        {
         if(selected==1)
           {
            if(Symbol()==OrderSymbol()) // only for current chart symbol
              {
               switch(OrderType())
                 {
                  case OP_BUY: // for buy order
                    {
                     // if objects not found - create them
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()+takeprofit*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJ_HLINE,0,0,OrderOpenPrice()-stoploss*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-SL",7,3);
                       }
                     // if objects exist
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
                       {
                        if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
                       {
                        if(Ask<ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                    }
                  break;

                  case OP_SELL: // for sell order
                    {
                     // if objects not found - create them
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()-takeprofit*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")<0)
                       {
                        ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJ_HLINE,0,0,OrderOpenPrice()+stoploss*Point());
                        ObjectSet("#"+IntegerToString(OrderTicket())+"-SL",7,3);
                       }
                     // if objects exist
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
                       {
                        if(Ask<ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                     if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
                       {
                        if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))
                          {
                           PlaySound("alert2.wav"); // OrderClose now removed...
                          }
                       }
                    }
                  break;
                 }
              }
           }
        }
     }
//+------------------------------------------------------------------+
//--- delete objects when order is closed
   for(int order=OrdersHistoryTotal()-1; order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS,MODE_HISTORY);
        {
         if(selected==1)
           {
            // if objects are still found - Delete them
            if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
              {
               ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-TP");
              }
            if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-SL")>=0)
              {
               ObjectDelete(0,"#"+IntegerToString(OrderTicket())+"-SL");
              }
           }
        }
     }
//+------------------------------------------------------------------+    
  } // end OnTimer() function
//+------------------------------------------------------------------+

Así que ahora tiene la adición totalmente automatizada de líneas virtuales de take profit y stoploss, y también la eliminación totalmente automatizada de estas líneas.

Por supuesto, este ejemplo está escaneando continuamente el conjunto de la historia...

Adicionalmente se podría añadir un entero que contenga el número de órdenes, que luego se comparará con OrdersTotal(), y cada vez que algo cambie se ejecutará el código de eliminación de objetos.

O bien, podría añadir un simple contador (60) y entonces la pieza de código sólo comprobará una vez por minuto, si algo necesita ser eliminado.

 

¡Oye, hombre! ¡Funciona perfectamente! ¡Muchas gracias!

Sólo he cambiado un poco. Hasta ahora funciona sin problemas.

//--- delete objects when order is closed
   for(int order=OrdersHistoryTotal()-1; order>=0; order--)
     {
      bool selected=OrderSelect(order,SELECT_BY_POS,MODE_HISTORY);
        {
         if(selected==1)
           {
            // if objects are still found - Delete them
            ObjectsDeleteAll( 0, "#" + IntegerToString( OrderTicket() ) ); // for arrows
            ObjectsDeleteAll( 0, _prefix + " #" + IntegerToString( OrderTicket() ) ); // order, sl, tp, price objects
           }
        }
     }

Si algo está mal por favor hágamelo saber.
Una vez más, muchas gracias.

 

Tal vez nadie entiende mi pregunta. Pero todavía necesito un buen comentario para ello. Así que ahora estoy tratando de aclarar mi pregunta con la imagen.
Pregunta: También Stop Loss, Take Profit Líneas frente a los objetos del panel de comercio. Sé que causó desde la última vez crea objeto. Pero si usted me entiende, por favor, hágame saber cómo puedo hacer que el objeto del panel de comercio debe ser el frente de todos los otros objetos sin "Stop Loss y Take Profit" Líneas.

Objetos mezclados

Sé que puedo usar OBJPROP_BACK, pero no quiero usarlo, sólo necesito ver la línea y el precio como ambos. Espero recibir buenos comentarios al respecto.


Abrir, Stop Loss, Take Profit, líneas de precios " Crear y Eliminar " que todos ellos en una función. Así que ahora estoy tratando de dividirlo, porque necesito poner esa función en OnChartEvent(). Pero antes necesito preguntar.
P: ¿Si pongo esa función en OnChartEvent() - por lo que esa función no podría efectos a mi manualmente Órdenes?

Estoy trabajando en ello ahora.

Por favor, ayúdenme, gracias de antemano.

 

No Onchartevent() sólo ejecutará el código cuando haya un evento del gráfico, no es como la función OnTImer().

Así que tienes que saber exactamente lo que estás haciendo.

Por ejemplo, si usted está utilizando el código de exploración :

if(Bid>ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-SL",OBJPROP_PRICE,0))

Para comprobar si el precio ha cruzado su línea esto no funcionará en OnChartEvent().

También si quieres usar el ejemplo automatizado

if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
   {
     ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,OrderOpenPrice()-takeprofit*Point());
     ObjectSet("#"+IntegerToString(OrderTicket())+"-TP",7,3);
   }

Esto no funcionará ni creará los objetos.

Tendrá que volver a escribir el código.

También, puedes poner los objetos H_LINE a OBJPROP_BACK esto no es problema los seguirás viendo y estarán bajo tu panel.

 

Realmente agradable y útil comentario, ahora sé con certeza que debo probar al menos una vez para saber lo que podría hacer adicionalmente.

Gracias por su rápida respuesta y útil comentario.

 
Marco vd Heijden:

Tendrás que volver a escribir el código.

( Ya he leído atentamente tu comentario pero sólo quería probar una vez - finalmente como has dicho no funciona como el OnTimer(). )

¿Debo cambiar todo el código del bloque?
Ahora tengo cuatro funciones. Sólo intento ponerlas en OnChartEvent(). Ya probé solo veo una cosa actualiza esto es solo Print() para los precios de stop loss, take profit.
OrderModify() no funciona en él.

Voy a empezar a probar algo de nuevo para este tema en 8 - 10 horas.
Sólo necesito buenos comentarios, espero que lo consiga.

Muchas gracias de antemano.

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
  {
   if(id==CHARTEVENT_OBJECT_DRAG) // I already tried with take profit object - there was not any effects
     {
      SL_TPcreateobjects();
      SL_TPdrags();
      SL_TPmodify();
      deleteobjs();
     }
  }
// if objects not found - create them
SL_TPcreateobjects()
  {
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;
      if(Symbol()!=OrderSymbol()) continue;

      if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")<0)
        {
         ObjectCreate(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJ_HLINE,0,0,takeprofit);
        }
     }
  }
// if objects exist
SL_TPdrags()
  {
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;
      if(Symbol()!=OrderSymbol()) continue;

      if(ObjectFind(0,"#"+IntegerToString(OrderTicket())+"-TP")>=0)
        {
         if(TP_Price!=ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
           {
            TP_drag=1;
            TP_Price=ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0);
           }
         if(TP_drag==1)
           {
            if(TP_Price==ObjectGetDouble(0,"#"+IntegerToString(OrderTicket())+"-TP",OBJPROP_PRICE,0))
              {
               Print("Take Profit Price:",DoubleToString(TP_Price,Digits));
               TP_drag=0;
              }
           }
        }
     }
  }
// order closed - delete junks
deleteobjs()
{
  for(int i=OrdersHistoryTotal()-1; i>=0; i--)
    {
     bool Selected=OrderSelect(i,SELECT_BY_POS,MODE_HISTORY);
     if(Selected==1)
       {
        ObjectsDeleteAll(0,"#"+IntegerToString(OrderTicket())+"-TP");
       }
    }
}
// ordermodify()
SL_TPmodify()
{
  Order_Modify=OrderModify(OrderTicket(),OrderOpenPrice(),SL_Price,TP_Price,0,CLR_NONE);
}
//+------------------------------------------------------------------+
 

Esas funciones sólo se ejecutarán cuando ocurra un chartevent.

Al menos eso es lo que muestras aquí.

El chartevent es sólo un disparador de una rutina de interrupción cuando alguien presiona un botón o algo más en el gráfico.

Ahora has cogido el ejemplo totalmente automatizado y lo has puesto debajo de un botón, no pasará nada si nadie lo pulsa.

 
Marco vd Heijden:

Esas funciones solo se ejecutan cuando ocurre un chartevent.
Al menos eso es lo que muestra aquí.
Chartevent es sólo un disparador de una rutina de interrupción cuando alguien presiona un botón o algo más en el gráfico.
Ahora has cogido el ejemplo totalmente automatizado y lo has puesto debajo de un botón, no pasará nada si nadie lo pulsa.

Es posible que tu último comentario parezca tan simple, pero en realidad ese comentario me mostró el camino correcto.
Así que ahora resuelvo mi problema que trato de usar el arrastre.

Y ahora estoy empezando a investigar sobre algunos otros objetos gráficos que se mueven con ese objeto HLine.

¡Muchas gracias hombre!
¡Todo lo mejor para ti!


honest_knave:

Además, piense en la frecuencia con la que mueve la línea. ¿Es una vez por segundo? Probablemente no.
Ponga su código en OnChartEvent():

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
  {
   if(id==CHARTEVENT_OBJECT_DRAG && sparam=="line") // the chart event of dragging the line
¡Muchas gracias hombre! ¡Así que su este comentario realmente me ayudó mucho!