PDA

Ver la versión completa : Ayuda Tiempo de expiacion orden stop



didaz
07-07-2022 07:39,
Esto me está volviendo loco. Lo explicaré despacio.

Tengo

_ticket_orden=OrderSend(Symbol(),OP_BUYSTOP,_lotes ,High[1]+10*point,_slip_page _pips,_stop_loss_precio,_take_profit_precio,"BUY",_ea_magic_number,0,Green);

y

_ticket_orden=OrderSend(Symbol(),OP_SELLSTOP,_lote s,Low[1]-10*point,_slip_page_pips,_stop_loss_precio,_take_p rofit_precio,"Sell",_ea_magic_number,0,Red);

Hasta aquí todo perfecto.

pero ahora para anular la orden stop al cabo de n velas hago lo siguiente:

//Calculo de la fecha de expiracion de la orden pendiente.
datetime _expiacion = TimeCurrent()+(Period()*60)*_velas_para_expirar;

// Enviar orden
_ticket_orden=OrderSend(Symbol(),OP_BUYSTOP,_lotes ,High[1]+10*point,_slip_page_pips,_stop_loss_precio,_take_ profit_precio,"BUY",_ea_magic_number,_expiacion,Green);

Y tambien todo perfecto. _expiacion es un numero que representa la fecha de expiacion y que se coloca en el sitio correspondiente de funcion OrderSend


Y ahora viene el misterio.

Hago exactamente lo mismo pero con la orden de sellstop, es decir:

//Calculo de la fecha de expiracion de la orden pendiente.
datetime _expiacion = TimeCurrent()+(Period()*60)*_velas_para_expirar;

// Enviar orden
_ticket_orden=OrderSend(Symbol(),OP_SELLSTOP,_lote s,Low[1]-10*point,_slip_page_pips,_stop_loss_precio,_take_p rofit_precio,"Sell",_ea_magic_number,_expiacion,Red);


... y sorpresa, :wow2::wow2: ¡todo se me excogorcia!, y ademas, paso de tener unas 250 operaciones a tener unas 1.200. ¿¿¿???

¡¡ Socorro!! ¿Alguien sabe por que puede ser esto?

Saludos.

Una cosa a tener en cuenta es que el tiempo minimo de expiracion para la ordenes pendientes es de 11 minutos.
No se si esto tiene que ver con tu problema.

Ciclo
28-02-2023 01:41,
Al final no ha sido tan fácil por que si la orden pendiente pasaba a mercado, por ejemplo despues de la 2 vela, el programa trataba de borrar una orden inexistente y daba error.

Lo que he hecho ha sido averiguar primero si hay orden pendiente abierta con el ticket correspondiente, luego verificar si hay expiración y luego proceder al borrado de la orden.

Muchas gracias a todos los que me habeis ayudado.

Un saludo.

Ciclo
28-02-2023 08:25,
Ya he visto donde estaba el fallo, la variable ticket era una variable local y no conservaba el valor en los siguientes ticks, solo ha hecho falta convertila en variable global y vuala. :contento2: ( o como se diga vuala)


50144

Ciclo
28-02-2023 08:55,
Muchas gracias Snake y Roberto por los buenos consejos.
Creo que ya lo tengo, pero me falla en algo tan tonto como la utilizacion del dato de return. Me da error y no se por que. Seguro que para vosotros es facil.


En el codigo siguiente, se llama a la funcion abrir_orden_sell() (funcion que tambien pongo mas abajo). Luego, supongo que regreso de la funcion con el valor del ticket en la variable orden_ticket (o al menos eso creo) pero me da error de ese parametro cuando ejecuta (en su momento) la orden Delete.

La funcion abrir_orden_sell() opera con dos variables globales ( a nivel de programa): fecha_expiracion_segundos y numero_velas_para_expirar. La primera se usa fuera de la funcion para comparar ese tiempo con el tiempo actual para ejecutar la funcion Delete de la orden pendiente.


// Verificar si es señal de ejecutar venta
// ---------------------------------------


if(senal_abrir_sell==1)
{
int orden_ticket= abrir_orden_sell(take_profit_pips,stop_loss_pips,s lip_page_pips,ea_magic_number,lotes);
// eliminar señal de venta
senal_abrir_sell=0;
}


-----------------------------------------------
// Borrar la orden pendiente al cabo de n velas
// --------------------------------------------
//Calculo de la fecha de expiracion de la orden pendiente.
if (fecha_expiracion_segundos!=0)
Print("Tiempo de expiracion= ",fecha_expiracion_segundos," - Tiempo Actual = ", TimeCurrent(),", Tiempo Restante= ", fecha_expiracion_segundos-TimeCurrent());
if ( TimeCurrent()>= fecha_expiracion_segundos)
{
OrderDelete (orden_ticket,Goldenrod);
fecha_expiracion_segundos=0;
}





