Correct calculation of the lot from the % of the deposit - page 5

 
EverAlex:

Therefore lSL is how many points to SL

Point = 0.00001 (on 5-digit quotes)

dLotStep = 0.01


The formula (lSL*dLotCost*dLotStep))*dLotStep is wrong

It should be something like ( lSL*dLotCost*Point))*dLotStep


You don't have to make anything up. The lot size is different for each brokerage company and you have to adjust it to the right size. Points have nothing to do with it
 
Vinin:

You don't have to invent anything. The lot size is different in each brokerage company and we have to bring it to the right size. The points have nothing to do with it.


In our case, lSL is the drawdown size in points of quotes but not in points of the lot.

I.e. points have nothing to do with it.

So, in the calculation formula we should multiply (what is in brackets) by Point, not by dLotStep.

Another thing is that this is already done at the expense of dLotCost (along with conversion to deposit currency)...

I.e. we're first in the

MathRound(AccountFreeMargin()*lRisk*0.01/(lSL*dLotCost*dLotStep))

Get an integer and then recalculate back to the correct units of the lot by multiplying by dLotStep ?

 
double lotSize(double deposSize=1000.0, string currName="USDCHF", double proc=2.0, int pipsLoss=1000)// функция лота
{  
   //проверка достаточности средств 
   if(deposSize < 
   MarketInfo(currName,MODE_MARGINREQUIRED)*MarketInfo(currName,MODE_MINLOT))
   //для проведения торговли
   {
      Alert("Величина вашего депозита недостаточна \nдля торговли на инструменте\""+currName+"\" \nc минимальнодопустимым лотом");
      return 0.0;
   }
   //проверка, на стоп-аут
   ENUM_ACCOUNT_STOPOUT_MODE stopOutMode=(ENUM_ACCOUNT_STOPOUT_MODE)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE);
   double procUsed;
   if(stopOutMode==ACCOUNT_STOPOUT_MODE_PERCENT)//если стоп-аут в процентах
     {
         if(proc > AccountInfoDouble(ACCOUNT_MARGIN_SO_SO))
           {
               Alert("Потеря выше уровня STOPOUT!\nРасчет лота производиться по величине STOPOUT.");
               procUsed=AccountInfoDouble(ACCOUNT_MARGIN_SO_SO)/100;
               //Print(MarketInfo(currName,MODE_MARGINREQUIRED)," ",procUsed);
               return deposSize/(pipsLoss+procUsed*MarketInfo(currName,MODE_MARGINREQUIRED));               
           }
     }
     //а вот здесь нужна доработка, для платформ, где стоп-аут в пунктах
     //как сказал один наш товарищ "у кого идеи ростут из нужного места".. доделает
     
   double currMove=deposSize*proc/100;// расчет процента от величины депозита
   double lotCount=currMove/(pipsLoss*MarketInfo(currName,MODE_TICKVALUE));//ну а тут и ведеться сам расчет лота

   if(lotCount<MarketInfo(currName,MODE_MINLOT))
   {
      return MarketInfo(currName,MODE_MINLOT);
   }
   if(lotCount>MarketInfo(currName,MODE_MAXLOT))
   {
      return MarketInfo(currName,MODE_MAXLOT);  
   }
   return NormalizeDouble(lotCount,2);
   //return lotCount;
}

There is also an option with a deposit of 3 quid to trade EURUSD and put 30% on the losing side... but this is out of a series of perversions

 
EverAlex:


In terms of the problem lSL is the size of the drawdown in points of quotes, not in points of the lot.

I.e. points have nothing to do with it.

So, in the calculation formula we should multiply (what is in brackets) by Point, not by dLotStep.

Another thing is that this is already done at the expense of dLotCost (along with conversion to deposit currency)...

I.e. we first in

get an integer, and then recalculate back to the correct units of the lot by multiplying by dLotStep ?




Yes
 
Vinin:


The formula is still wrong (for a block of iSL>0).

TICKVALUE gives the price for TICKSIZE.

And lSL is given in POINT points.

POINT does not always coincide with TICKSIZE (see 3-digit pair XAUUSD at Alpari).

