Problemas raros al mandar ejecutar posiciones.

 

Buenas gente, estoy programando un EA que operara en Forex para que, despues de que se cumplan varias condiciones en unos datos que agregue al grafico, se ejecute una orden de compra o una de venta segun lo requerido. 

Al parecer ya pude programar todas las condiciones ya que se ejecutan satisfactoriamente pero al momento de la ejecucion de la operacion A VECES aparecen errores. 

Cuando utilizaba cTrade para ejecutar ordenes, algunas veces me aparecia el error "not enough money" al realizar alguna operacion y otras veces se ejecutaba de manera normal, en el log tenia los valores de compra/venta, Stop Loss, take Profit y Lotaje para verificar si la operacion daba numeros invalidos o extraños pero eran corretos y con calculadora en mano revisaba si el lotaje era correcto, al punto en que yo podia meter una orden manual con los mismos parametros exactos y dicha orden se ejecutaba en mercado sin problemas. 

Ahora que cambie a OrderSend, parecia que todo iba de manera correcta hasta que hoy al estar probando y que se cumplieran los valores de una Compra, mi EA me salio el error 4756. Añado que tiempo antes ya habia realizado operaciones tanto de Compra como de Venta sin ningun problema. Lo que me extraña es que sea A VECES. 

Dejo la funcion que ejecuta compras para ver si alguien puede encontrar algun error, como mencione, las condiciones y toda la logica que busco en la operacion se ejecuta de manera correcta (fui revisando cada uno de los puntos con mensajes en el log para ver si las condiciones se iban cumpliendo, a la vez que tengo activados comentarios en el grafico para ir viendo como se mueven los valores booleanos). La funcion que ejecuta ventas es exactamente igual, solo que con los signos cambiados.