Esta es la definicion de la funcion abrir_orden_sell ().
Todo va perfecto hasta que tiene que borrar la orden pendiente.


int abrir_orden_sell(int _take_profit_pips,int _stop_loss_pips,int _slip_page_pips,int _ea_magic_number,double _lotes)
{
//Print("TP= ",_take_profit_pips,", SL= ",_stop_loss_pips,", slippage= ",_slip_page_pips,", magic number= ",_ea_magic_number,", lotes= ",_lotes,", nº velas expiracion= ",_velas_para_expirar );
int _ticket_orden;


double bid =MarketInfo(Symbol(),MODE_BID); // Requerimiento del valor Bid
double ask =MarketInfo(Symbol(),MODE_ASK); // Requerimiento del valor Ask
double point =MarketInfo(Symbol(),MODE_POINT);//Requerimiento del valor Point


double pricesell= Low[1]-10*point; //Bid

// Calculo del precio StopLoss
double _stop_loss_precio=NormalizeDouble(pricesell+_stop_ loss_pips*point,Digits);

// Calculo del precio TakeProfit en base a los pips provistos
int _take_profit_precio=NormalizeDouble(pricesell -_take_profit_pips*point,Digits);


// Enviar orden
_ticket_orden=OrderSend(Symbol(),OP_SELLSTOP,_lote s,pricesell,_slip_page_pips,_stop_loss_precio,_tak e_profit_precio,"Sell",_ea_magic_number,0,Red);

if(_ticket_orden==-1)
{
// error al abrir orden
Print("- ERROR!!!!: Error al abrir orden SELLSTOP");
return -1;
}
else
{
// Orden abierta correctamente
Print("- Orden SELLSTOP aceptada");

// Calculo de fecha de expiracion en segundos
fecha_expiracion_segundos = TimeCurrent()+(Period()*60)*numero_velas_para_expi rar;


//Print( "Expiracion orden SELLSTOP = " + TimeToString(fecha_expiracion_segundos, TIME_DATE|TIME_MINUTES));

// retornar el ticket de la orden
return _ticket_orden;
}
}
//--------------------------------------------------------------------


No se si se entiende, el caso es que me da error de la variable return a la hora de ejecutar la orden delete.

50142

Un abrazo

robertomar
28-02-2023 13:45,
Compi, para que salgas de dudas de qué fecha te está calculando como expiración de las órdenes, por si tuvieras algún error en su cálculo, lo mejor es que el Print lo pogas así:



Print( "Expiracion orden BUYSTOP = " + TimeToString(_expiracion_buy, TIME_DATE|TIME_MINUTES));


Por otra parte, algunos brokers NO permiten enviar las órdenes con expiración, y los que lo permiten, yo de todos los que he probado, NINGUNO me ha permitido enviarla con una expiración menor a 10 minutos.

Por tanto, lo más seguro es enviarlas con expiración = 0, y luego calcular la expiración aparte, y que el EA vaya chequeando y cuando se pase el tiempo estipulado, que mande orden de borrar la orden (OrderDelete).

Espero que te oriente.

Saludos y un abrazo.

Hola compi. Te paso captura de donde tienes que darle para envolver el código con la etiqueta correspondiente, para que salga así:

Tú pones el código que sea, por ejemplo este:



int OnInit()
{
//--- indicator buffers mapping
Comment("");
//---
return(INIT_SUCCEEDED);
}

Y entonces tienes que darle al botón que te pongo en la captura:

50137

Y entonces te quedará así:

50138


Respecto a lo otro que me preguntas, depende de si el EA solo lleva una operación abierta al mismo tiempo, porque si lleva varias abiertas la cosa se complicaría un poco.

También puedes probar, como tú no tienes que hacer un EA que valga para TODO el mundo como hago yo, puesto que no se donde lo va a poner cada cual, sino que en tu caso es para ti, y ya sabes en qué broker lo vas a poner, pues puedes probar si ahí donde lo pongas te permiten enviarlas con expiración y cual es el intervalo más corto de expiración que te permiten, y ya si eso cubre tus necesidades, puedes ponerlo como lo estabas haciendo (usando el parámetro de expiration de OrderSend).

Saludos y un abrazo.

Snake300kbps
28-02-2023 18:02,
Gracias Roberto. Me viene muy bien saber como podia escribir eso.

Por otro lado, como se hace para poner en el foro el codigo como tu lo has puesto?

Y por ultimo (para no abusar demasiado). ¿Hay alguna forma sencilla de contar el tiempo transcurrido?

Un saludo y gracias.

Es complicado ayudar sin poder ver el código completo o saber la idea que tienes, pero prueba una cosa, primera pones la order con expiration = 0 (para que no haya espiración).
Luego, comprueba con Print si el resultado es lo que esperas, hazlo paso a paso comprobando cada paso con un print, por ejemplo.



