Página 1 de 1

Duda Programación Robot

Publicado: 28 Ago 2021 19:58
por landorra
No estoy seguro del subforo en el que debería abrir este hilo de consulta, de modo que pido disculpas por adelantado si no es este. Ruego ayuda de algún programado presente aquí que fuera tan amable de crear un fragmento que necsito añadir a un proyecto que tengo en marcha. Se trata de lo siguiente.

Dispongo de los siguientes parámetros de entrada para el usuario: a) distancia de SL y TP para todas las operaciones en pips, y b) cantidad de dinero (sea cual sea la divisa que sea la cuenta) que quiero conseguir si se alcanza dicho TP. Por ejemplo, se selecciona una distancia de 20 pips de SL, 40 pips de TP y se quiere conseguir 50 euros de beneficio con ello.

Pues bien, qué fórmula debería usar para que:
1. El bot calcule los lotes necesarios para conseguir esa cantidad de dinero especificada para dicha distancia de TP.
2. El cálculo anterior sea automático para toda divisa y todo par/cruce.

Esto escapa a mis capacidades y cualquier ayuda será con creces agradecida. ;)

Re: Duda Programación Robot

Publicado: 28 Ago 2021 21:02
por X-Trader
Entiendo que es para Metatrader 4, lo muevo aquí.

Saludos,
X-Trader

Re: Duda Programación Robot

Publicado: 28 Ago 2021 21:23
por Foréxitos
Hola landorra, tu idea es poner una operación por cierre? Saludos

Re: Duda Programación Robot

Publicado: 28 Ago 2021 21:39
por Foréxitos
Si es así, es 50, que son los euros que querés ganar, dividido 40 de TP... si lo querés más ajustado súmale al TP el Spread que perdió, la comisión y el Swap aprox pasados a pips, y el resultado te da el lotaje que debería usar para ganar 50 euros por operación.

Re: Duda Programación Robot

Publicado: 28 Ago 2021 21:56
por Foréxitos
El siguiente paso es más fácil todavía, haces una variable externa para poner la divisa de la próxima operación.

Re: Duda Programación Robot

Publicado: 29 Ago 2021 13:45
por landorra
Foréxitos escribió: 28 Ago 2021 21:23 Hola landorra, tu idea es poner una operación por cierre? Saludos
Gracias por tu respuesta. No, lo que necesito es que me calcule los valores de lotes en función de la distancia variable de TP. Ya sé que en EURUSD puedo dividir dinero entre pips para conseguir lotes, pero no sé cómo trasladar eso a índices o cruces, por ejemplo. Además, la distancia de TP puede ser diferente de una operación a la siguiente.

Re: Duda Programación Robot

Publicado: 29 Ago 2021 14:39
por Foréxitos
landorra escribió: 29 Ago 2021 13:45 Gracias por tu respuesta. No, lo que necesito es que me calcule los valores de lotes en función de la distancia variable de TP. Ya sé que en EURUSD puedo dividir dinero entre pips para conseguir lotes, pero no sé cómo trasladar eso a índices o cruces, por ejemplo. Además, la distancia de TP puede ser diferente de una operación a la siguiente.
Hola landorra, bueno en ese caso lo único que cambia son los dígitos... en el EURUSD tenés 5 y en el SP500 2. Sí querés hacemos un zoom el lunes a las 9hs (-3GMT) y lo resolvemos.
Sino, tenés que usar en tus cálculos NormaliceDouble(variable,_Digits); Saludos.

Re: Duda Programación Robot

Publicado: 31 Ago 2021 02:24
por Foréxitos
Corrección: NormalizeDouble()

Re: Duda Programación Robot

Publicado: 09 Sep 2021 10:58
por landorra
Lamento el retraso en la respuesta. Gracias por tu información. De todas formas, me temo que no funciona como explicas. Te pongo un ejemplo. Quiero probar la fórmula en el índice del NASDAQ. En mi broker ese instrumento tiene dos decimales. Quiero que la fórmula me calcules los lotes para conseguir 500 € con un recorrido de 40 pips (no 40 puntos). Si divido 500 € entre 40 pips, el resultado es de ¡¡12.5 lotes estándar!! :O.

