¿Cómo se calcula el tamaño del lote?

 

Digamos que mi mini cuenta tiene un margen de 10.000 dólares, y quiero arriesgar un 2% en la próxima operación (es decir, simplemente usar 200 dólares para comprar <alguna cantidad> de contratos).

[Me doy cuenta de que esta es una visión limitada del "riesgo". No me interesan los pips de stopLoss, ni los objetivos de beneficios, ni nada por el estilo].

Usando MetaTrader, obtengo la siguiente información de la mini cuenta de mi corredor:

accountLeverage = AccountLeverage(); // valor = 200
modeLotSize = MarketInfo("EURUSDm", MODE_LOTSIZE); // valor = 10000
modeLotStep = MarketInfo("EURUSDm", MODE_LOTSTEP); // valor = .01
modeMinLot = MarketInfo("EURUSDm", MODE_MINLOT) ); // valor = .01

PREGUNTA: ¿Cómo puedo calcular el tamaño del lote para 200 dólares? (Sería útil saber el coste de un lote de tamaño mínimo. En este caso, el lote de tamaño mínimo es de 0,01).

PREGUNTA: ¿La fórmula de cálculo del tamaño del lote es la misma para todos los pares de divisas?

Muchas gracias de antemano.

 

El problema no está totalmente definido. Si dices que quieres arriesgar un 2% entonces tienes que fijar una de las variables: el nivel de stop loss o el volumen de la operación. Ya que estás preguntando sobre el cálculo del tamaño del lote eso significa que no lo quieres fijo pero eso requiere que te intereses en los pips de stop loss aunque digas que no lo haces. Si no tienes un stop loss entonces arriesgar el 2% significa tomar un tamaño de lote fijo, por ejemplo 1.0, y esperar hasta que tus pérdidas actuales alcancen el 2% del margen inicial. No es necesario calcular el tamaño del lote aquí como ves.


Una vez que el nivel de stop loss entra en la vista, el cálculo es simple:


double tradeVolume = AccountFreeMargin() * Risk/100 / ( StopLossPoints * MarketInfo( Symbol(), MODE_TICKVALUE ) );


Es decir, dado un nivel de stop loss para cualquier operación en particular, siempre tendrá el porcentaje especificado de su margen inicial perdido si se toma el stop loss.


También querrá normalizar el valor resultante por MODE_LOTSTEP y limitarlo con MODE_MINLOT y MODE_MAXLOT.

 
bstone wrote >>

El problema no está totalmente definido. Si dices que quieres arriesgar un 2% entonces tienes que fijar una de las variables: el nivel de stop loss o el volumen de la operación. Como estás preguntando por el cálculo del tamaño del lote, eso significa que no lo quieres fijo, pero eso requiere que te intereses por los pips de stop loss aunque digas que no lo tienes. Si no tienes un stop loss entonces arriesgar el 2% significa tomar un tamaño de lote fijo, por ejemplo 1.0, y esperar hasta que tus pérdidas actuales alcancen el 2% del margen inicial. No es necesario calcular el tamaño del lote aquí como ves.


Una vez que el nivel de stop loss entra en la vista, el cálculo es simple:

double tradeVolume = AccountFreeMargin() * Risk/100 / ( StopLossPoints * MarketInfo( Symbol(), MODE_TICKVALUE ) );


Es decir, dado un nivel de stop loss para cualquier operación en particular, siempre tendrá el porcentaje especificado de su margen inicial perdido si se toma el stop loss.

También querrá normalizar el valor resultante mediante MODE_LOTSTEP y limitarlo con MODE_MINLOT y MODE_MAXLOT.

Esto produce una respuesta de 6,66 en una minicuenta. ¿Le parece correcto?

double risk3 = 2.0;
stopLossPips = 30;
double orderLotSize3 = AccountFreeMargin() * risk3/100 / ( stopLossPips * MarketInfo( Symbol(), MODE_TICKVALUE ) );
orderLotSize3 = orderLotSize3 - MathMod( orderLotSize3, 2*MarketInfo( Symbol(), MODE_LOTSTEP ) );
orderLotSize3 = NormalizeDouble(orderLotSize3, 2);

 

Sólo si MODE_TICKVALUE es 1,0, lo que parece raro (pero depende de las propiedades de la minicuenta). ¿Cuál es el MODE_TICKVALUE para el instrumento en cuestión y su minicuenta? Para EURUSD, una cuenta estándar, y un apalancamiento de 1:100 es de 10 dólares dando un volumen de negociación de 0,66 lotes para el riesgo del 2% y el stop de 30 pp.

 
Hello.

