Download MetaTrader 5

How do I calculate lot size?

To add comments, please log in or register
Speed up MQL5 Cloud Network. Install Strategy Tester Agent!
John Chaffins
186
John Chaffins 2008.09.22 22:31 

Let's say my mini account has margin of $10,000, and I want to risk 2% on the next trade (that is, simply use $200 to buy <some amount> of contracts).

[I realize this is a limited view of "risk". I'm not interested in stopLoss pips, or profit targets, or whatever.]

Using MetaTrader, I get the following mini account information from my broker:

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

QUESTION: How do I calculate the lot size for $200? (It would be useful to know the cost of a minimum size lot. In this case, the minimum size lot is .01).

QUESTION: Is the lot size calculation formula the same for all currency pairs?

Thank you very much in advance.

Roman Kramar
742
Roman Kramar 2008.09.22 22:43  

The problem is not fully defined. If you say you want to risk 2% then you have to fix one of the variables: the stop loss level or the trade volume. Since you're asking about calculating the lot size that means you don't want it fixed but that requires you to become interested in stop loss pips even though you say you're not. If you don't have a stop loss then risking 2% means taking a fixed lot size, e.g. 1.0, and waiting till your current losses reach 2% of the initial margin. You don't need to calculate the lot size here as you see.


Once stop loss level enters the view, the calculation is simple:


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


That is, given a stop loss level for any particular trade, you will always have the specified percentage of your initial margin lost if the stop loss is taken.


You will also want to normalize the resulting value by MODE_LOTSTEP and cap it with MODE_MINLOT and MODE_MAXLOT.

John Chaffins
186
John Chaffins 2008.09.22 23:27  
bstone wrote >>

The problem is not fully defined. If you say you want to risk 2% then you have to fix one of the variables: the stop loss level or the trade volume. Since you're asking about calculating the lot size that means you don't want it fixed but that requires you to become interested in stop loss pips even though you say you're not. If you don't have a stop loss then risking 2% means taking a fixed lot size, e.g. 1.0, and waiting till your current losses reach 2% of the initial margin. You don't need to calculate the lot size here as you see.


Once stop loss level enters the view, the calculation is simple:

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


That is, given a stop loss level for any particular trade, you will always have the specified percentage of your initial margin lost if the stop loss is taken.

You will also want to normalize the resulting value by MODE_LOTSTEP and cap it with MODE_MINLOT and MODE_MAXLOT.

This produces an answer of 6.66 on a mini-account. Does that seem about right?

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);

Roman Kramar
742
Roman Kramar 2008.09.22 23:44  

Only If MODE_TICKVALUE is 1.0 which looks weird (but depends on the properties of the mini-account). What is MODE_TICKVALUE for the instrument in question and your mini-account? For EURUSD, a standard account, and a 1:100 leverage it's $10 giving a trading volume of 0.66 lots for the 2% risk the and the 30 pp stop.

Airat Safin
1300
Airat Safin 2008.09.23 13:21  
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.
Airat Safin
1300
Airat Safin 2008.09.23 21:20  
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.
Airat Safin
1300
Airat Safin 2008.09.24 15:28  
Hello.
Another method of operation volume computing is in https://www.mql5.com/ru/forum/111267.
Best regards,
Ais.
scalony
64
scalony 2008.09.24 18:14  

I think the easiest method to get amount of margin needed for one lot is


MarketInfo(Symbol(),MODE_MARGINREQUIRED);


I usually use following formula to calculate lots:

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;

However you asked about how to calculate amount of lots that use fixed amount of margin for example 200$ in this case the foolowing formula should be changed to:

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;

Airat Safin
1300
Airat Safin 2008.09.24 18:54  
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.
John Chaffins
186
John Chaffins 2008.09.25 01:06  
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.

I'm using the code you mentioned at 'Ищу функцию вычисления размера лота.'. Thank you.

I HAVE ONE QUESTION ABOUT THIS CODE: Does it always produce and even numbered lotsize (such as 6.66 and not 6.67).

That's good if it does. I just don't understand why it does.

The attached code is in a Script file format, so you could paste the code into a new script and run it immediately.

Airat Safin
1300
Airat Safin 2008.09.25 08:07  
Hello.
Correct code must be able to produce any valid result.
Examples.




Best regards,
Ais.
123
To add comments, please log in or register