Como puedes ver, no es correcto. Está claro que para el instrumento del EURUSD pueda ser correcto, pero no para el resto de instrumentos.

Re: Duda Programación Robot

Publicado: 09 Sep 2021 18:54
por Síntesis


ValorDelTick = MarketInfo (Symbol(), Mode_TickValue);

Teniendo el valor del tick y el valor en euros a arriesgar y la distancia, puedes deducir el numero de lotes.

Lotes = NormalizeDouble(Valor a arriesgar en euros/Distancia Stop/ ValorDelTick,numDecimales);

A ver si te sirve

Saludos


Re: Duda Programación Robot

Publicado: 12 Sep 2021 19:31
por landorra
Síntesis escribió: 09 Sep 2021 18:54

ValorDelTick = MarketInfo (Symbol(), Mode_TickValue);

Teniendo el valor del tick y el valor en euros a arriesgar y la distancia, puedes deducir el numero de lotes.

Lotes = NormalizeDouble(Valor a arriesgar en euros/Distancia Stop/ ValorDelTick,numDecimales);

A ver si te sirve

Saludos

Gracias por la sugerencia, pero no funciona. Me salen unos lotes disparados. He probado esta otra opción que he encontrado en otro foro:

double LotSize = SymbolInfoDouble(NULL,SYMBOL_TRADE_CONTRACT_SIZE);
double TickValue = SymbolInfoDouble(NULL,SYMBOL_TRADE_TICK_VALUE);
double TickSize = SymbolInfoDouble(NULL,SYMBOL_TRADE_TICK_SIZE);
double PointSize = SymbolInfoDouble(NULL,SYMBOL_POINT);
double lot_size = 0
double StopsInMoney = 50
double TakeProfit = 100

lot_size = StopsInMoney/(TakeProfit*LotSize*(TickValue/TickSize)*PointSize);

Pero tampoco funciona. en este caso los lots no pasan del mínimo. Como se puede ver en el ejemplo, quiero conseguir 50 euros si el precio alcanza un TP de 100 pips.

¿Alguna otra sugerencia? :?

Re: Duda Programación Robot

Publicado: 12 Sep 2021 23:43
por Síntesis
Te puedo pasar mi script pero te calcula sobre un porcentaje del balance. Lo puedes modificar si quieres para que te calcule sobre una cantidad.

Tiene otras opciones como el calculo automatico de la distancia del stop según el atr. También tengo los script para buy y sell con los parametros calculados aquí. Si te interesa me lo dices.

Código: Seleccionar todo



//+------------------------------------------------------------------+
//|                                                ParametrosSet.mq4 |
//|                                         Copyright 2020, Sintesis |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, Sintesis"
#property version   "4.00"
//--- strict compilation mode 
#property strict 
//--- show input parameters 
#property show_inputs 


//--- input parameters

extern double  PorcRiesgo           = 2;      // Porcentaje Riesgo. "Si es cero, nº de lotes mínimo." 
extern double  Lotes                = 0;      // Nº Lotes. "Si Lotes== 0.0, entonces cálculo de lotes automatico."

extern bool    distSL_Auto          = true;   // distSL_Auto. "Calcula la distancia SL automaticamente."
extern int     distSL               = 0;      // Distancia SL. "Manual cuando distSL_Auto==false."
extern int     distTP               = 0;      // Distancia TP.
extern double  RatioTP              = 1;      // Si RatioTP =0 se toma Distancia TP.
extern double  Balance              = 0;    // Balance. "Si Balance==0, Balance= Balance real de la cuenta."  

extern double  multiplicador_atr    = 3;      // Multiplicador ATR."Para calcular distancia del stop."
extern int     n_atr                = 10;     // Numero velas ATR.
extern ENUM_TIMEFRAMES TimeFrame    = PERIOD_CURRENT;// TimeFrame para el calculo del riesgo.
extern int     GV_Deslizamiento     = 10;     // Maximo deslizaminto;
extern int     maximo_numero_lotes  = 10;     // Maximo nº de lotes;
 