int    init ()
{

double ad.Volume                                                                                                ;

string as.Symbol            = "EURUSD"                                                                          ;

double ad.LotStep           = MarketInfo ( as.Symbol , MODE_LOTSTEP        )                                    ;
double ad.MinimalVolume     = MarketInfo ( as.Symbol , MODE_MINLOT         )                                    ;
double ad.NominalLot        = MarketInfo ( as.Symbol , MODE_LOTSIZE        )                                    ;
double ad.NominalMargin     = MarketInfo ( as.Symbol , MODE_MARGINREQUIRED )                                    ;
double ad.QuoteAsk          = MarketInfo ( as.Symbol , MODE_ASK            )                                    ;
double ad.QuoteBid          = MarketInfo ( as.Symbol , MODE_BID            )                                    ;

double ad.EquityQuant       = 0.01                                                                              ;
double ad.MarginLimit       = AccountEquity () * ad.EquityQuant                                                 ;
double ad.VolumeLimit       = ad.MarginLimit   / ad.NominalMargin                                               ;

if   ( ad.VolumeLimit       < ad.MinimalVolume )
       ad.Volume            = 0                                                                                 ;
else { int ai.Steps         = MathFloor ( ( ad.VolumeLimit - ad.MinimalVolume ) / ad.LotStep )                  ;
       ad.Volume            = ad.MinimalVolume + ad.LotStep * ai.Steps                                          ; }

double ad.Leverage          = AccountLeverage ()                                                                ;
double ad.RealLeverage      = ad.Leverage                                                                       ;

double ad.MarginBuy.1       = ad.QuoteAsk * ad.Volume * ad.NominalLot / ad.RealLeverage                         ;
double ad.MarginSell.1      = ad.QuoteBid * ad.Volume * ad.NominalLot / ad.RealLeverage                         ;

double ad.MarginBuy.2       = AccountFreeMargin () - AccountFreeMarginCheck ( as.Symbol , OP_BUY  , ad.Volume ) ;
double ad.MarginSell.2      = AccountFreeMargin () - AccountFreeMarginCheck ( as.Symbol , OP_SELL , ad.Volume ) ;

Alert ( "ad.MarginSell.2    = " , ad.MarginSell.2    , " " , AccountCurrency ()                               ) ;
Alert ( "ad.MarginBuy.2     = " , ad.MarginBuy.2     , " " , AccountCurrency ()                               ) ;
Alert ( "ad.MarginSell.1    = " , ad.MarginSell.1    , " " , AccountCurrency ()                               ) ;
Alert ( "ad.MarginBuy.1     = " , ad.MarginBuy.1     , " " , AccountCurrency ()                               ) ;
Alert ( "ad.Volume          = " , ad.Volume          , " " , "lots"                                           ) ;
Alert ( "Output :"                                                                                            ) ;
Alert ( " "                                                                                                   ) ;
Alert ( "ai.Steps           = " , ai.Steps                                                                    ) ;
Alert ( "ad.LotStep         = " , ad.LotStep         , " " , "lots"                                           ) ;
Alert ( "ad.MinimalVolume   = " , ad.MinimalVolume   , " " , "lots"                                           ) ;
Alert ( "ad.VolumeLimit     = " , ad.VolumeLimit     , " " , "lots"                                           ) ;
Alert ( "ad.MarginLimit     = " , ad.MarginLimit     , " " , AccountCurrency ()                               ) ;
Alert ( "ad.NominalMargin   = " , ad.NominalMargin   , " " , AccountCurrency ()                               ) ;
Alert ( "ad.RealLeverage    = " , ad.RealLeverage                                                             ) ;
Alert ( "ad.NominalLot      = " , ad.NominalLot      , " " , StringSubstr ( as.Symbol , 0 , 3 )               ) ;
Alert ( "Processing :"                                                                                        ) ;
Alert ( " "                                                                                                   ) ;
Alert ( "ad.EquityQuant     = " , ad.EquityQuant                                                              ) ;
Alert ( "AccountEquity   () = " , AccountEquity   () , " " , AccountCurrency ()                               ) ;
Alert ( "as.Symbol          = " , as.Symbol                                                                   ) ;
Alert ( "Input :"                                                                                             ) ;
Alert ( " "                                                                                                   ) ;
Alert ( "AccountCurrency () = " , AccountCurrency ()                                                          ) ;
}
Best regards,
Ais.
 
Important.
1. Calculation of the "ad.Margin****.1" is correct for "***USD" symbols if USD is account currency.
2. Calculation of the "ad.Margin****.2" is more universal but some symbols may have miscounts.
3. Real leverage and "AccountLeverage ()" may differ.
4. Real leverage calculation formula depends on forex symbol parsing.
Example.
...

