¡Necesito la fórmula del tamaño de LOT de moneymanagement basada en el SL y el riesgo de la cuenta! - página 3

 

¡OK chicos! Este código fue escrito por mí y es el que uso en mis propios EAs. Es bastante complejo porque, además del Risk% y el StopLoss, también tiene en cuenta el Margin Risk% así como corrige el Lot Size en base al Minimum, Maximum y Step Size. También utiliza siempre el valor mínimo del Balance Actual y del Patrimonio en lugar de utilizar sólo uno de ellos. Creo que es más seguro de esa manera.

Tenga en cuenta, sin embargo, que no utiliza el spread en el cálculo, porque lo calculo por separado al calcular el StopLoss a utilizar. La función de abajo, por lo tanto, utiliza un tamaño de stop loss relativo. En mis EA's el argumento dblStopLossPips se calcula de antemano dependiendo de varios factores como la estrategia, el spread, el ATR, etc.; por lo que el valor final que se pasa a la función dblLotsRisk() es ya un valor final para calcular el tamaño del Lote a utilizar.

// Function to Determine Tick Point Value in Account Currency

        double dblTickValue( string strSymbol )
        {
                return( MarketInfo( strSymbol, MODE_TICKVALUE ) );
        }
        

// Function to Determine Pip Point Value in Account Currency

        double dblPipValue( string strSymbol )
        {
                double dblCalcPipValue = dblTickValue( strSymbol );
                switch ( MarketInfo( strSymbol, MODE_DIGITS ) )
                {
                        case 3:
                        case 5:
                                dblCalcPipValue *= 10;
                                break;
                }
                
                return( dblCalcPipValue );
        }
        

// Calculate Lot Size based on Maximum Risk & Margin

        double dblLotsRisk( string strSymbol, double dblStopLossPips,
                double dblRiskMaxPercent, double dblMarginMaxPercent,
                double dblLotsMin, double dblLotsMax, double dblLotsStep )
        {
                double
                        dblValueAccount = MathMin( AccountEquity(), AccountBalance() )
                ,       dblValueRisk    = dblValueAccount * dblRiskMaxPercent / 100.0
                ,       dblValueMargin  = AccountFreeMargin() * dblMarginMaxPercent / 100.0
                ,       dblLossOrder    = dblStopLossPips * dblPipValue( strSymbol )
                ,       dblMarginOrder  = MarketInfo( strSymbol, MODE_MARGINREQUIRED )
                ,       dblCalcLotMin
                                = MathMax( dblLotsMin, MarketInfo( strSymbol, MODE_MINLOT ) )
                ,       dblCalcLotMax
                                = MathMin( dblLotsMax, MarketInfo( strSymbol, MODE_MAXLOT ) )
                ,       dblModeLotStep  = MarketInfo( strSymbol, MODE_LOTSTEP )
                ,       dblCalcLotStep  = MathCeil( dblLotsStep / dblModeLotStep ) * dblModeLotStep
                ,       dblCalcLotLoss
                                = MathFloor( dblValueRisk / dblLossOrder / dblCalcLotStep ) * dblCalcLotStep
                ,       dblCalcLotMargin
                                = MathFloor( dblValueMargin / dblMarginOrder / dblCalcLotStep ) * dblCalcLotStep
                ,       dblCalcLot = MathMin( dblCalcLotLoss, dblCalcLotMargin )
                ;
                
                if ( dblCalcLot < dblCalcLotMin ) dblCalcLot = dblCalcLotMin;
                if ( dblCalcLot > dblCalcLotMax ) dblCalcLot = dblCalcLotMax;

                return ( dblCalcLot );
        }
 
GumRai:

Esto me da dolor de cabeza sólo por tratar de entender los paréntesis.

Para ser honesto, no tengo ni idea de lo que está tratando de lograr aquí.

No puedo ver cómo MODE_STOPLEVEL o SPREAD son relevantes, seguramente debería basar sus cálculos en la distancia de stop-loss desde el precio actual.

No debería hacer ninguna diferencia cuál es la moneda de la cuenta, el cálculo debería ser el mismo porque TICKVALUE está en la moneda de la cuenta.

Tenga en cuenta, al poner su línea de código en 2 líneas, el post no es tan amplia y hace que sea más fácil de leer sin desplazarse a la derecha y la izquierda :)

En la página anterior publiqué una imagen en la que ilustraba mi fórmula para calcular el lote, pero el pipvalue o tickvalue o lo que sea siempre está dando vueltas, cotización->moneda base y otras cosas que son confusas, pero hasta ahora mi fórmula ha hecho un buen trabajo, aunque no estoy seguro de que sea correcta.