//Partimos de la base que Expiration es en Segundos
//Tambien hay que tener en cuenta que Period() es tu TimeFrame actual en Minutos

int Velas_en_entero=3; //ejemplo de cuantas velas quiero que expire

//(Multiplicamos tu timeframe por el numero de velas) para luego pasarlo a Segundos (*60)
datetime Velas_en_datetime = (Period()*Velas_en_entero) * 60
Print("VELA EN ENTERO = ",Velas_en_entero," VELA EN SEGUNDOS = ",Velas_en_datetime); //confirmamos que va bien
//Sumamos La cantidad de velas que quieres para expirar al tiempo actual para que sea hacia delante.
datetime expiration = Velas_en_datetime + TimeCurrent();

//Creamos una variable de comprobación en intero para confirmar calculos, este deberia ser el resultado de cuantas velas quedan para la expiración
int z= expiration/60/Period();
Print("CANTIDAD DE VELAS PARA LA ESPIRACIÓN = ",z); //lo confirmamos


y por ultimo, si es lo que quieres, modifica la orden con OrderModify y en expiration pones expiration que es el tiempo en segundos.

Es mas o menos lo que has hecho, pero te doy la idea de que lo hagas de una forma mas organizada simplesmente para encontrar el fallo, luego ya lo juntas todo en 1 linea y a correr :).

Espero que te ayude.

Ciclo
28-02-2023 20:03,
Compi, para que salgas de dudas de qué fecha te está calculando como expiración de las órdenes, por si tuvieras algún error en su cálculo, lo mejor es que el Print lo pogas así:



Print( "Expiracion orden BUYSTOP = " + TimeToString(_expiracion_buy, TIME_DATE|TIME_MINUTES));


Por otra parte, algunos brokers NO permiten enviar las órdenes con expiración, y los que lo permiten, yo de todos los que he probado, NINGUNO me ha permitido enviarla con una expiración menor a 10 minutos.

Por tanto, lo más seguro es enviarlas con expiración = 0, y luego calcular la expiración aparte, y que el EA vaya chequeando y cuando se pase el tiempo estipulado, que mande orden de borrar la orden (OrderDelete).

Espero que te oriente.

Saludos y un abrazo.

Gracias Roberto. Me viene muy bien saber como podia escribir eso.

Por otro lado, como se hace para poner en el foro el codigo como tu lo has puesto?

Y por ultimo (para no abusar demasiado). ¿Hay alguna forma sencilla de contar el tiempo transcurrido?

Un saludo y gracias.

robertomar
28-02-2023 20:35,
Compi, para que salgas de dudas de qué fecha te está calculando como expiración de las órdenes, por si tuvieras algún error en su cálculo, lo mejor es que el Print lo pogas así:



Print( "Expiracion orden BUYSTOP = " + TimeToString(_expiracion_buy, TIME_DATE|TIME_MINUTES));


Por otra parte, algunos brokers NO permiten enviar las órdenes con expiración, y los que lo permiten, yo de todos los que he probado, NINGUNO me ha permitido enviarla con una expiración menor a 10 minutos.

Por tanto, lo más seguro es enviarlas con expiración = 0, y luego calcular la expiración aparte, y que el EA vaya chequeando y cuando se pase el tiempo estipulado, que mande orden de borrar la orden (OrderDelete).

Espero que te oriente.

Saludos y un abrazo.

Ciclo
01-03-2023 00:36,
Como digo, lo curioso es con la orden buystop funciona y y la sellstop no, ¡y son identicas!

En la captura de abajo se puede ver como la orden buystop es cancelada despues de tres velas. ¿¿??

50094

Ciclo
01-03-2023 00:42,
Hola Snake.

Eso que dices, si, me di cuenta de que estaba mal por que el stop loss y el take profit estaban referenciados a Bid (o Ask) cuando tenian que estar puestos respecto a high o low. Lo dejé así

//--------------------------------------------------------------------
// Abrir Orden BuyStop (encima del maximo de la vela 1)
//--------------------------------------------------------------------
int abrir_orden_buy(int _take_profit_pips,int _stop_loss_pips,int _slip_page_pips,int _ea_magic_number,double _lotes,int _velas_para_expirar)

