How to calculate a position size correctly

 

Hello

I have the following code:

double calcPositionSize() {
        // calculate position size based on account balance, pcRisk, price, symbol and stoploss.
        // For size, equity is account balance adjusted to take into account the open positions you have already.
        //
        size = AccountInfoDouble(ACCOUNT_EQUITY);       
        Print("size: ", size);
        riskMoney = size * tradePC / 100;
        Print("riskMoney: ", riskMoney);
        double unitCost = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
        Print("unitCost: ", unitCost);
        double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
        Print("tickSize: ", NormalizeDouble(tickSize,8));
        if((SL != 0) 
        && (unitCost != 0) 
        && (tickSize != 0)) {
                positionSize = riskMoney / (SL * unitCost / tickSize);
        }

        return(positionSize);
}

When this function is called from within my EA, I can alert ERRORs (error: 4756) because the lot size is basically too small.  I'm running this in Strategy Tester with 1:100 leverage and an initial margin of $10000 on GBPUSD and alpari as my broker (who run a 5 _digit).  My risk exposure is 2%, stop loss (SL) of 20 pips.

I see this come up in the tester:

2013.05.02 00:07:41     2011.07.18 16:15:15   tickSize: 1e-005.0
2013.05.02 00:07:41     2011.07.18 16:15:15   unitCost: 1.0
2013.05.02 00:07:41     2011.07.18 16:15:15   riskMoney: 200.0
2013.05.02 00:07:41     2011.07.18 16:15:15   size: 10000.0
2013.05.02 00:07:41     2011.07.18 16:15:15   SL set to: 20 pips (1.60225)

It's tickSize which is breaking the calculation, but I've tried to NormalizeDouble to get a non-exponential number for this and it's still outputting 1e-005.0.  1 x 10e-5.0? OK that's 0.00001 which would be in line with the broker's digits setup.

So if I'm right, my calculation by hand is:

positionSize = riskMoney / (SL * unitCost / tickSize);

0.0001 = 200 / (20 * 1 / 0.00001)

Right, so I've been trying to open a position of lot size 0.0001 lots.  And as my account is a mini account, that'll be 0.0001 mini lots which is basically not worth trading obviously.

But is the best thing to do to find out what size in units 1 lot is and adjust the calculation (i.e. multiply up the position size for mini/micro accounts) or to go up to a normal sized account and try and open a position of 0.0001 normal lots (10 units)?  Even that sounds small.

Also, why is NormalizeDouble not returning 0.00001 instead of the exponential form?

Thanks - sorry if I've missed an obvious point here.

Documentation on MQL5: Standard Constants, Enumerations and Structures / Environment State / Symbol Properties
Documentation on MQL5: Standard Constants, Enumerations and Structures / Environment State / Symbol Properties
  • www.mql5.com
Standard Constants, Enumerations and Structures / Environment State / Symbol Properties - Documentation on MQL5
 
strontiumDog:

Hello

I have the following code:

When this function is called from within my EA, I can alert ERRORs (error: 4756) because the lot size is basically too small.  I'm running this in Strategy Tester with 1:100 leverage and an initial margin of $10000 on GBPUSD and alpari as my broker (who run a 5 _digit).  My risk exposure is 2%, stop loss (SL) of 20 pips.

....

Hi, I think you must adjust your code and decide what to do when your calculation figure out a lot lower than 0.01.

For instance (just a suggestion):

...

if (positionSize<0.001) positionSize=0; // return 0 if lot is to small and is better don't send an order
else if (positionSize<0.01) positionSize=0.01; // return 0.01 if lot is smaller than this but ok to send an order

return(positionSize);
}

Note that, in this example, you have to check the return positionSize to don't send any order if this value is zero. 

About NormalizeDouble, looks like just a debug information format, but the number is ok in memory.

 
strontiumDog:

Hello

I have the following code:

When this function is called from within my EA, I can alert ERRORs (error: 4756) because the lot size is basically too small.  I'm running this in Strategy Tester with 1:100 leverage and an initial margin of $10000 on GBPUSD and alpari as my broker (who run a 5 _digit).  My risk exposure is 2%, stop loss (SL) of 20 pips.

I see this come up in the tester:

It's tickSize which is breaking the calculation, but I've tried to NormalizeDouble to get a non-exponential number for this and it's still outputting 1e-005.0.  1 x 10e-5.0? OK that's 0.00001 which would be in line with the broker's digits setup.