double pipMultiplier,GV_DistSL,GV_DistTP,GV_Lotes,GV_ValorDelTick;
double StopRiesgo,ValorATR;
int    nDecimales;

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart(){

    //if (MuestraAlerta)Alert("");
          
    nDecimales=1;
    double x=MarketInfo(Symbol(),MODE_LOTSTEP)*10;
    while(x<1)
     {
      x*=10; nDecimales+=1;
     }

    double digit  = MarketInfo(Symbol(),MODE_DIGITS); 
    //digit=_Digits;
    if(digit==2 || digit==4  || digit==1)  pipMultiplier = 1;
    if(digit==3 || digit==5)               pipMultiplier = 10;
    if(digit==6)                           pipMultiplier = 100;

    ValorATR=MathFloor (iATR(NULL,TimeFrame,n_atr,1)/Point);
    StopRiesgo=NormalizeDouble(multiplicador_atr*ValorATR,0);
    
      
    if (distSL_Auto) GV_DistSL=StopRiesgo;else GV_DistSL=distSL;
    GV_DistTP=distTP;
    if (RatioTP!=0 && GV_DistSL!=0)GV_DistTP=GV_DistSL*RatioTP; 
        
    CalculoNumeroLotes();            
   
    //--- Asignar a Variables Globales
  
  
    GlobalVariableSet("Ordenes_Lotes",GV_Lotes);
    GlobalVariableSet("Ordenes_DistanciaSL",GV_DistSL);
    GlobalVariableSet("Ordenes_DistanciaTP",GV_DistTP);
    GlobalVariableSet("Ordenes_Deslizamiento",GV_Deslizamiento);
    GlobalVariableSet("Valor_Tick",GV_ValorDelTick);
    //GlobalVariableSet("Ordenes_PorcRiego",GV_PorcRiesgo);
    //GlobalVariableSet("Ordenes_Balance",GV_Balance); 
       
  }
  
//+------------------------------------------------------------------+


void CalculoNumeroLotes()
    
    { 
             
       Balance=MathRound(Balance);
       if (Balance==0.0)Balance=MathRound(AccountBalance());      
       //if (Equidad=0.0)Equidad= MathRound(AccountEquity());       
              
       // Calculo con Fraccion Fija 
       
       GV_ValorDelTick =MarketInfo(Symbol(),MODE_TICKVALUE);
                         
       if (Lotes==0.0)GV_Lotes=NormalizeDouble(Balance*PorcRiesgo/100/StopRiesgo/ GV_ValorDelTick,nDecimales);
       else  GV_Lotes= Lotes;                                                                              
              
       GV_Lotes= MathRound (GV_Lotes/MarketInfo(Symbol(),MODE_LOTSTEP));
       GV_Lotes= GV_Lotes*MarketInfo(Symbol(),MODE_LOTSTEP);             
                       
       
       if (GV_Lotes<MarketInfo(Symbol(),MODE_MINLOT))  // Mínimo Nº de Lotes
         {                 
          //Alert(Symbol(),"-"+TFtoString(_Period),", Lotes= Mínimo nº de lotes= ",MarketInfo(Symbol(),MODE_MINLOT));
          MessageBox("Lotes= "+MarketInfo(Symbol(),MODE_MINLOT)+" (mínimo nº de lotes) \r\r"+ "Dist SL= "+GV_DistSL+                    
                     " pips.    Dist TP= "+GV_DistTP+" pips.",Symbol()+"-"+TFtoString(_Period) ); 
          
          GV_Lotes=MarketInfo(Symbol(),MODE_MINLOT);return;
         }
                
      if(GV_Lotes>maximo_numero_lotes) // Máximo Nº de Lotes
        {                    
          //Alert(Symbol(),"-"+TFtoString(_Period), " Lotes= Máximo nº de lotes= ", maximo_numero_lotes);
          MessageBox("Lotes= "+maximo_numero_lotes+" (máximo nº de lotes)\r\r Dist SL= "+GV_DistSL+ 
                     " pips.    Dist TP= "+GV_DistTP+" pips.",Symbol()+"-"+TFtoString(_Period) ); 
          
          GV_Lotes=maximo_numero_lotes;return;          
        }   
      
      
      if (Lotes==0.0) MessageBox("Lotes= "+ GV_Lotes+",   Riesgo="+PorcRiesgo+"% sobre "+Balance+" €."+"\r\r"+
                                 "Dist SL= "+GV_DistSL+ " pips.    Dist TP= "+GV_DistTP+" pips.",Symbol()+"-"+TFtoString(_Period) );                  
      
      else MessageBox(Symbol()+"-"+TFtoString(_Period)+": Nº Lotes discrecional="+ GV_Lotes);
      
      
    } 
  