void Compras()
{


// Los comentarios aqui escritos no estan en mi codigo, simplemente los agregue aqui para explicar un poco las cosas.


MqlTradeRequest request;   
MqlTradeResult result;     


ZeroMemory(request);
ZeroMemory(result);


    double cierreVelaActual = iClose(_Symbol, PERIOD_CURRENT, 1);
    double BajovelaActual = iLow(_Symbol, PERIOD_CURRENT, 1);
    string Cambio = " ";
    
    
   // Aqui comienzan las condiciones para operar en base a otros valores expresados en otra funcion, estas condiciones parecen estar correctas pero las dejo por si alguien encuentra algun problema
if (!HayOrdenAbierta())
  {
    if (!RompioNivel && ((cierreVelaActual <= Nivel105 && cierreVelaActual >= Nivel150) || (BajovelaActual <= Nivel105 && BajovelaActual >= Nivel150)))
    {
     
        RompioNivel = true;  
        Print("¡Condición cumplida!");
        SendNotification("Se cumplio condicion");    
    }   
    
    if(RompioNivel && (cierreVelaActual < Nivel150 || BajovelaActual < Nivel150) )
    {
    Nivel0 = 0;
    Nivel100 = 0;
    RompioNivel = false;
    printf("Parametros fuera de condicion, reiniciando");
    SendNotification("Parametros fuera del rango, reiniciando");
    }
    
    
    if (RompioNivel)
    {
    
    double cierreVelaAnterior = iClose(_Symbol, PERIOD_CURRENT, 2);  
    double aperturaVelaAnterior = iOpen(_Symbol, PERIOD_CURRENT, 2); 
    double highVelaActual = iHigh(_Symbol, PERIOD_CURRENT, 1);         
    double lowVelaActual = iLow(_Symbol, PERIOD_CURRENT, 1);          
    double aperturaVelaActual = iOpen(_Symbol, PERIOD_CURRENT, 1);     
    printf("Valores guardados, esperando gatillo");
    
        
    
    
    if ((cierreVelaAnterior < aperturaVelaAnterior || cierreVelaAnterior == aperturaVelaAnterior) && cierreVelaActual > aperturaVelaActual)
    {
         
         if(cierreVelaActual > Nivel50 || highVelaActual > Nivel33 || lowVelaActual < Nivel150)
        {
        printf("Gatillo no cmplido, reiniciando");
        Nivel0 = 0;
        Nivel100 = 0;
        RompioNivel = false;
        }    

        if (cierreVelaActual < Nivel50 && lowVelaActual < Nivel33 && highVelaActual > Nivel150)
        {
           trade.SetExpertMagicNumber(magicNumber);
           precioBid = iClose(_Symbol, PERIOD_CURRENT, 1);  // No se dejen llevar por el nombre de la variable, simplemente por comodidad decidi dejarla con ese nombre. La de Ventas tiene otro nombre. 
           TPNivel = TPCompra; // Esta variable tiene un valor basado en otra funcion, para este punto ya tiene un valor definido.
           SLCompra = precioBid - ((TPNivel - precioBid) * 2);
           
           if(SLCompra > Nivel200)
           {
           SLCompra = Nivel200;
           Cambio = "\nSe forzo Stop Loss a nivel preestablecido";
           DistanciaVela = MathAbs(precioBid - SLCompra);
           TPNivel = precioBid + (DistanciaVela * 0.5);
           } 
           
           NivelCierre = precioBid - (TPNivel - precioBid) ;
           
           
    // Ambas Variables, "balance" y "riesgoPorcentaje" estan declaradas en otra funcion y tienen sus valores de manera correcta. 
    double riesgoMaximo = balance * (riesgoPorcentaje / 100.0);
    double stopLossDistancia = MathAbs(precioBid - SLCompra);
    double valorPunto = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
    double tamanoPunto = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
    double perdidaPorLote = stopLossDistancia / tamanoPunto * valorPunto;
    double lotaje = riesgoMaximo / perdidaPorLote;
    double loteMinimo = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
    double loteMaximo = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
    double pasoLote = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
    
    lotaje = NormalizeDouble(lotaje / pasoLote, 0) * pasoLote;
    lotaje = MathMax(loteMinimo, MathMin(lotaje, loteMaximo));
    
    printf("Giro encontrado, ejecutando orden, se arriesgaran: " + DoubleToString(riesgoMaximo) + " Dolares en la operacion" + Cambio);
    printf("Se abre operacion con " + DoubleToString(lotaje) + " lotes con TP en " + DoubleToString(TPNivel) + " y SL en " + DoubleToString(SLCompra));
    SendNotification("Ejecutando Orden \nNivel de cierre sera: " + DoubleToString(NivelCierre) + Cambio);

           Parcialidad = MathMin(iLow(_Symbol, PERIOD_CURRENT, 1), iLow(_Symbol, PERIOD_CURRENT, 2));  //Esta variable se utiliza para otra funcion.
           //int ticket = trade.Buy(lotaje, _Symbol, SYMBOL_ASK, SLCompra, TPNivel, 10);  //Esta es la linea de codigo cTrade que usaba antes, la deje por si alguien puede encontrar mi error.
           
           ////////////////////////////////////////////////////////
          
          // Esta es con Order Send, es la que utilice para reemplazar la de cTrade que deje mas arriba
request.action   = TRADE_ACTION_DEAL;   
request.symbol   = _Symbol;            
request.volume   = lotaje;              
request.type     = ORDER_TYPE_BUY;    
request.price    = SymbolInfoDouble(_Symbol, SYMBOL_ASK); 
request.sl       = SLCompra;           
request.tp       = TPNivel;             
request.deviation= 10if (!OrderSend(request, result))
{
    Print("Error al enviar la orden de compra: ", GetLastError());
}
else
{
    Print("Orden de compra enviada con éxito. Ticket: ", result.order);
}

int ticket = result.order;
          
          ///////////////////////////////////////////////////////
           
           
            Nivel0 = 0;
            Nivel100 = 0;

           RompioNivel = false;
        }
    }
    }
    }
    
}
bool HayOrdenAbierta()
{
   if (PositionSelect(_Symbol))
   {
       return true;
   }
   return false;
}

Como mencione esa es la funcion que ejecuta Compras, la de Ventas es basicamente igual solo cambiando algunos signos. hasta el momento del cambio a "OrderSend" solo Compras me dio una unica vez un error, que fue el error 4756, las ventas aun no han presentado ningun error.

Debido a que mi codigo espera al cierre de vela para operar, pude notar que hubo un pequeño Gap al momento en que se supone que debia meter mi operacion, mi teoria es que esto fue el causante del error y causante de los errores anteriores que tenia al usar cTrade y si es asi ¿existe alguna forma de darle cierta holgura en gaps asi de pequeños o simplemente es una coincidencia y el problema esta en otro lado?.