So if I'm right, my calculation by hand is:

0.0001 = 200 / (20 * 1 / 0.00001)

Right, so I've been trying to open a position of lot size 0.0001 lots.  And as my account is a mini account, that'll be 0.0001 mini lots which is basically not worth trading obviously.

You need to ensure your position size is less than or equal to SYMBOL_VOLUME_MAX  greater than or equal to SYMBOL_VOLUME_MIN  and a multiple of SYMBOL_VOLUME_STEP

Also I think this calculation is wrong . . .

positionSize = riskMoney / (SL * unitCost / tickSize);

 what is the relevance of SYMBOL_TRADE_TICK_SIZE  in your calculation ?

Shouldn't you be using . . .

positionSize = ( riskMoney / SL ) / unitCost ;

 so position size = (200 / 20) / 1  =  10 / 1 = 10 lots ?

 
strontiumDog:

Hello

I have the following code:

When this function is called from within my EA, I can alert ERRORs (error: 4756) because the lot size is basically too small.  I'm running this in Strategy Tester with 1:100 leverage and an initial margin of $10000 on GBPUSD and alpari as my broker (who run a 5 _digit).  My risk exposure is 2%, stop loss (SL) of 20 pips.

I see this come up in the tester:

It's tickSize which is breaking the calculation, but I've tried to NormalizeDouble to get a non-exponential number for this and it's still outputting 1e-005.0.  1 x 10e-5.0? OK that's 0.00001 which would be in line with the broker's digits setup.

So if I'm right, my calculation by hand is:

0.0001 = 200 / (20 * 1 / 0.00001)

Right, so I've been trying to open a position of lot size 0.0001 lots.  And as my account is a mini account, that'll be 0.0001 mini lots which is basically not worth trading obviously.

But is the best thing to do to find out what size in units 1 lot is and adjust the calculation (i.e. multiply up the position size for mini/micro accounts) or to go up to a normal sized account and try and open a position of 0.0001 normal lots (10 units)?  Even that sounds small.

Also, why is NormalizeDouble not returning 0.00001 instead of the exponential form?

Thanks - sorry if I've missed an obvious point here.

The problem here is your are mixing pips and points, the formula RaptorUk give you is right BUT you have to use pips or points and not pip for SL, and point for unitCost :

General formula is :

            LOTS            = risque (%) * Capital / (SL (in pips) * pipvalue)  

                                                     or

            LOTS            = risque (%) * Capital / (SL (in points) * pointvalue)  

In your example, you want to risk 200$ and have a SL of 20 pips (0.0020), this is 10$ par pip.

so you have to find the volume (lots) to obtain this pipvalue, so the results will be 1 standard lot.

P.S: 0.00001 or 1e-005 is exactly the same, this only the output format used by print. You can control the output format using PrintFormat.

 
figurelli:

Hi, I think you must adjust your code and decide what to do when your calculation figure out a lot lower than 0.01.

For instance (just a suggestion):

Note that, in this example, you have to check the return positionSize to don't send any order if this value is zero. 

About NormalizeDouble, looks like just a debug information format, but the number is ok in memory.

angevoyageur:

The problem here is your are mixing pips and points, the formula RaptorUk give you is right BUT you have to use pips or points and not pip for SL, and point for unitCost :

General formula is :

            LOTS            = risque (%) * Capital / (SL (in pips) * pipvalue)  

                                                     or

            LOTS            = risque (%) * Capital / (SL (in points) * pointvalue)  

In your example, you want to risk 200$ and have a SL of 20 pips (0.0020), this is 10$ par pip.

so you have to find the volume (lots) to obtain this pipvalue, so the results will be 1 standard lot.

P.S: 0.00001 or 1e-005 is exactly the same, this only the output format used by print. You can control the output format using PrintFormat.

RaptorUK:

You need to ensure your position size is less than or equal to SYMBOL_VOLUME_MAX  greater than or equal to SYMBOL_VOLUME_MIN  and a multiple of SYMBOL_VOLUME_STEP

Also I think this calculation is wrong . . .

 what is the relevance of SYMBOL_TRADE_TICK_SIZE  in your calculation ?

Shouldn't you be using . . .

 so position size = (200 / 20) / 1  =  10 / 1 = 10 lots ?

Chaps thanks very much for the swift replies.  Angevoyageur thanks for the link to PrintFormat.  That sorts the number format on output.

Figurelli, thanks for the suggestion, I did intend to not trade if the lot size is too small.