El SPREAD puede ser irrelevante, pero el stoplevel es necesario. Pongo el SL lo más cerca posible del precio de la orden, que es el nivel de stoplevel, pero debido a las fluctuaciones y picos, necesito ajustarlo manualmente a veces, por eso pongo una variable STOPSLIP con la que puedo ajustar el SL a la volatilidad o lo que sea.

FMIC:

¡OK chicos! Este código lo he escrito yo y es el que utilizo en mis propios EA's. Es bastante complejo porque, además del Risk% y el StopLoss, también tiene en cuenta el Margin Risk% así como corrige el Lot Size en base al Minimum, Maximum y Step Size. También utiliza siempre el valor mínimo del Balance Actual y del Patrimonio en lugar de utilizar sólo uno de ellos. Creo que es más seguro de esa manera.

Tenga en cuenta, sin embargo, que no utiliza el spread en el cálculo, porque lo calculo por separado al calcular el StopLoss a utilizar. La función de abajo, por lo tanto, utiliza un tamaño de stop loss relativo. En mis EA's el argumento dblStopLossPips se calcula de antemano dependiendo de varios factores como la estrategia, el spread, el ATR, etc.; por lo que el valor final que se pasa a la función dblLotsRisk() es ya un valor final para calcular el tamaño del Lote a utilizar.

Gracias, lo probaré y diré mi opinión.

Aunque no entiendo por qué pones tantas variables ahí, todo el código puede caber en 1 línea :)

 
Proximus:

En la página anterior publiqué una imagen en la que ilustraba mi fórmula para calcular el lote, pero el pipvalue o tickvalue o lo que sea siempre está dando vueltas, cotización->moneda base y otras cosas que son confusas, pero hasta ahora mi fórmula hizo un buen trabajo, aunque no estoy seguro de que sea correcta.

El SPREAD puede ser irrelevante, pero el stoplevel es necesario. Puse el SL lo más cerca posible del precio de la orden, que es el nivel de stoplevel, pero debido a las fluctuaciones y picos, necesito ajustarlo manualmente a veces, por eso puse una variable STOPSLIP con la que puedo ajustar el SL a la volatilidad o lo que sea.

Gracias, lo probaré y diré mi opinión.

Aunque no entiendo por qué pones tantas variables ahí, todo el código puede caber en 1 línea :)


Sí, el código podría ponerse en una sola línea, pero créeme, NUNCA es una buena manera de codificar, a menos que estés tratando de exprimir hasta el último ciclo de CPU de tu código para ser el más rápido del planeta.

Por eso "GumRai" se quejaba de que le dolía la cabeza al intentar entender el otro código. Simplemente no era muy legible o fácil de entender y eso lo hace muy difícil de depurar.

Mi manera puede ser más verbosa, pero es más fácil de depurar y mantener, así como más legible y más fácil de entender por otros como usted.

Pero siéntase libre de compactarlo todo en una línea. Pero no se queje si no da los mismos resultados. Dejaré que seas tú quien depure ESO.

 

Perdonad por reabrir este hilo pero es crucial confirmar algo, así que esta es la función que se me ha ocurrido (la pongo pública y me lo podéis agradecer después):

double LOTUNITSTORISK()
{
double LOTS=((AccountBalance()*RISKPERCENT/100) / (  MarketInfo(Symbol(), MODE_TICKVALUE)*MarketInfo(Symbol(), MODE_TICKSIZE)*STOPSIZE     ));
return LOTS;
}


Esta función debería devolver las unidades de lote basadas en el riesgo de la cuenta, y calculadas a través de una cuenta en EUR, ya que el EUR es siempre la moneda base.

Unidad de lote significa = el tamaño real del dinero de una posición por lo que para una cuenta de 100 € de 1% de riesgo debería devolver 1€ que basado en el STOPLOSS por ejemplo un stoploss de 100 pipetas debería ser 1000 unidades de lote ( 0.01 LOT EN MT4 EQUIVALENTE)

Es crítico que la moneda de la cuenta sea el EURO, nada más.

Una vez que llamemos a LOTUNITTORISK(), dividiremos el resultado por 100.000 para obtener el tamaño real del lote en formato MT4 (1000 unidades de efectivo 0,01 LOTE en MT4)

RISKPERCENT =es un int y puede ser 1,2,3,4 el % de riesgo que arriesgamos

STOPSIZE = es un int y es el número de pipetas (pips/10 en broker de 5 dígitos) que tiene nuestro tamaño de stoploss, así por ejemplo 60 pipetas SL es un SL de 6 pip.

