Calcul correct du lot à partir du % de la caution - page 5

 
EverAlex:

Donc lSL est le nombre de points vers SL

Point = 0.00001 (sur les cotations à 5 chiffres)

dLotStep = 0,01


La formule (lSL*dLotCost*dLotStep))*dLotStep est incorrecte.

Cela devrait être quelque chose comme (lSL*dLotCost*Point))*dLotStep


Tu n'as pas besoin d'inventer quoi que ce soit. La taille du lot est différente pour chaque société de courtage et vous devez l'ajuster à la bonne taille. Les points n'ont rien à voir avec cela
 
Vinin:

Vous n'avez pas besoin d'inventer quoi que ce soit. La taille du lot est différente dans chaque société de courtage et nous devons l'amener à la bonne taille. Les points n'ont rien à voir avec cela.


Dans notre cas, lSL est la taille du drawdown en points de cotations mais pas en points du lot.

En d'autres termes, les points n'ont rien à voir avec cela.

Ainsi, dans la formule de calcul, nous devons multiplier (ce qui est entre parenthèses) par Point, et non par dLotStep.

Une autre chose est que cela est déjà fait aux dépens de dLotCost (avec la conversion en monnaie de dépôt)...

C'est à dire que nous sommes les premiers dans les

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

Obtenir un nombre entier, puis recalculer en unités correctes du lot en multipliant par 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;
}

Il y a aussi une option avec un dépôt de 3 livres pour trader l'EURUSD et mettre 30% sur le côté perdant... mais ceci est hors d'une série de perversions

 
EverAlex:


En ce qui concerne le problème, lSL est la taille du drawdown en points de cotations, et non en points du lot.

En d'autres termes, les points n'ont rien à voir avec cela.

Ainsi, dans la formule de calcul, nous devons multiplier (ce qui est entre parenthèses) par Point, et non par dLotStep.

Une autre chose est que cela est déjà fait aux dépens de dLotCost (avec la conversion en monnaie de dépôt)...

C'est-à-dire que nous sommes les premiers à

obtenir un nombre entier, puis recalculer pour revenir aux unités correctes du lot en multipliant par dLotStep ?




Oui
 
Vinin:


La formule est toujours fausse (pour un bloc de iSL>0).

TICKVALUE donne le prix de TICKSIZE.

Et lSL est donné en points POINT.

LePOINT ne coïncide pas toujours avec le TICKSIZE (voir la paire à 3 chiffres XAUUSD chez Alpari).

Vous devez donc convertir lSL de POINT en TICKSIZE.

Sinon, nous obtiendrons un lot 10 fois surestimé (c'est ce que j'ai observé sur la paire XAUUSD jusqu'à ce que j'ajoute le recalcul).

si (lSL>0){

lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL ; // TICKSIZE/POINT donnera un entier (1 ou 10), nous pouvons utiliser le type int lSL

// Voilà ce que c'était.

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

PS : pour les CT optimisés pour de nombreuses passes (>10mln) tous les paramètres invariables du symbole(TICKSIZE, POINT, TICKVALUE, LOTSTEP, MINLOT, MAXLOT etc.) doivent être assignés à des variables dans la fonctioninit() et utiliser ces variables dans les calculs.

Notamment en mettant la valeur de TickSize/Point dans une variable.

 
EverAlex:

La formule est toujours fausse (pour un bloc de iSL>0).

TICKVALUE donne le prix de TICKSIZE.

Et lSL est donné en points POINT.

LePOINT ne coïncide pas toujours avec le TICKSIZE (voir la paire à 3 chiffres XAUUSD chez Alpari).

Vous devez donc convertir lSL de POINT en TICKSIZE.

Sinon, nous obtiendrons un lot 10 fois surestimé (c'est ce que j'ai observé sur la paire XAUUSD jusqu'à ce que j'ajoute le recalcul).

si (lSL>0){

lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL ; // TICKSIZE/POINT donnera un entier (1 ou 10), nous pouvons utiliser le type int lSL

// Voilà ce que c'était.

PS : pour les TS qui optimisent de nombreuses passes (>10mln) tous les paramètres non modifiables du symbole(TICKSIZE, POINT, TICKVALUE, LOTSTEP, MINLOT, MAXLOT etc.) doivent être assignés à des variables dans la fonctioninit() et utiliser les variables dans les calculs.

Notamment en mettant la valeur de TickSize/Point dans une variable.




Merci.
 
Vinin:

Merci

Le topicstarter a envoyé ses respects dès la première page et n'est jamais revenu.

Il y a quelques années, cette question a été discutée sur un forum quelque part. Je vais la raconter de mémoire, mais sans formules.

Supposons que nous négocions la paire AUDCHF. Elle a été prise de manière tout à fait arbitraire afin d'expliquer comment se forment les profits ou les pertes sur une position. Le même sujet a été abordé à https://www.mql5.com/ru/forum/150912.

Si nous négocions un lot unique de 100000 AUD, alors ( sur une base de cinq chiffres) chaque pip fait 1 CHF (dénominateur de la paire) de profit ou de perte (cela dépend de la direction que nous avons prise et de la direction que prend le prix).

Par conséquent, à tout moment, nous savons combien de CHF nous avons gagné/perdu. Le gain/la perte est converti(e) dans la devise du dépôt, en utilisant le taux de change USDCHF du moment, si la devise du dépôt est USD, ou EURCHF, si la devise du dépôt est EUR. Par analogie, pour toutes les paires et les devises de dépôt.

Voici la réponse : nous ne pouvons pas toujours estimer la taille exacte du lot. MarketInfo() avec le paramètre de requête MODE_TICKVALUE peut servir de guide.

 
Mislaid:

D'où la réponse : nous ne pouvons pas toujours estimer la taille exacte du lot. MarketInfo() avec le paramètre de requête MODE_TICKVALUE peut servir de guide.


C'est ainsi qu'il a été comptabilisé pendant longtemps. Au moins dans le bon post de Vinin (avec un calcul de lot erroné pour des TICKSIZE c POINT non concordants) et l'ancien post de Martingeil (avec un calcul de lot correct, mais pas de possibilité de définir drawdown ==0).

L'essentiel est que la valeur correcte de TICKVALUE arrive de la société de courtage (ou soit calculée correctement sur le client, si elle est calculée en MT).


Au début de ce thème, il n'y avait pas de TICKVALUE .

Et avec son avènement, tout s'est simplifié et ce sujet a langui pendant un certain temps.

PS : bientôt je posterai ma version - un hybride de la version de Vinin (elle a une formule plus simple et iSL==0) et de celle de Martingeil (contrôle des fonds insuffisants même pour le lot minimum).

Caractéristiques : 1) calcul du solde à partir de AccountFreeMargin(), et non de AccountBalance().

2) Et (pour les shifters) il est pris en compte que le solde diminuera d'un certain montant lorsqu'une transaction ouverte se ferme sur SL.

S'il n'y a pas assez d'argent, même pour le solde minimum, le volume du lot sera de -134 (erreur 134 - pas assez d'argent pour ouvrir une transaction).

A ce propos, la question à Vinin (et autres camarades expérimentés) : ce code se colore tout seul ou vous le faites vous-même ? J'ai essayé de définir le style du snippet "code", mais cela ne l'a pas coloré. Ou est-ce qu'il n'est coloré qu'après avoir soumis le message ?

 
EverAlex:

Une question pour Vinin (et d'autres camarades expérimentés) : le code se colore-t-il lui-même, ou le colorez-vous vous-même ? J'ai essayé de définir le style du snippet "code", mais il n'est pas coloré. Ou est-ce qu'il n'est coloré qu'après avoir soumis le message ?

Il est coloré par moi-même. Mais pas toujours.
 

j'ai finalisé mon idée (pour les plateformes avec pourcentage de stop-out)... je partage le code... critique constructive acceptée

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