RaptorUK, the formula I got was derived from this free positionsizecalculator indicator: http://www.earnforex.com/metatrader-indicators/Position-Size-Calculator.  I didn't test it as I was just intending on just using the calculation part and not use it as an indicator in my EA.  The last function in it is:

void CalculateRiskAndPositionSize()
{
   if (!UseMoneyInsteadOfPercentage) RiskMoney = Size * Risk / 100;
   else RiskMoney = MoneyRisk;
   ObjectSetString(0, "RiskMoney", OBJPROP_TEXT, "Risk, money:  " + DoubleToString(RiskMoney, 2));

   double UnitCost = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double TickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   if ((StopLoss != 0) && (UnitCost != 0) && (TickSize != 0)) PositionSize = RiskMoney / (StopLoss * UnitCost / TickSize);
   
   ObjectSetString(0, "PositionSize", OBJPROP_TEXT, "Pos. Size:    " + DoubleToString(PositionSize, 2));
}
// Copyright © 2012-2013, Andriy Moraru

https://www.mql5.com/en/docs/constants/environment_state/marketinfoconstants suggests these are mql5-provided internals for such calculations.  I have to say that during my research last night on finding code in mql5 for this calculation I remarked at how little forthright code there was easily accessible.  I was expecting one steadfast, always-top-in-google metaquotes article which pops up with a 101 of how it's done, but "mql5 calculate position size" didn't exactly spring up anything really useful. 

Angevoyageur, the SYMBOL_TRADE_TICK_VALUE mql5 documentation is really sparse, can you pass me a link as to get more information on it and all the other symbol properties if you have one please?  It'd be useful to get more info.

Just one other question,

positionSize = ( riskMoney / SL ) / unitCost ;

and

LOTS            = risque (%) * Capital / (SL (in pips) * pipvalue)  

are different as once (risk*capital) is divided by the SL in pips, RaptorUK then further divides by unitcost but Angevoyageur multiplies by pipvalue.

As Angevoyageur says RaptorUK's formula is correct, can I assume that these are the same? Irrespective, the unitcost calc from the symbol property SYMBOL_TRADE_TICK_VALUE returns '1' for me in this case, but from Angevoyageur's post looks like that is pipvalue or pointvalue.  Do I understand that I need do other calculations to derive pipvalue prior to then multiplying it by ($200/20) in this case?

Thanks

 

strontiumDog:

...

Angevoyageur, the SYMBOL_TRADE_TICK_VALUE mql5 documentation is really sparse, can you pass me a link as to get more information on it and all the other symbol properties if you have one please?  It'd be useful to get more info.

This article would probably help you ;-)


Just one other question,

and

are different as once (risk*capital) is divided by the SL in pips, RaptorUK then further divides by unitcost but Angevoyageur multiplies by pipvalue.

As Angevoyageur says RaptorUK's formula is correct, can I assume that these are the same? 

Yes, there are the same, provided that you use same units for SL and unitCost. (Both pips, both points but not mixed).

a = (b / c) / d is equivalent  to a = b / (c * d)

Irrespective, the unitcost calc from the symbol property SYMBOL_TRADE_TICK_VALUE returns '1' for me in this case, but from Angevoyageur's post looks like that is pipvalue or pointvalue.  Do I understand that I need do other calculations to derive pipvalue prior to then multiplying it by ($200/20) in this case?

As you have a 5 digits broker, 1 point is 0.00001 which give you a value of 1$ for EURUSD for 1 point (for 1 standard lot). If you use pip 0.0001 for your SL, then you have to convert your pips to points (20 => 200 in this case) or convert your unitCost from points to pips (1 => 10 in this case).


Thanks

 
strontiumDog:

Chaps thanks very much for the swift replies.  Angevoyageur thanks for the link to PrintFormat.  That sorts the number format on output.

Figurelli, thanks for the suggestion, I did intend to not trade if the lot size is too small.

RaptorUK, the formula I got was derived from this free positionsizecalculator indicator: http://www.earnforex.com/metatrader-indicators/Position-Size-Calculator.  I didn't test it as I was just intending on just using the calculation part and not use it as an indicator in my EA.  The last function in it is:


OK,  I had a look at the page you gave a link to,  in their code Stoploss is a price difference between the entry price and the StopLoss price, hence the reason that they divide by ticksize,  if your SL is a number of points you don't need to do the division.  A word of advice,  NEVER  use anyone else's code without first fully understanding it . . .  and I mean nobody's code.

 

