![MQL5 - Lenguaje de estrategias comerciales para el terminal de cliente MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
Está perdiendo oportunidades comerciales:
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Registro
Entrada
Usted acepta la política del sitio web y las condiciones de uso
Si no tiene cuenta de usuario, regístrese
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.
{
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");
}
}
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
Y el pool de historial
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.
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.
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 :
Para comprobar si el precio ha cruzado su línea esto no funcionará en OnChartEvent().
También si quieres usar el ejemplo automatizado
{
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.
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.
{
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.
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!
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():
{
if(id==CHARTEVENT_OBJECT_DRAG && sparam=="line") // the chart event of dragging the line