Preguntas de los principiantes MQL5 MT5 MetaTrader 5 - página 1415

 

Gracias por el código. Lo único que faltaba era la adaptación a un tamaño de lote intermedio válido:

double lotsz (double risk, double sl, ENUM_ORDER_TYPE ordDir, string sym="", double CommissionPerLot=0) {
   MqlTick mqTick;
   if (sym == "") sym = _Symbol;
   double deltaValue = SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE) / SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_SIZE);
   SymbolInfoTick(sym,mqTick); 
   double diff = (ordDir==ORDER_TYPE_BUY) ? mqTick.ask - sl : ( (ordDir==ORDER_TYPE_SELL) ? sl - mqTick.bid : -1.0 );
   if (diff<0.0) return(0.0);
   double lts = ( (AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk/100) / (diff * deltaValue + CommissionPerLot) );
   lts = ( fmin(fmax(SymbolInfoDouble(sym,SYMBOL_VOLUME_MIN),lts),SymbolInfoDouble(sym,SYMBOL_VOLUME_MAX)));
   double stepSize = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);
   return ((int)MathRound(lts/stepSize)*stepSize);
}
// use: lotsz(5, sl)

Tengo otra pregunta: Si calculo la pérdida de una operación stopped out con TICK_VALUE o con deltaValue como arriba, el resultado es siempre ligeramente diferente del cálculo interno de MQL5:

double price=(ordDir==ORDER_TYPE_BUY) ? mqTick.ask : ((ordDir==ORDER_TYPE_SELL) ? mqTick.bid : mqTick.last);
double loss;
OrderCalcProfit(ordDir, sym, 1, price, sl, loss)

¿Esto se debe a que la pérdida/ganancia por tick es diferente para una cuenta EUR y para precio de mercado 1.0 y precio de mercado 1.2? Porque si introduzco, por ejemplo, "price + 0.1" en lugar de price y "sl + 0.1" en lugar de sl en el código de abajo, entonces la distancia por tick (diff) es la misma, pero los respectivos resultados emitidos por OrderCalcProfit son diferentes. Y cuando miro los beneficios/pérdidas que obtengo de las operaciones manuales, esto último parece confirmarse.

Si estoy en lo cierto, entonces el siguiente código sería más preciso:

double lotsz (double risk, double entry, double sl, ENUM_ORDER_TYPE ordDir, string sym="", double CommissionPerLot=0) {
   if (sym == "") sym = _Symbol;
   double loss;
   OrderCalcProfit(ordDir, sym, 1, entry, sl, loss);
   double lts = ((AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk * 0.01) / -loss);
   lts = (fmin(fmax(SymbolInfoDouble(sym, SYMBOL_VOLUME_MIN), lts), SymbolInfoDouble(sym, SYMBOL_VOLUME_MAX)));
   double stepSize = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);
   return ((int)MathRound(lts / stepSize) * stepSize);
}
// use: lotsz(5, ask, sl)
P.D. Gracias de nuevo por la idea básica: vincular el factor de riesgo no al saldo sino al margen libre tiene claramente sentido.
 

El siguiente código fue creado según el propio sar parabólico experto de mql 5. ¿Puedo invertir aquí el funcionamiento de la señal de compra y de la señal de venta? Es decir, cuando llegue la señal de compra, quiero que abra venta en lugar de compra. ¿alguien me puede ayudar?




#property copyright "Copyright 2022, MetaQuotes Ltd."

#property link "https://www.mql5.com"

#property version "1.00"

//+------------------------------------------------------------------+

//| Incluir |

//+------------------------------------------------------------------+

#include <Expert\Expert.mqh>

//--- señales disponibles

#include <ExpertoSeñalSAR.mqh>

//--- señales disponibles

#include <Expert\Trailing\TrailingNone.mqh>

//--- gestión de dinero disponible

#include <Expert\Money\Money\MoneyFixedLot.mqh>

//+------------------------------------------------------------------+