strontiumDog:


As Angevoyageur says RaptorUK's formula is correct, can I assume that these are the same? Irrespective, the unitcost calc from the symbol property SYMBOL_TRADE_TICK_VALUE returns '1' for me in this case, but from Angevoyageur's post looks like that is pipvalue or pointvalue.  Do I understand that I need do other calculations to derive pipvalue prior to then multiplying it by ($200/20) in this case?

Thanks

 

Our equations are the same just laid out differently . . .   multiplying by  1/x is the same as dividing by x 

 

RaptorUK thanks for the advice - I'm treading very carefully through this subject and naturally have no intention of putting anything even into forward test until I understand every part in depth (sometimes I put code in first based on some assumptions and work back from there).  At this point I'm really just hacking around with stuff, and with such a large subject as this, I'm taking my time.  I missed the parenthesis placement in yours and Angevoyageur's posts. Thanks to both of you - Angevoyageur also for the link.

 
strontiumDog:

RaptorUK thanks for the advice - I'm treading very carefully through this subject and naturally have no intention of putting anything even into forward test until I understand every part in depth (sometimes I put code in first based on some assumptions and work back from there).  At this point I'm really just hacking around with stuff, and with such a large subject as this, I'm taking my time.  I missed the parenthesis placement in yours and Angevoyageur's posts. Thanks to both of you - Angevoyageur also for the link.

You are welcome.
 

Just one last thing, now I've done some more reading on the subject, including rereading parts of this thread.  I now understand the unitCost is coming back as 1 because my 5 digit broker is giving me pip price for EURUSD in pipettes and I have a USD account.  So because of this, 1 pip is valued at $10 but 1 pipette at $1 (hence 1).

OK.  so in order to use just one formula which covers all possible symbols (from Clint's post on this http://forums.babypips.com/newbie-island/40993-question-calculating-position-sizes-article.html and that above), I need to calculate the pip value each time I need a lot size.  Now from further reading, this in many cases (where USD is not the cross currency of the pair) varies with symbol price, and I'm to 'rely on my trading platform' for the value.

Looks like SYMBOL_TRADE_TICK_SIZE is what was being used by the chap who wrote the indicator I referred to above, but I'm interested to know your thoughts on how you would reliably arrive at this pip value in mql5 for the lot size calculation for an EA which was to be able to calculate them irrespective of symbol it was dragged onto and account currency (although as you know mine is in USD).

Cheers for your help.

A question from "Calculating Position Sizes" article
  • A Fistful of Pips
  • forums.babypips.com
I have a question about the below from the baby pips school... I understand that we need to figure out how many pips the trader can stand before they get out, but I guess I am not connecting all the dots.. So if you want to only risk 1% of your $5000 account, you put up $50. Simple. But then you want to figure out the value of this in...
 
strontiumDog:

Just one last thing, now I've done some more reading on the subject, including rereading parts of this thread.  I now understand the unitCost is coming back as 1 because my 5 digit broker is giving me pip price for EURUSD in pipettes and I have a USD account.  So because of this, 1 pip is valued at $10 but 1 pipette at $1 (hence 1).

OK.  so in order to use just one formula which covers all possible symbols (from Clint's post on this http://forums.babypips.com/newbie-island/40993-question-calculating-position-sizes-article.html and that above), I need to calculate the pip value each time I need a lot size.  Now from further reading, this in many cases (where USD is not the cross currency of the pair) varies with symbol price, and I'm to 'rely on my trading platform' for the value.

Looks like SYMBOL_TRADE_TICK_SIZE is what was being used by the chap who wrote the indicator I referred to above, but I'm interested to know your thoughts on how you would reliably arrive at this pip value in mql5 for the lot size calculation for an EA which was to be able to calculate them irrespective of symbol it was dragged onto and account currency (although as you know mine is in USD).

Already answered above . . .

RaptorUK:

OK,  I had a look at the page you gave a link to,  in their code Stoploss is a price difference between the entry price and the StopLoss price, hence the reason that they divide by ticksize,  if your SL is a number of points you don't need to do the division.  A word of advice,  NEVER  use anyone else's code without first fully understanding it . . .  and I mean nobody's code.

 Having said that,  ticksize is, I think, the wrong variable to use to do this,  I think it should really be point ( SYMBOL_POINT ).  For Forex it probably wouldn't cause an issue but for some Indexes it may well give an incorrect calculation.

Reason: