Korrekte Berechnung der Partie aus dem Prozentsatz der Kaution - Seite 5

 
EverAlex:

Daher ist lSL die Anzahl der Punkte zu SL

Punkt = 0,00001 (bei 5-stelligen Kursen)

dLotStep = 0,01


Die Formel (lSL*dLotCost*dLotStep))*dLotStep ist falsch

Es sollte etwa (lSL*dLotCost*Point))*dLotStep sein


Sie müssen sich nichts ausdenken. Die Losgröße ist bei jedem Maklerunternehmen anders, und Sie müssen sie an die richtige Größe anpassen. Punkte haben damit nichts zu tun
 
Vinin:

Sie brauchen nichts zu erfinden. Die Losgröße ist bei jedem Maklerunternehmen anders, und wir müssen sie auf die richtige Größe bringen. Die Punkte haben damit nichts zu tun.


In unserem Fall ist lSL eine Drawdown-Größe in Kurspunkten, aber nicht in Lot-Punkten.

Das heißt, die Punkte haben etwas damit zu tun.

In der Berechnungsformel sollten wir also (was in Klammern steht) mit Point multiplizieren, nicht mit dLotStep.

Eine andere Sache ist, dass dies bereits auf Kosten von dLotCost geschieht (zusammen mit der Umrechnung in die Einzahlungswährung)...

D.h. wir sind die Ersten in der

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

Holen Sie sich eine ganze Zahl und berechnen Sie dann die korrekten Einheiten des Loses zurück, indem Sie mit dLotStep multiplizieren ?

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

Es gibt auch eine Option mit einer Einzahlung von 3 Pfund, um mit EURUSD zu handeln und 30% auf die Verliererseite zu setzen... aber das ist aus einer Reihe von Perversionen

 
EverAlex:


Im Hinblick auf das Problem ist lSL die Größe des Drawdowns in Punkten der Notierungen, nicht in Punkten der Partie.

Das heißt, die Punkte haben nichts damit zu tun.

In der Berechnungsformel sollten wir also (was in Klammern steht) mit Point multiplizieren, nicht mit dLotStep.

Eine andere Sache ist, dass dies bereits auf Kosten von dLotCost geschieht (zusammen mit der Umrechnung in die Einzahlungswährung)...

D.h. wir zuerst in

eine ganze Zahl erhalten und dann durch Multiplikation mit dLotStep ? auf die korrekten Einheiten der Partie zurückrechnen.




Ja
 
Vinin:


Die Formel ist immer noch falsch (für einen Block von iSL>0).

TICKVALUE gibt den Preis für TICKSIZE an.

Und lSL wird in POINT-Punkten angegeben.

POINT stimmt nicht immer mit TICKSIZE überein (siehe 3-stelliges Paar XAUUSD bei Alpari).

Sie müssen also lSL von POINT in TICKSIZE umwandeln.

Andernfalls erhalten wir ein 10-fach überschätztes Lot (das habe ich beim XAUUSD-Paar beobachtet, bis ich die Neuberechnung hinzugefügt habe).