So you must convert lSL from POINT to TICKSIZE.

Otherwise, we will obtain a 10 times overestimated lot (that's what I observed on the XAUUSD pair until I added recalculation).

if (lSL>0){

lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL; // TICKSIZE/POINT will give an integer (1 or 10), we can use int type lSL

// here is what it was.

 double dLotCost=MarketInfo(lSymbol,MODE_TICKVALUE);
 dLot=MathRound(AccountFreeMargin()*lRisk*0.01/(lSL*dLotCost*dLotStep))*dLotStep;
}

PS: for TC optimized for many passes (>10mln) all unchangeable parameters of symbol(TICKSIZE, POINT, TICKVALUE, LOTSTEP, MINLOT, MAXLOT etc.) should be assigned to variables in functioninit() and use these variables in calculations.

Including putting value of TickSize/Point into a variable.

 
EverAlex:

The formula is still wrong (for a block of iSL>0).

TICKVALUE gives the price for TICKSIZE.

And lSL is given in POINT points.

POINT does not always coincide with TICKSIZE (see 3-digit pair XAUUSD at Alpari).

So you must convert lSL from POINT to TICKSIZE.

Otherwise, we will obtain a 10 times overestimated lot (that's what I observed on the XAUUSD pair until I added recalculation).

if (lSL>0){

lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL; // TICKSIZE/POINT will give an integer (1 or 10), we can use int type lSL

// here is what it was.

PS: for TS which optimize many passes (>10mln) all unchangeable parameters of symbol(TICKSIZE, POINT, TICKVALUE, LOTSTEP, MINLOT, MAXLOT etc.) must be assigned to variables in functioninit() and use variables in calculations.

Including putting value of TickSize/Point into a variable.




Thank you
 
Vinin:

Thanks

The topicstarter sent his respects on the first page and never came back.

A few years ago this issue was discussed on a forum somewhere. I will retell it from memory, but without formulas.

Suppose we trade the AUDCHF pair. It was taken quite arbitrarily in order to explain how profit or loss is formed on a position. Approximately the same topic was brought up at https://www.mql5.com/ru/forum/150912

If we trade a single lot of 100000 AUD, then ( on a five digits) every pip makes 1 CHF (pair denominator) profit or loss (it depends on which way we have gone and where the price is going).

Accordingly, at any given time, we know how much CHF we have gained/lost. The gain/loss is converted to the currency of the deposit, using the USDCHF exchange rate at the moment, if the deposit currency is USD, or EURCHF, if the deposit currency is EUR. By analogy, for all pairs and deposit currencies.

This is the answer: we cannot always estimate the exact right lot size. MarketInfo() with request parameter MODE_TICKVALUE can be a guide.

 
Mislaid:

Hence the answer: we cannot always estimate the exact right lot size. MarketInfo() with MODE_TICKVALUE request parameter can be a guide.


That's how it's been accounted for a long time. At least in Vinin's nice post (with wrong lot calculation for mismatched TICKSIZE c POINT) and Martingeil's old post (with correct lot calculation, but no possibility to set drawdown ==0).

The main thing is that the correct value of TICKVALUE should arrive from the brokerage company (or calculated correctly on the client, if it is calculated in MT).


When this theme started, there was no TICKVALUE .

And with its advent, everything got simplified and this topic languished for a while.

PS: soon I will post my version - a hybrid of Vinin's version (it has simpler formula and iSL==0) and Martingeil's (control of insufficient funds even for min. lot).

Features: 1) calculation of balance from AccountFreeMargin(), not from AccountBalance().

2) And (for shifters) it is taken into account that the balance will decrease by a certain amount when an open trade closes on SL.

If there is not enough money even for min. balance - it will show lot volume -134 (error 134 - not enough money to open a trade)

In this regard, the question to Vinin (and other experienced comrades): is this code colored by itself or you do it yourself? I tried setting the snippet style "code", but it didn't colour it. Or is it only coloured after submitting the post?

 
EverAlex:

A question for Vinin (and other experienced comrades): does the code colour itself, or do you colour it yourself? I tried to set the snippet style "code", but it's not coloured. Or is it only coloured after submitting the post?

It is colored by myself. But not always.
 

finalised my idea (for platforms with stop-out percentage)... sharing the code... constructive criticism accepted

double lotSize(double deposSize=1000.0, string currName="USDCHF", double proc=2.0, int pipsLoss=1000)
{  
   double lotCount=0;
   //1) проверка достаточности средств для проведения торговли
   if(deposSize < 
   MarketInfo(currName,MODE_MARGINREQUIRED)*MarketInfo(currName,MODE_MINLOT))
   {
      //Alert("Величина вашего депозита недостаточна \nдля торговли на инструменте\""+currName+"\" \nc минимальнодопустимым лотом");
      return 0.0;
   }
   
   double currMove=deposSize*proc/100;// расчет процента от величины депозита
   
  
   //расчивываем максимально допустимый лот, до стоп-аута
   double SOlot = deposSize/(pipsLoss*MarketInfo(currName,MODE_TICKVALUE)+
   MarketInfo(currName,MODE_MARGINREQUIRED)*AccountInfoDouble(ACCOUNT_MARGIN_SO_SO)/100);     
   //расчет величины депозита, при котором сработает стоп-аут
   double SOval = SOlot*pipsLoss*MarketInfo(currName,MODE_TICKVALUE);
   
   
   ENUM_ACCOUNT_STOPOUT_MODE stopOutMode=(ENUM_ACCOUNT_STOPOUT_MODE)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE);
   
   if(stopOutMode==ACCOUNT_STOPOUT_MODE_PERCENT)//если стоп-аут в процентах
   {  
     
     if((deposSize-currMove)<SOval)//проверяем остаток на депозите на превышение значения стоп-аут
     {     
         if(SOlot<MarketInfo(currName,MODE_MINLOT))//если лот стоп-аута меньше минимального лота
         {
             lotCount = MarketInfo(currName,MODE_MINLOT);
             //находим количесвто пунктов до вылета по стоп-ауту и выбрасываем предупреждение
             int pipsSO=(int)round((deposSize - SOval)/(lotCount * MarketInfo(currName,MODE_TICKVALUE)));
             Print("При прохождении ценой больше ", pipsSO," пп.- \nторговля будет прекращена по STOP OUT!");             
             
             
         }
         else//если наш стоп-аут лот больше равно минимального
         {
              lotCount = SOlot;              
              int pipsSO=(int)round((deposSize - SOval)/(lotCount * MarketInfo(currName,MODE_TICKVALUE)));
              Print("Достижение STOP OUT, произойдет через ", pipsSO, " и работа будет проведена с максимальнодоступимым лотом до STOP OUT");
                           
         }
     }
     else//если же остаток на депозите будет меньше стоп-аута
     {     
     lotCount = currMove/(pipsLoss*MarketInfo(currName,MODE_TICKVALUE));
         if(lotCount<MarketInfo(currName,MODE_MINLOT))//если лот меньше минимального лота
         {            
            int pipsProc=(int)round(currMove/(MarketInfo(currName,MODE_MINLOT)*MarketInfo(currName,MODE_TICKVALUE)));
            Print(proc,"%-й уровень депозита будет достигнут, з минимальнолопустимым лотом, за ",pipsProc," пп.");
            lotCount=MarketInfo(currName,MODE_MINLOT);      
         }         
     }     
     
   }
   else{
   //а вот здесь нужна доработка, для платформ, где стоп-аут в пунктах
   //как сказал один наш товарищ "у кого идеи ростут из нужного места".. доделает
   /*
   */}      
  
   //"прическа" для лота   
   lotCount = MathFloor(lotCount/MarketInfo(currName,MODE_MINLOT))*MarketInfo(currName,MODE_MINLOT);   

   if(lotCount<MarketInfo(currName,MODE_MINLOT))
   {
      return MarketInfo(currName,MODE_MINLOT);
   }
   if(lotCount>MarketInfo(currName,MODE_MAXLOT))
   {
      return MarketInfo(currName,MODE_MAXLOT);  
   }   
   return lotCount;
}