//+------------------------------------------------------------------+

string TFtoString (int TF) { 

    string TFS = "";
    
    switch(TF) {
    
     case 1:     TFS = "M1";  break;
     case 5:     TFS = "M5";  break;
     case 15:    TFS = "M15"; break;
     case 30:    TFS = "M30"; break;
     case 60:    TFS = "H1";  break;
     case 240:   TFS = "H4";  break;
     case 1440:  TFS = "D1";  break;
     case 10080: TFS = "W1";  break;
     case 43200: TFS = "MN1"; break;
     
     }
     
  return(TFS);
  
  }



Re: Duda Programación Robot

Publicado: 13 Sep 2021 16:31
por landorra
Gracias por compartir el código. Lo probaré. ;)
Síntesis escribió: 12 Sep 2021 23:43 Te puedo pasar mi script pero te calcula sobre un porcentaje del balance. Lo puedes modificar si quieres para que te calcule sobre una cantidad.

Tiene otras opciones como el calculo automatico de la distancia del stop según el atr. También tengo los script para buy y sell con los parametros calculados aquí. Si te interesa me lo dices.

Código: Seleccionar todo



//+------------------------------------------------------------------+
//|                                                ParametrosSet.mq4 |
//|                                         Copyright 2020, Sintesis |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, Sintesis"
#property version   "4.00"
//--- strict compilation mode 
#property strict 
//--- show input parameters 
#property show_inputs 


//--- input parameters

extern double  PorcRiesgo           = 2;      // Porcentaje Riesgo. "Si es cero, nº de lotes mínimo." 
extern double  Lotes                = 0;      // Nº Lotes. "Si Lotes== 0.0, entonces cálculo de lotes automatico."

extern bool    distSL_Auto          = true;   // distSL_Auto. "Calcula la distancia SL automaticamente."
extern int     distSL               = 0;      // Distancia SL. "Manual cuando distSL_Auto==false."
extern int     distTP               = 0;      // Distancia TP.
extern double  RatioTP              = 1;      // Si RatioTP =0 se toma Distancia TP.
extern double  Balance              = 0;    // Balance. "Si Balance==0, Balance= Balance real de la cuenta."  

extern double  multiplicador_atr    = 3;      // Multiplicador ATR."Para calcular distancia del stop."
extern int     n_atr                = 10;     // Numero velas ATR.
extern ENUM_TIMEFRAMES TimeFrame    = PERIOD_CURRENT;// TimeFrame para el calculo del riesgo.
extern int     GV_Deslizamiento     = 10;     // Maximo deslizaminto;
extern int     maximo_numero_lotes  = 10;     // Maximo nº de lotes;
 

double pipMultiplier,GV_DistSL,GV_DistTP,GV_Lotes,GV_ValorDelTick;
double StopRiesgo,ValorATR;
int    nDecimales;

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart(){

    //if (MuestraAlerta)Alert("");
          
    nDecimales=1;
    double x=MarketInfo(Symbol(),MODE_LOTSTEP)*10;
    while(x<1)
     {
      x*=10; nDecimales+=1;
     }

    double digit  = MarketInfo(Symbol(),MODE_DIGITS); 
    //digit=_Digits;
    if(digit==2 || digit==4  || digit==1)  pipMultiplier = 1;
    if(digit==3 || digit==5)               pipMultiplier = 10;
    if(digit==6)                           pipMultiplier = 100;

    ValorATR=MathFloor (iATR(NULL,TimeFrame,n_atr,1)/Point);
    StopRiesgo=NormalizeDouble(multiplicador_atr*ValorATR,0);
    
      
    if (distSL_Auto) GV_DistSL=StopRiesgo;else GV_DistSL=distSL;
    GV_DistTP=distTP;
    if (RatioTP!=0 && GV_DistSL!=0)GV_DistTP=GV_DistSL*RatioTP; 
        
    CalculoNumeroLotes();            
   
    //--- Asignar a Variables Globales
  
  
    GlobalVariableSet("Ordenes_Lotes",GV_Lotes);
    GlobalVariableSet("Ordenes_DistanciaSL",GV_DistSL);
    GlobalVariableSet("Ordenes_DistanciaTP",GV_DistTP);
    GlobalVariableSet("Ordenes_Deslizamiento",GV_Deslizamiento);
    GlobalVariableSet("Valor_Tick",GV_ValorDelTick);
    //GlobalVariableSet("Ordenes_PorcRiego",GV_PorcRiesgo);
    //GlobalVariableSet("Ordenes_Balance",GV_Balance); 
       
  }
  