Quiero saber si la función calcula bien los LOT UNITS, por favor pruébenla y si encuentran algún error por favor ayúdenme :)

¡Mil gracias!

 
Proximus:
MarketInfo(Symbol(), MODE_TICKVALUE)* MarketInfo(Symbol(), MODE_TICKSIZE)*STOPSIZE

Risk  = lotsize * StopSize * TickValue /  TickSize
         1      *  0.0100  *  $10.00   / 0.0001
$1000 = one lot * 100 pips *  $10.00   / pip
  1. Usted coloca el stop donde debe estar - donde la razón de la operación ya no es válida. Por ejemplo, al negociar un rebote de un soporte, el stop se sitúa por debajo del soporte.
  2. Saldo de la cuenta * porcentaje = RIESGO = (OrderOpenPrice - OrderStopLoss)*DIR * OrderLots * DeltaPerlot (Nota OOP-OSL incluye el SPREAD)
  3. NO utilice TickValue por sí mismo - DeltaPerlot
  4. También debe comprobar FreeMargin para evitar el stop out
 
WHRoeder:
  1. Usted coloca el stop donde debe estar - donde la razón de la operación ya no es válida. Por ejemplo, al negociar un rebote de un soporte, el stop se sitúa por debajo del soporte.
  2. Saldo de la cuenta * porcentaje = RIESGO = (OrderOpenPrice - OrderStopLoss)*DIR * OrderLots * DeltaPerlot (Nota OOP-OSL incluye el SPREAD)
  3. NO utilice TickValue por sí mismo - DeltaPerlot
  4. También hay que comprobar el FreeMargin para evitar el stop out

1) La función solo devuelve el LOT SIZE en unidad monetaria no en unidad MT4 nada mas, cuando pongo las ordenes entonces respectivamente el STOPSIZE será añadido/sustraído de Bid en caso de BUY y Ask en caso de sell.It es igual que MT4 maneja el TP y SL.

COMPRA abierta en ASK, cerrada en BID

VENTA abierta en BID, cerrada en ASK

2) No puedo usar OrderOpenprice man porque no se abre ninguna orden antes de que se calcule esta función.Spreads no incluidos, los spreads se manejarán cuando añada/resuma el STOPSIZE después de que se abra la orden.

Pero antes de eso necesitamos determinar el tamaño del lote, eso es lógico.

3) No entiendo esto.

4) Obviamente, pero vuelvo a recalcar que la función de colocación de órdenes se ejecuta después de esto, y tiene poco que ver con esta función.El único propósito que tiene esta función es determinar el tamaño del lote, nada más.


TickValue /  TickSize

Incorrecto, si los divido entonces obtengo el número incorrecto, tal vez para las cuentas en USD se debe hacer así, pero es una cuenta en EUR.Se deben multiplicar.

 
Proximus:

BUY abierto en ASK, cerrado en BID SELL abierto en BID, cerrado en ASK

2) No puedo usar OrderOpenprice

3) No entiendo esto.

4)t, si los divido entonces obtengo el número incorrecto, tal vez para las cuentas en USD se debe hacer así, pero es una cuenta en EUR.Deben ser multiplicados.

  1. El Ask es el OrderOpenPrice para una compra
  2. El Bid es el OrderOpenPrice para una venta. ¿Por qué no puedes usarlo, tienes que saberlo para pasarlo a OrderSend?
  3. Debes usar tickvalue/ticksize. El tickvalue por sí mismo no tiene sentido.
  4. Debes dividir para obtener las unidades correctas (Cambio en el precio) * (tickValue) /(cambio en el precio) te da un valor. $10 por pip = $1 por punto = valor/cambio. Recuerde que el resultado en es la moneda de la cuenta por lo que cuando se divide por su riesgo se obtiene un número puro, de nuevo las unidades cancelan $risk(BAL%)/$risk(SL). Si tienes que multiplicar es que estás haciendo algo mal o los valores del broker están estropeados.
 
WHRoeder:
Proximus:

COMPRA abierta en ASK, cerrada en BID VENTA abierta en BID, cerrada en ASK

2) No puedo utilizar OrderOpenprice

3) No entiendo esto.