{
//Print("TP= ",_take_profit_pips,", SL= ",_stop_loss_pips,", slippage= ",_slip_page_pips,", magic number= ",_ea_magic_number,", lotes= ",_lotes,", nº velas expiracion= ",_velas_para_expirar );
int _ticket_orden;


double bid =MarketInfo(Symbol(),MODE_BID); // Requerimiento del valor Bid
double ask =MarketInfo(Symbol(),MODE_ASK); // Requerimiento del valor Ask
double point =MarketInfo(Symbol(),MODE_POINT);//Requerimiento del valor Point

double pricebuy=High[1]+10*point; // Ask


// Calculo del precio StopLoss
double _stop_loss_precio= NormalizeDouble(pricebuy -_stop_loss_pips*point,Digits);


// Calculo del precio TakeProfit en base a los pips provistos
double _take_profit_precio=NormalizeDouble(pricebuy +_take_profit_pips*point,Digits);


//Calculo de la fecha de expiracion de la orden pendiente.
datetime _expiracion_buy = TimeCurrent()+(Period()*60)*_velas_para_expirar;
Print( "Expiracion orden BUYSTOP= ",_expiracion_buy);
// Enviar orden
_ticket_orden=OrderSend(Symbol(),OP_BUYSTOP,_lotes ,pricebuy,_slip_page_pips,_stop_loss_precio,_take_ profit_precio,"BUY",_ea_magic_number,_expiracion_buy,Green);
if(_ticket_orden==-1)
{
// error al abrir orden
Print("- ERROR!!!!: Error al abrir orden BUYSTOP");
return -1;
}
else
{
// Orden abierta correctamente
Print("- Orden BUYSTOP aceptada");
// retornar el ticket de la orden
return _ticket_orden;
}
}
//--------------------------------------------------------------------



Pero sigo con el mismo problema. Habia pensado si que en
datetime _expiracion_buy = TimeCurrent()+(Period()*60)*_velas_para_expirar
la fecha de expiración me sale en formato int y no se si tendría que ponerse en formato datetime

50093

Pero lo curioso es que si la orden sellstop pongo la expiracion a cero y la orden buystop le coloco la variable _expiracion_buy con el formato int, no pasa nada, pero si coloco esa misma variable en la orden sellstop, se me escogorcia el invento y me aparecen cantidad de ordenes. Una cosa rara.

Lo que no se es si se puede pasa a formato datetime (fecha y hora) estos digitos en formato int.

Saludos y gracias.

P.D. el titulo del hilo está mal puesto, no es Tiempo de expiacion orden stop, sino Tiempo de expiracion de orden stop.

Snake300kbps
01-03-2023 03:01,
Mañana desde el ordenador te lo miro a ver que esta pasando. Pero de ante mano por si quiere probar, recomiendo no hacer muchos cálculos donde debería ir 1 variable, a mi me ha dado problema algunas veces. Así que te recomiendo probar declarar una variable para almacenar el cálculo del precio en vez de calcularlo en el ordersend. double buyStopPrice=(High [1]+(10*pip)); por ejemplo.

Enviado desde mi SM-G925F mediante Tapatalk

Ciclo
01-03-2023 05:49,
Esto me está volviendo loco. Lo explicaré despacio.

Tengo

_ticket_orden=OrderSend(Symbol(),OP_BUYSTOP,_lotes ,High[1]+10*point,_slip_page _pips,_stop_loss_precio,_take_profit_precio,"BUY",_ea_magic_number,0,Green);

y

_ticket_orden=OrderSend(Symbol(),OP_SELLSTOP,_lote s,Low[1]-10*point,_slip_page_pips,_stop_loss_precio,_take_p rofit_precio,"Sell",_ea_magic_number,0,Red);

Hasta aquí todo perfecto.

pero ahora para anular la orden stop al cabo de n velas hago lo siguiente:

//Calculo de la fecha de expiracion de la orden pendiente.
datetime _expiacion = TimeCurrent()+(Period()*60)*_velas_para_expirar;

// Enviar orden
_ticket_orden=OrderSend(Symbol(),OP_BUYSTOP,_lotes ,High[1]+10*point,_slip_page_pips,_stop_loss_precio,_take_ profit_precio,"BUY",_ea_magic_number,_expiacion,Green);

Y tambien todo perfecto. _expiacion es un numero que representa la fecha de expiacion y que se coloca en el sitio correspondiente de funcion OrderSend


Y ahora viene el misterio.

Hago exactamente lo mismo pero con la orden de sellstop, es decir:

//Calculo de la fecha de expiracion de la orden pendiente.
datetime _expiacion = TimeCurrent()+(Period()*60)*_velas_para_expirar;

// Enviar orden
_ticket_orden=OrderSend(Symbol(),OP_SELLSTOP,_lote s,Low[1]-10*point,_slip_page_pips,_stop_loss_precio,_take_p rofit_precio,"Sell",_ea_magic_number,_expiacion,Red);


... y sorpresa, :wow2::wow2: ¡todo se me excogorcia!, y ademas, paso de tener unas 250 operaciones a tener unas 1.200. ¿¿¿???

¡¡ Socorro!! ¿Alguien sabe por que puede ser esto?

Saludos.