//| Entradas |

//+------------------------------------------------------------------+

//--- entradas para el experto

input string Expert_Title ="sar"; // Nombre del documento

ulong Expert_MagicNumber =13831; //

bool Expert_EveryTick =false; //

//--- entradas para la señal principal

input int Signal_ThresholdOpen =10; // Valor umbral de la señal a abrir [0...100]

input int Signal_ThresholdClose=10; // Valor umbral de la señal para cerrar [0...100]

input double Signal_PriceLevel =0.0; // Nivel de precio para ejecutar una operación

input int Signal_Expiration =4; // Vencimiento de las órdenes pendientes (en compases)

input double Signal_SAR_Step =0.02; // Incremento de velocidad del SAR Parabólico(0.02,0.2)

input double Signal_SAR_Maximum =0.2; // Parabolic SAR(0.02,0.2) Velocidad máxima

input double Señal_SAR_Peso =1.0; // Parabólica SAR(0.02,0.2) Peso [0....1.0]

//--- entradas para dinero

input double Money_FixLot_Percent =10.0; // Porcentaje

input double Money_FixLot_Lots =0.1; // Volumen fijo

//+------------------------------------------------------------------+

//| Objeto experto global

//+------------------------------------------------------------------+

CExpert ExtExpert;

//+------------------------------------------------------------------+

//| Función de inicialización del experto

//+------------------------------------------------------------------+

int OnInit()

{

//--- Inicialización del experto

if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber))