Adjunto un par de Screenshots del mensaje de error, señalando donde debio de abrir la operacion y el pequeño gap que tuvo. 

Qué comprobaciones debe superar un robot comercial antes de ser publicado en el Mercado
Qué comprobaciones debe superar un robot comercial antes de ser publicado en el Mercado
  • www.mql5.com
Antes de su publicación, todos los productos del Mercado pasan por una comprobación preliminar de carácter obligatorio, con objeto de proporcionar un estándar único de calidad. En este artículo hablaremos de los errores más frecuentes que cometen los desarrolladores en sus indicadores técnicos y robots comerciales. Asimismo, mostraremos cómo puede usted comprobar por sí mismo su producto antes de enviarlo al Mercado.
Archivos adjuntos:
ERROR.png  99 kb
gap.png  7 kb
 
lahu92:

Buenas gente, estoy programando un EA que operara en Forex para que, despues de que se cumplan varias condiciones en unos datos que agregue al grafico, se ejecute una orden de compra o una de venta segun lo requerido. 

Al parecer ya pude programar todas las condiciones ya que se ejecutan satisfactoriamente pero al momento de la ejecucion de la operacion A VECES aparecen errores. 

Cuando utilizaba cTrade para ejecutar ordenes, algunas veces me aparecia el error "not enough money" al realizar alguna operacion y otras veces se ejecutaba de manera normal, en el log tenia los valores de compra/venta, Stop Loss, take Profit y Lotaje para verificar si la operacion daba numeros invalidos o extraños pero eran corretos y con calculadora en mano revisaba si el lotaje era correcto, al punto en que yo podia meter una orden manual con los mismos parametros exactos y dicha orden se ejecutaba en mercado sin problemas. 

Ahora que cambie a OrderSend, parecia que todo iba de manera correcta hasta que hoy al estar probando y que se cumplieran los valores de una Compra, mi EA me salio el error 4756. Añado que tiempo antes ya habia realizado operaciones tanto de Compra como de Venta sin ningun problema. Lo que me extraña es que sea A VECES. 

Dejo la funcion que ejecuta compras para ver si alguien puede encontrar algun error, como mencione, las condiciones y toda la logica que busco en la operacion se ejecuta de manera correcta (fui revisando cada uno de los puntos con mensajes en el log para ver si las condiciones se iban cumpliendo, a la vez que tengo activados comentarios en el grafico para ir viendo como se mueven los valores booleanos). La funcion que ejecuta ventas es exactamente igual, solo que con los signos cambiados.


Como mencione esa es la funcion que ejecuta Compras, la de Ventas es basicamente igual solo cambiando algunos signos. hasta el momento del cambio a "OrderSend" solo Compras me dio una unica vez un error, que fue el error 4756, las ventas aun no han presentado ningun error.

Debido a que mi codigo espera al cierre de vela para operar, pude notar que hubo un pequeño Gap al momento en que se supone que debia meter mi operacion, mi teoria es que esto fue el causante del error y causante de los errores anteriores que tenia al usar cTrade y si es asi ¿existe alguna forma de darle cierta holgura en gaps asi de pequeños o simplemente es una coincidencia y el problema esta en otro lado?.

Adjunto un par de Screenshots del mensaje de error, señalando donde debio de abrir la operacion y el pequeño gap que tuvo. 

Mi consejo es que utilices CTrade, porque es más sencillo y los errores se ven mejor. Un ejemplo:

#include <Trade\Trade.mqh> CTrade trade;

// Órdenes de compra y venta:

if(BuySignal&&LongPos<1){ // Trade LONG.
        double Ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
        if(!trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,MathMin(Lotsize,maxLot),Ask,SL,TP,CustomComment)){
                Print("PositionOpen error ",trade.ResultRetcode());
                return; // Salir de la función si hay error.
                }
if(SellSignal&&ShortPos<1){ // Trade SHORT.
        double Bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);
        if(!trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,MathMin(Lotsize,maxLot),Bid,0,TP,CustomComment)){
                Print("PositionOpen error ",trade.ResultRetcode());
                return; // Salir de la función si hay error.
                }

Si el lote, el SL y el TP son correctos esto debe funcionar, espero que sirva.