//+------------------------------------------------------------------+


void CalculoNumeroLotes()
    
    { 
             
       Balance=MathRound(Balance);
       if (Balance==0.0)Balance=MathRound(AccountBalance());      
       //if (Equidad=0.0)Equidad= MathRound(AccountEquity());       
              
       // Calculo con Fraccion Fija 
       
       GV_ValorDelTick =MarketInfo(Symbol(),MODE_TICKVALUE);
                         
       if (Lotes==0.0)GV_Lotes=NormalizeDouble(Balance*PorcRiesgo/100/StopRiesgo/ GV_ValorDelTick,nDecimales);
       else  GV_Lotes= Lotes;                                                                              
              
       GV_Lotes= MathRound (GV_Lotes/MarketInfo(Symbol(),MODE_LOTSTEP));
       GV_Lotes= GV_Lotes*MarketInfo(Symbol(),MODE_LOTSTEP);             
                       
       
       if (GV_Lotes<MarketInfo(Symbol(),MODE_MINLOT))  // Mínimo Nº de Lotes
         {                 
          //Alert(Symbol(),"-"+TFtoString(_Period),", Lotes= Mínimo nº de lotes= ",MarketInfo(Symbol(),MODE_MINLOT));
          MessageBox("Lotes= "+MarketInfo(Symbol(),MODE_MINLOT)+" (mínimo nº de lotes) \r\r"+ "Dist SL= "+GV_DistSL+                    
                     " pips.    Dist TP= "+GV_DistTP+" pips.",Symbol()+"-"+TFtoString(_Period) ); 
          
          GV_Lotes=MarketInfo(Symbol(),MODE_MINLOT);return;
         }
                
      if(GV_Lotes>maximo_numero_lotes) // Máximo Nº de Lotes
        {                    
          //Alert(Symbol(),"-"+TFtoString(_Period), " Lotes= Máximo nº de lotes= ", maximo_numero_lotes);
          MessageBox("Lotes= "+maximo_numero_lotes+" (máximo nº de lotes)\r\r Dist SL= "+GV_DistSL+ 
                     " pips.    Dist TP= "+GV_DistTP+" pips.",Symbol()+"-"+TFtoString(_Period) ); 
          
          GV_Lotes=maximo_numero_lotes;return;          
        }   
      
      
      if (Lotes==0.0) MessageBox("Lotes= "+ GV_Lotes+",   Riesgo="+PorcRiesgo+"% sobre "+Balance+" €."+"\r\r"+
                                 "Dist SL= "+GV_DistSL+ " pips.    Dist TP= "+GV_DistTP+" pips.",Symbol()+"-"+TFtoString(_Period) );                  
      
      else MessageBox(Symbol()+"-"+TFtoString(_Period)+": Nº Lotes discrecional="+ GV_Lotes);
      
      
    } 
  
//+------------------------------------------------------------------+

string TFtoString (int TF) { 

    string TFS = "";
    
    switch(TF) {
    
     case 1:     TFS = "M1";  break;
     case 5:     TFS = "M5";  break;
     case 15:    TFS = "M15"; break;
     case 30:    TFS = "M30"; break;
     case 60:    TFS = "H1";  break;
     case 240:   TFS = "H4";  break;
     case 1440:  TFS = "D1";  break;
     case 10080: TFS = "W1";  break;
     case 43200: TFS = "MN1"; break;
     
     }
     
  return(TFS);
  
  }