{

//----- falló

printf(__FUNCTION__+": error inicializando experto");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Creando señal

CExpertSignal *signal=nueva CExpertSignal;

if(señal==NULL)

{

//----- falló

printf(__FUNCTION__+": error creando señal");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//---

ExtExpert.InitSignal(señal);

signal.ThresholdOpen(Señal_UmbralAbrir);

signal.ThresholdClose(Señal_UmbralCierre);

signal.PriceLevel(Señal_NivelPrecio);

signal.Expiration(Señal_Expiración);

//--- Creación del filtro CSignalSAR

CSignalSAR *filtro0=nuevo CSignalSAR;

if(filtro0==NULL)

{

//----- fallido

printf(__FUNCTION__+": error creando filtro0");

ExtExpert.Deinit();

return(INIT_FAILED);

}

signal.AddFilter(filter0);

//--- Establece los parámetros del filtro

filter0.Paso(Señal_SAR_Paso);

filter0.Máximo(Señal_SAR_Máximo);

filter0.Peso(Señal_SAR_Peso);

//--- Creación del objeto trailing

CTrailingNone *trailing=nuevo CTrailingNone;

if(trailing==NULL)

{

//----- fallido

printf(__FUNCTION__+": error creando trailing");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Añadir trailing al experto (se borrará automáticamente))

if(!ExtExpert.InitTrailing(trailing))

{

//----- falló

printf(__FUNCTION__+": error inicializando trailing");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Establecer parámetros de trailing

//--- Creación del objeto dinero

CMoneyFixedLot *money=nuevo CMoneyFixedLot;

if(dinero==NULL)

{

//----- falló

printf(__FUNCTION__+": error creando dinero");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Añade dinero al experto (se borrará automáticamente))

if(!ExtExpert.InitMoney(dinero))

{

//----- falló

printf(__FUNCTION__+": error inicializando dinero");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Establecer parámetros de dinero

money.Porcentaje(Money_FixLot_Percent);

money.Lots(Money_FixLot_Lots);

//--- Comprobar todos los parámetros de los objetos de negociación

if(!ExtExpert.ValidationSettings())

{

//----- falló

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Ajuste de todos los indicadores necesarios

if(!ExtExpert.InitIndicators())

{

//----- falló

printf(__FUNCTION__+": error inicializando indicadores");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- ok

return(INIT_SUCCEED);

}

//+------------------------------------------------------------------+

//| Función de desinicialización del experto |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

{

ExtExpert.Deinit();

}

//+------------------------------------------------------------------+

//| Función manejadora del evento "Tick

//+------------------------------------------------------------------+

void OnTick()

{

ExtExpert.OnTick();

}

//+------------------------------------------------------------------+

//| Función manejadora del evento "Trade

//+------------------------------------------------------------------+

void OnTrade()

{

ExtExpert.OnTrade();

}

//+------------------------------------------------------------------+

//| Función manejadora del evento "Timer" |

//+------------------------------------------------------------------+

void OnTimer()

{

ExtExpert.OnTimer();

}

//+------------------------------------------------------------------+


 
Interesante sugerencia, le echaré un vistazo. La función OrderCalcProfit() sólo existe en MT5 y las ideas para el cálculo de lotes se remontan a tiempos de MT4....
 
No puedo abrir mi sesión en la app para poder ver cuanto dinero tengo 
 

Ahora he tenido tiempo de estudiar tu solución. Es más precisa (mientras que la otra es más cautelosa ya que se tiene en cuenta la comisión...) y es aparentemente menos propensa a errores, como se puede ver con el oro y la plata en la cuenta demo en MQ - con Roboforex es, como era de esperar, algo más cautelosa que su solución:

MetaQuotes demo account (b. 3369 Beta channel)
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   XAUUSD  in: 1717.65000 sl:1717.15000  diff:0.50000  delta:10.00000  delta:*diff:5.00000  tVal:0.10000  tSz:0.01000
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   XAGUSD  in: 18.45100 sl:18.40100  diff:0.05000  delta:500.00000  delta:*diff:25.00000  tVal:0.50000  tSz:0.00100
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   EURUSD  in: 1.02185 sl:1.02235  diff:0.00050  delta:97861.72139  delta:*diff:48.93086  tVal:0.97862  tSz:0.00001
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 9983.40 EUR:  XAUUSD  BU  in: 1717.65000  sl: 1717.15000  lotsC: 71.3100 (-3489.26)  lotsB: 10.2000 (-499.09)
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 9983.40 EUR:  XAGUSD  BU  in: 18.45100  sl: 18.40100  lotsC: 18.4900 (-4523.66)  lotsB: 2.0400 (-499.09)
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 9983.40 EUR:  EURUSD  SE  in: 1.02185  sl: 1.02235  lotsC: 9.8000 (-479.29)  lotsB: 10.2100 (-499.34)


RoboForex Demo account (b. 3320 release channel)
2022.07.25 17:46:22.772 test_MM-functions (EURUSD,D1)   XAUUSD  in: 1717.10000 sl:1717.15000  diff:0.05000  delta:100.00000  delta:*diff:5.00000  tVal:0.10000  tSz:0.00100
2022.07.25 17:46:22.772 test_MM-functions (EURUSD,D1)   XAGUSD  in: 18.43400 sl:18.43350  diff:0.00050  delta:5000.00000  delta:*diff:2.50000  tVal:0.05000  tSz:0.00001
2022.07.25 17:46:22.772 test_MM-functions (EURUSD,D1)   EURUSD  in: 1.02186 sl:1.02236  diff:0.00050  delta:100000.00000  delta:*diff:50.00000  tVal:1.00000  tSz:0.00001
2022.07.25 17:46:22.773 test_MM-functions (EURUSD,D1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 5348.69 USD:  XAUUSD  SE  in: 1717.10000  sl: 1717.15000  lotsC: 38.2000 (-191.00)  lotsB: 53.4900 (-267.45)
2022.07.25 17:46:22.773 test_MM-functions (EURUSD,D1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 5348.69 USD:  XAGUSD  BU  in: 18.43400  sl: 18.43350  lotsC: 59.4300 (-148.57)  lotsB: 106.9700 (-267.42)
2022.07.25 17:46:22.773 test_MM-functions (EURUSD,D1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 5348.69 USD:  EURUSD  SE  in: 1.02186  sl: 1.02236  lotsC: 5.1400 (-257.00)  lotsB: 5.3500 (-267.50)

En la cuenta de MQ, el tamaño de los lotes sería demasiado alto.

Aquí está mi script para comparar los dos métodos:

//+------------------------------------------------------------------+
//|                                            test_MM-functions.mq5 |
//|                                                            Calli |
//|                              https://www.mql5.com/de/users/gooly |
//+------------------------------------------------------------------+
#property copyright "Calli"
#property link      "https://www.mql5.com/de/users/gooly"
#property version   "1.00"
#property script_show_inputs
//--- input parameters
input double   risk_perCent   = 5.0;   // risk of capital in % on free_margin
input double   diff_sl        = 50;    // diff sl in points from entry
input double   CommPerLot     = 2.00;  

string Com = "",Syms[] = {"XAUUSD", "XAGUSD", "EURUSD" }; //,"AUDUSD","GBPCHF","GBPUSD", "EURCAD", "USDCAD", "USDRUB", "GBPJPY", "USDJPY"};

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
#define  forEach(TYPE, VAR, ARRAY) \
                TYPE VAR=NULL; \
                for(int i##VAR=0;  i##VAR<ArraySize(ARRAY)&&((VAR=ARRAY[i##VAR])!=NULL||true);  i##VAR++)

void OnStart()
  {
//---
   MqlTick mqTick;
   forEach(string, sym, Syms){
      
      double pnt = SymbolInfoDouble(sym,SYMBOL_POINT);
      ENUM_ORDER_TYPE ord = GetMicrosecondCount()%2==0 ? ORDER_TYPE_BUY : ORDER_TYPE_SELL; // randomly buy or sell
      SymbolInfoTick(sym,mqTick); 
      double entry = (ord==ORDER_TYPE_BUY) ? mqTick.ask : mqTick.bid,
             sl    = (ord==ORDER_TYPE_BUY) ? entry - diff_sl*pnt : entry + diff_sl*pnt,
             lossC = 0.0, lossB = 0.0,
             lotsC = lotszC(risk_perCent, entry, sl, sym, CommPerLot), 
             lotsB = lotszB(risk_perCent, entry, sl, sym, CommPerLot);
      
      if (!OrderCalcProfit(ord, sym, lotsC, entry, sl, lossC) ) 
         Print("chk OrderCalcProfit(",EnumToString(ord),", ",sym,", lot: ",lotsC,", in: ",DoubleToString(entry,6),", out: ",DoubleToString(sl,6),", lossC) => err: ",_LastError," lossC: ",lossC);
             
      if (!OrderCalcProfit(ord, sym, lotsB, entry, sl, lossB) ) 
         Print("chk OrderCalcProfit(",EnumToString(ord),", ",sym,", lot: ",lotsC,", in: ",DoubleToString(entry,6),", out: ",DoubleToString(sl,6),", lossC) => err: ",_LastError," lossC: ",lossC);
             
      string res = StringFormat("Set: Risk: %.1f %%, dSL: %.0f  Com/Lot: %.2f  Free: %.2f %s:  %s  %s  in: %.5f  sl: %.5f  lotsC: %.4f (%+.2f)  lotsB: %.4f (%+.2f)",
                                 risk_perCent, diff_sl, CommPerLot,
                                 AccountInfoDouble(ACCOUNT_MARGIN_FREE),AccountInfoString(ACCOUNT_CURRENCY),
                                 sym, (ord==ORDER_TYPE_BUY ? "BU" : "SE"), entry, sl, lotsC, lossC, lotsB, lossB );
      Com = Com + res+"\n";
   }
   Comment(Com);
   //Print(Com);
  }
//+------------------------------------------------------------------+
double lotszC (double risk, double entry, double sl, string sym="", double CommissionPerLot=0) {
   if (sym == "") sym = _Symbol;
   double deltaValue = SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE) / SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_SIZE);
   ENUM_ORDER_TYPE ordDir = entry > sl ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
   double diff = fabs (entry - sl); 
   Print(sym,"  in: ",DoubleToString(entry,5)," sl:",DoubleToString(sl,5),"  diff:",DoubleToString(diff,5),
         "  delta:",DoubleToString(deltaValue,5),"  delta:*diff:",DoubleToString(deltaValue*diff,5),
         "  tVal:",DoubleToString(SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE),5),"  tSz:",
         DoubleToString(SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_SIZE),5));
   double lts = ( (AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk/100) / (diff * deltaValue + CommissionPerLot) );
   lts = ( fmin(fmax(SymbolInfoDouble(sym,SYMBOL_VOLUME_MIN),lts),SymbolInfoDouble(sym,SYMBOL_VOLUME_MAX)));
   double stepSize = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);
   return (MathRound(lts/stepSize)*stepSize);
}

double lotszB (double risk, double entry, double sl, string sym="", double CommissionPerLot=0) {
   if (sym == "") sym = _Symbol;
   ENUM_ORDER_TYPE ordDir = entry > sl ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
   double loss;
   if (!OrderCalcProfit(ordDir, sym, 1, entry, sl, loss)) return(-1.0);
   double lts = ((AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk * 0.01) / -loss);
   lts = (fmin(fmax(SymbolInfoDouble(sym, SYMBOL_VOLUME_MIN), lts), SymbolInfoDouble(sym, SYMBOL_VOLUME_MAX)));
   double stepSize = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);
   return (MathRound(lts / stepSize) * stepSize);
}

Derivé la dirección de in > sl (comprar) o in < sl (vender). Entonces no habría problemas con las órdenes pendientes

 

Gracias por sus pruebas. Sí, si se comparan los resultados entre sí, se puede ver por un lado la consistencia de OrderCalcProfit y por otro lado, al menos para EURUSD y RoboForex, que los resultados difieren en aproximadamente "Lot size * CommissionPerLot". Esto se podría añadir:

if (!OrderCalcProfit(ordDir, sym, 1, entry, sl, loss)) return(-1.0);
double lts = ((AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk * 0.01) / (-loss + CommissionPerLot);
Si he utilizado correctamente la búsqueda del foro, no hay manera de consultar el valor "CommissionPerLot" directamente utilizando MQL5, ¿verdad?
 
Benjamin Fotteler #:


Si he utilizado correctamente la búsqueda del foro, entonces no hay manera de consultar el valor "CommissionPerLot" directamente utilizando MQL5, ¿verdad?

Sí, no directamente en el terminal, sino solicitándolo al broker o en el historial de operaciones: DEAL_COMMISSION.

Dokumentation zu MQL5: Konstanten, Enumerationen und Strukturen / Handelskonstanten / Eigenschaften der Deals
Dokumentation zu MQL5: Konstanten, Enumerationen und Strukturen / Handelskonstanten / Eigenschaften der Deals
  • www.mql5.com
Eigenschaften der Deals - Handelskonstanten - Konstanten, Enumerationen und Strukturen - Nachschlagewerk MQL5 - Nachschlagewerk über die Sprache des algothitmischen/automatischen Handels für MetaTrader 5
 



Estimados miembros~.


Estoy tratando de contar velas. por favor ayuda~~


int Barcount;

if(Barcount != Bars)

{ Barcount
Barcount = Bars;
pt = pt + 1;
}

Print("pt=",pt) ;


int OT,SHi;

if(OrderSelect(ticket,SELECT_BY_TICKET)==true)

{ }

OT = OrderOpenTime();

}

SHi = iBarShift(Symbol(),0,OT);

Imprimir("SHi=",SHi);

 

Hola.

Pregunta de aficionado sobre CFDs.

¿Puede alguien explicar la naturaleza de los swaps para CFD sobre materias primas/acciones? ¿De dónde viene el swap que se acumula durante la noche? ¿Cuál es la explicación?

 
Buenas tardes. El idioma ruso no funciona en Mt4