wenn (lSL>0){

lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL; // TICKSIZE/POINT ergibt eine ganze Zahl (1 oder 10), wir können den Typ int verwenden lSL

// Hier ist, was es war.

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

PS: Für TC, das für viele Durchläufe (>10 Mio.) optimiert ist, sollten alle unveränderlichen Parameter des Symbols(TICKSIZE, POINT, TICKVALUE, LOTSTEP, MINLOT, MAXLOT usw.) in der Funktioninit() Variablen zugewiesen werden und diese Variablen in den Berechnungen verwendet werden.

Einschließlich der Aufnahme des Wertes von TickSize/Point in eine Variable.

 
EverAlex:

Die Formel ist immer noch falsch (für einen Block von iSL>0).

TICKVALUE gibt den Preis für TICKSIZE an.

Und lSL wird in POINT-Punkten angegeben.

POINT stimmt nicht immer mit TICKSIZE überein (siehe 3-stelliges Paar XAUUSD bei Alpari).

Sie müssen also lSL von POINT in TICKSIZE umwandeln.

Andernfalls erhalten wir ein 10-fach überschätztes Lot (das habe ich beim XAUUSD-Paar beobachtet, bis ich die Neuberechnung hinzugefügt habe).

wenn (lSL>0){

lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL; // TICKSIZE/POINT ergibt eine ganze Zahl (1 oder 10), wir können den Typ int verwenden lSL

// Hier ist, was es war.

PS: Für TS, die viele Durchläufe (>10 Mio.) optimieren, müssen alle unveränderlichen Parameter des Symbols(TICKSIZE, POINT, TICKVALUE, LOTSTEP, MINLOT, MAXLOT usw.) in der Funktioninit() Variablen zugewiesen werden und in den Berechnungen Variablen verwendet werden.

Einschließlich der Aufnahme des Wertes von TickSize/Point in eine Variable.




Dankeschön
 
Vinin:

Danke

Der Themenstarter hat auf der ersten Seite seinen Respekt bekundet und ist nie zurückgekommen.

Vor ein paar Jahren wurde dieses Thema in einem Forum diskutiert. Ich werde es aus dem Gedächtnis nacherzählen, aber ohne Formeln.

Angenommen, wir handeln das Paar AUDCHF. Er wurde recht willkürlich gewählt, um zu erklären, wie Gewinn oder Verlust auf einer Position entstehen. Ungefähr das gleiche Thema wurde auf https://www.mql5.com/ru/forum/150912 angesprochen.

Wenn wir ein einziges Lot von 100000 AUD handeln, dann macht (bei einer fünfstelligen Zahl) jeder Pip 1 CHF (Nenner des Paares) Gewinn oder Verlust (es hängt davon ab, in welche Richtung wir gegangen sind und wohin sich der Preis bewegt).

Dementsprechend wissen wir zu jedem Zeitpunkt, wie viel CHF wir gewonnen oder verloren haben. Der Gewinn/Verlust wird in die Währung der Einlage umgerechnet, wobei der aktuelle USDCHF-Wechselkurs verwendet wird, wenn die Einlagewährung USD ist, oder EURCHF, wenn die Einlagewährung EUR ist. Dies gilt analog für alle Paare und Einzahlungswährungen.

Das ist die Antwort: Wir können nicht immer genau die richtige Losgröße schätzen. MarketInfo() mit dem Abfrageparameter MODE_TICKVALUE kann eine Orientierungshilfe sein.

 
Mislaid:

Daher die Antwort: Wir können nicht immer genau die richtige Losgröße schätzen. MarketInfo() mit dem Abfrageparameter MODE_TICKVALUE kann eine Orientierungshilfe sein.


So wird es schon seit langem abgerechnet. Zumindest in Vinins schönem Beitrag (mit falscher Lotberechnung für nicht übereinstimmende TICKSIZE c POINT) und Martingeils altem Beitrag (mit korrekter Lotberechnung, aber keiner Möglichkeit, Drawdown ==0 zu setzen).

Die Hauptsache ist, dass der korrekte Wert von TICKVALUE von der Maklerfirma kommt (oder vom Kunden korrekt berechnet wird, wenn er in MT berechnet wird).


Als dieses Thema begann, gab es noch keinen TICKVALUE .

Mit seiner Einführung wurde alles vereinfacht, und dieses Thema geriet für eine Weile in Vergessenheit.

PS: In Kürze werde ich meine Version veröffentlichen - eine Mischung aus Vinins Version (sie hat eine einfachere Formel und iSL==0) und Martingeils Version (Kontrolle unzureichender Mittel sogar für die Mindestmenge).

Besonderheiten: 1) Berechnung des Saldos aus AccountFreeMargin(), nicht aus AccountBalance().

2) Und (bei Shiftern) wird berücksichtigt, dass der Saldo um einen bestimmten Betrag abnimmt, wenn ein offener Handel auf SL geschlossen wird.

Wenn nicht genug Geld vorhanden ist, auch nicht für den Mindestbetrag, wird das Losvolumen -134 angezeigt (Fehler 134 - nicht genug Geld für die Eröffnung eines Geschäfts)

In diesem Zusammenhang die Frage an Vinin (und andere erfahrene Kameraden): ist dieser Code von selbst gefärbt oder machen Sie es selbst? Ich habe versucht, den Snippet-Stil "Code" einzustellen, aber es hat ihn nicht gefärbt. Oder ist sie erst nach dem Absenden des Beitrags farbig?

 
EverAlex:

Eine Frage an Vinin (und andere erfahrene Kameraden): Färbt sich der Code selbst oder färben Sie ihn selbst? Ich habe versucht, den Snippet-Stil "Code" einzustellen, aber er ist nicht farbig. Oder ist sie erst nach dem Absenden des Beitrags farbig?

Sie ist von mir selbst gefärbt. Aber nicht immer.
 

meine Idee fertiggestellt (für Plattformen mit Stop-Out-Prozentsatz)... ich teile den Code... konstruktive Kritik akzeptiert

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