Como calcular o tamanho do lote?

 

Digamos que minha mini conta tem margem de $10.000, e eu quero arriscar 2% na próxima negociação (ou seja, simplesmente usar $200 para comprar <algum montante> de contratos).

[Percebo que esta é uma visão limitada do "risco". Não estou interessado em stopLoss pips, ou metas de lucro, ou o que quer que seja].

Usando MetaTrader, recebo as seguintes informações de mini-conta de meu corretor:

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

PERGUNTA: Como calcular o tamanho do lote para $200? (Seria útil saber o custo de um lote de tamanho mínimo. Neste caso, o tamanho mínimo do lote é .01).

PERGUNTA: A fórmula de cálculo do tamanho do lote é a mesma para todos os pares de moedas?

Muito obrigado de antemão.

 

O problema não está totalmente definido. Se você diz que quer arriscar 2%, então você tem que corrigir uma das variáveis: o nível de stop loss ou o volume de comércio. Já que você está perguntando sobre o cálculo do tamanho do lote, isso significa que você não quer que ele seja consertado, mas isso exige que você se interesse em stop loss pips, mesmo que você diga que não está. Se você não tiver um stop loss, então arriscar 2% significa tomar um tamanho de lote fixo, por exemplo 1,0, e esperar até que suas perdas atuais atinjam 2% da margem inicial. Você não precisa calcular o tamanho do lote aqui, como você vê.


Uma vez que o nível de stop loss entra na visão, o cálculo é simples:


Duplo volume de comércio = AccountFreeMargin() * Risk/100 / ( StopLossPoints * MarketInfo( Symbol(), MODE_TICKVALUE ) );


Ou seja, dado um nível de stop loss para qualquer comércio em particular, você sempre terá a porcentagem especificada de sua margem inicial perdida se o stop loss for tomado.


Você também vai querer normalizar o valor resultante por MODE_LOTSTEP e limitá-lo com MODE_MINLOT e MODE_MAXLOT.

 
bstone wrote >>

O problema não está totalmente definido. Se você diz que quer arriscar 2%, então você tem que corrigir uma das variáveis: o nível de stop loss ou o volume de comércio. Já que você está perguntando sobre o cálculo do tamanho do lote, isso significa que você não quer que ele seja consertado, mas isso exige que você se interesse em stop loss pips, mesmo que você diga que não está. Se você não tiver um stop loss, então arriscar 2% significa tomar um tamanho de lote fixo, por exemplo 1,0, e esperar até que suas perdas atuais atinjam 2% da margem inicial. Você não precisa calcular o tamanho do lote aqui, como você vê.


Uma vez que o nível de stop loss entra na visão, o cálculo é simples:

volume de comércio duplo = AccountFreeMargin() * Risk/100 / ( StopLossPoints * MarketInfo( Symbol(), MODE_TICKVALUE ) );


Ou seja, dado um nível de stop loss para qualquer negociação específica, você sempre terá a porcentagem especificada de sua margem inicial perdida se o stop loss for tomado.

Você também desejará normalizar o valor resultante por MODE_LOTSTEP e limitá-lo com MODE_MINLOT e MODE_MAXLOT.

Isto produz uma resposta de 6,66 em uma mini-conta. Isso parece correto?

risco duplo3 = 2,0;
stopLossPips = 30;
duplo pedidoLotSize3 = AccountFreeMargin() * risco3/100 / ( stopLossPips * MarketInfo( Symbol(), MODE_TICKVALUE ) );
orderLotSize3 = orderLotSize3 - MathMod( orderLotSize3, 2*MarketInfo( Symbol(), MODE_LOTSTEP ) );
orderLotSize3 = NormalizeDouble(orderLotSize3, 2);

 

Somente se MODE_TICKVALUE for 1.0 o que parece estranho (mas depende das propriedades da mini-conta). O que é MODE_TICKVALUE para o instrumento em questão e sua mini-conta? Para EURUSD, uma conta padrão e uma alavancagem de 1:100 é de $10 dando um volume de negociação de 0,66 lotes para o risco de 2% o e a parada 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.
 

Acho que o método mais fácil para obter a quantidade de margem necessária para um lote é


MarketInfo(Symbol(),MODE_MARGINREQUIRED);


Eu normalmente uso a seguinte fórmula para calcular 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;

No entanto, você perguntou como calcular a quantidade de lotes que utilizam um montante fixo de margem, por exemplo, 200$ neste caso, a fórmula de tolice deve ser mudada para:

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.

Estou usando o código que você mencionou em 'Ищу функцию вычисления размера лота.'. Obrigado.

TENHO UMA PERGUNTA SOBRE ESTE CÓDIGO: Ele sempre produz e até numera os lotes (como 6,66 e não 6,67).

Isso é bom, se for o caso. Eu simplesmente não entendo porque ele faz.

O código anexo está em um formato de arquivo Script, assim você poderia colar o código em um novo script e executá-lo imediatamente.

Arquivos anexados:
 
Hello.
Correct code must be able to produce any valid result.
Examples.




Best regards,
Ais.