//<method 24>
int    air.Ticker.Compute.4

 (//<0>

){//<24>

if      ( avi.Ticker.Conversion      ==   ac.Direct      )
        { avi.Ticker.ConversionDigits =         avi.Ticker.QuoteDigits                                                 ;
          avd.Ticker.ConversionAsk    =         avd.Ticker.QuoteAsk                                                    ;
          avd.Ticker.ConversionBid    =         avd.Ticker.QuoteBid                                                    ;
          avd.Ticker.RealLeverage     =         avd.Ticker.QuoteAsk * avd.Ticker.NominalLot / avd.Ticker.NominalMargin ; }

else if ( avi.Ticker.Conversion      ==   ac.DirectCross )
        { avi.Ticker.ConversionDigits =         MarketInfo ( avs.Ticker.ConversionSymbol    , MODE_DIGITS )            ;
          avd.Ticker.ConversionAsk    =         MarketInfo ( avs.Ticker.ConversionSymbol    , MODE_ASK    )            ;
          avd.Ticker.ConversionBid    =         MarketInfo ( avs.Ticker.ConversionSymbol    , MODE_BID    )            ;
          avd.Ticker.RealLeverage     = ( avd.Ticker.ConversionAsk + avd.Ticker.ConversionBid ) / 2
                                        * avd.Ticker.NominalLot    / avd.Ticker.NominalMargin                          ; }

else if ( avi.Ticker.Conversion      ==   ac.Inverse     )
        { avi.Ticker.ConversionDigits =   8   - avi.Ticker.QuoteDigits                                                 ;
          avd.Ticker.ConversionAsk    =   1.0 / avd.Ticker.QuoteBid                                                    ;
          avd.Ticker.ConversionBid    =   1.0 / avd.Ticker.QuoteAsk                                                    ;
          avd.Ticker.RealLeverage     =                              avd.Ticker.NominalLot  / avd.Ticker.NominalMargin ; }

else    { avi.Ticker.ConversionDigits =   8   - MarketInfo ( avs.Ticker.ConversionSymbol    , MODE_DIGITS )            ;
          avd.Ticker.ConversionAsk    =   1.0 / MarketInfo ( avs.Ticker.ConversionSymbol    , MODE_BID    )            ;
          avd.Ticker.ConversionBid    =   1.0 / MarketInfo ( avs.Ticker.ConversionSymbol    , MODE_ASK    )            ;
          avd.Ticker.RealLeverage     = ( avd.Ticker.ConversionAsk + avd.Ticker.ConversionBid ) / 2
                                        * avd.Ticker.NominalLot    / avd.Ticker.NominalMargin                          ; }

}//</method 24>

... 
Best regards,
Ais.
 
Hello.
Another method of operation volume computing is in https://www.mql5.com/ru/forum/111267.
Best regards,
Ais.
 

Creo que el método más fácil para obtener la cantidad de margen necesaria para un lote es


MarketInfo(Symbol(),MODE_MARGINREQUIRED);


Normalmente utilizo la siguiente fórmula para calcular los lotes:

double OneLotMargin = MarketInfo(Symbol(),MODE_MARGINREQUIRED);
double FreeMargin = AccountFreeMargin();
double lotMM = FreeMargin/OneLotMargin*Risk/100;
double LotStep = MarketInfo(Symbol(),MODE_LOTSTEP);
lotMM = NormalizeDouble(lotMM/LotStep,0)*LotStep;

Sin embargo, has preguntado cómo calcular la cantidad de lotes que utilizan una cantidad fija de margen, por ejemplo 200$, en este caso la fórmula de foolowing debe ser cambiada:

double OneLotMargin = MarketInfo(Symbol(),MODE_MARGINREQUIRED);
double MarginAmount = 200; //this means we want to use 200$ for trade
double lotMM = MarginAmount/OneLotMargin;
double LotStep = MarketInfo(Symbol(),MODE_LOTSTEP);
lotMM = NormalizeDouble(lotMM/LotStep,0)*LotStep;

 
Hello.
Note, that "minimal lot" and "lot step" may differ.
For example, "minimal lot" may be 0.10, "lot step" may be 0.01.
In this case, simple calculation methods may produce incorrect operation volume, for example, 0.05.
Best regards,
Ais.
 
Ais wrote >>
Hello.
Another method of operation volume computing is in 'Ищу функцию вычисления размера лота.'.
Best regards,
Ais.

Ais
wrote
>>
Hello.
Note, that "minimal lot" and "lot step" may differ.
For example, "minimal lot" may be 0.10, "lot step" may be 0.01.
In this case, simple calculation methods may produce incorrect operation volume, for example, 0.05.
Best regards,
Ais.

Estoy usando el código que mencionaste en 'Ищу функцию вычисления размера лота.'. Gracias.

TENGO UNA PREGUNTA SOBRE ESTE CÓDIGO: ¿Siempre produce un tamaño de lote con número par (como 6,66 y no 6,67).

Es bueno si lo hace. Pero no entiendo por qué lo hace.

El código adjunto está en formato de archivo Script, así que podría pegar el código en un nuevo script y ejecutarlo inmediatamente.

Archivos adjuntos:
 
Hello.
Correct code must be able to produce any valid result.
Examples.




Best regards,
Ais.