4)t, si los divido entonces obtengo el número incorrecto, tal vez para las cuentas en USD se debe hacer así, pero es una cuenta en EUR.Deben ser multiplicados.

  1. El Ask es el OrderOpenPrice para una compra
  2. El Bid es el OrderOpenPrice para una venta. ¿Por qué no puedes usarlo, tienes que saberlo para pasarlo a OrderSend?
  3. Debes usar tickvalue/ticksize. Tickvalue por sí mismo no tiene sentido.
  4. Debes dividir para obtener las unidades correctas (Cambio en el precio) * (tickValue) /(cambio en el precio) te da un valor. $10 por pip = $1 por punto = valor/cambio. Recuerde que el resultado en es la moneda de la cuenta por lo que cuando se divide por su riesgo se obtiene un número puro, de nuevo las unidades cancelan $riesgo(BAL%)/$riesgo(SL). Si tienes que multiplicar es que estás haciendo algo mal o que los valores del broker están estropeados.


1,2 Lo sé, pero entiéndeme que eso lo maneja otra función que no tiene nada que ver con esta

3) Según tengo entendido el tickvalue es el valor de 1 pip en la moneda base, por lo que dependiendo del par que utilice habrá que dividir o multiplicar por él.En el caso de una cuenta en EUR parece que hay que multiplicar no dividir.

Aquí hay una imagen que lo ilustra mejor:


En el EUR/USD para una operación de 3% de riesgo necesitamos abrir 1798 unidades, redondeado 0.02 LOTES en unidades de MT4 para lograrlo.

El tamaño del STOPLOSS se determina por otra función.

Parece que es correcto, ya que lo he probado, pero no estoy seguro de si la fórmula es realmente precisa, que es lo que estoy tratando de determinar aquí, así que por favor ayuda en eso.

 

Yo también he estado tratando de averiguar este cálculo del tamaño del lote basado en el SL, el riesgo de la cuenta y el nivel de Margin Call, especialmente cuando el nivel de Margin Call no es del 100%, sino que es, por ejemplo, del 120%. La mejor respuesta que he encontrado es lo que WHRoeder compartió aquí en su código whrea.m q4. El código whrea.mq4 necesitaba alguna corrección pero WHRoeder ya da esa corrección aquí en su respuesta al comentario de RaptorUK. Así que la respuesta completa para calcular el tamaño del lote está ahí, pero se requiere un poco de esfuerzo para entender completamente lo que WHRoeder ha compartido.

He adjuntado el código que he extraído y modificado del whrea.mq4 de WHRoeder para compilarlo con la última nueva compilación de MT4 para calcular el tamaño del lote para una operación larga en la que el nivel de Margin Call es superior al 100%.

Sin embargo, no estoy seguro si multiplicar por el MarginCallLevel % es correcto para tener en cuenta el Margin Call Level % para evitar un margin call. Si el MarginCallLevel es 100% entonces ambas líneas de código serían correctas, pero si el MarginCallLevel es 120%, ¿multiplicar por el MarginCallLevel % sería una prueba correcta de Margin Call? Si no es así, ¿cuál es la forma correcta de hacerlo? WHRoeder, ¿puede ayudar con esto? William, he hecho todo lo posible.

Aquí está el código de esa sección de Prueba de Margen para una operación larga:

extern double MarginCallLevel = 120; //As a percentage

double MarginCallLevel1 = MarginCallLevel * 0.01; 

        double  AFMC    = AccountFreeMarginCheck(Symbol(), OP_BUY, tradesize),
                        eRisk   = equityatrisk + atrisknew;

        //Test for margin
        //Note: Not sure if multiplying by the MarginCallLevel % here is correct to 
        //take the Margin Call Level % into account for avoiding a margin call.
        //If the MarginCallLevel is 100% then both lines of code would be correct
        //but if the MarginCallLevel is 120% would multiplying by the MarginCallLevel %
        //be a correct Margin Call test? If not, then what is the correct way to do this?

        //if (AFMC*0.99 <= eRisk){
        if (AFMC*0.99 <= eRisk*MarginCallLevel1){
            tradesize *= 0.95;    // Must still round to lotStep.
            continue;   }   // Prevent margin call if new trade goes against us.
Archivos adjuntos:
 

... en esta parte del código hay un problema con la nueva compilación (error ---> 'MarketInfo' - tipo de expresión de cambio ilegal) tal vez todo estaba bien hasta la actualización a MT4 build 600+ ... pero desde entonces ya no funciona.

// Function to Determine Pip Point Value in Account Currency

        double dblPipValue( string strSymbol )
        {
                double dblCalcPipValue = dblTickValue( strSymbol );
                switch ( MarketInfo( strSymbol, MODE_DIGITS ) )
                {
                        case 3:
                        case 5:
                                dblCalcPipValue *= 10;
                                break;
                }
                
                return( dblCalcPipValue );
        }
        

Así que, por favor, podría publicar alguna versión más reciente ... si, por supuesto, todavía estás por aquí.


Razón de la queja: