Calcolo corretto del lotto dalla % del deposito - pagina 5

 
EverAlex:

Quindi lSL è quanti punti a SL

Punto = 0,00001 (su quotazioni a 5 cifre)

dLotStep = 0,01


La formula (lSL*dLotCost*dLotStep))*dLotStep non è corretta

Dovrebbe essere qualcosa come (lSL*dLotCost*Point))*dLotStep


Non c'è bisogno di inventare nulla. La dimensione del lotto è diversa per ogni società di intermediazione e devi adattarla alla giusta dimensione. I punti non c'entrano niente
 
Vinin:

Non devi inventare nulla. La dimensione del lotto è diversa in ogni società di intermediazione e dobbiamo portarlo alla giusta dimensione. I punti non c'entrano niente.


Nel nostro caso, lSL è una dimensione di drawdown in punti di quotazioni ma non in punti di lotto.

Cioè i punti non c'entrano niente.

Quindi, nella formula di calcolo dovremmo moltiplicare (ciò che è tra parentesi) per Point, non per dLotStep.

Un'altra cosa è che questo è già fatto a spese di dLotCost (insieme alla conversione in moneta di deposito)...

Cioè siamo primi nel

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

Ottenere un intero e poi ricalcolare alle unità corrette del lotto moltiplicando per 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;
}

C'è anche un'opzione con un deposito di 3 sterline per scambiare EURUSD e mettere il 30% sul lato perdente... ma questo è fuori da una serie di perversioni

 
EverAlex:


In termini di problema lSL è la dimensione del drawdown in punti di quotazioni, non in punti del lotto.

Cioè i punti non c'entrano niente.

Quindi, nella formula di calcolo dovremmo moltiplicare (ciò che è tra parentesi) per Point, non per dLotStep.

Un'altra cosa è che questo è già fatto a spese di dLotCost (insieme alla conversione in moneta di deposito)...

Cioè noi per primi in

ottenere un intero, e poi ricalcolare alle unità corrette del lotto moltiplicando per dLotStep ?




 
Vinin:


La formula è ancora sbagliata (per un blocco di iSL>0).

TICKVALUE dà il prezzo per TICKSIZE.

E lSL è dato in punti POINT.

POINT non sempre coincide con TICKSIZE (vedi coppia a 3 cifre XAUUSD su Alpari).

Quindi dovete convertire lSL da POINT a TICKSIZE.

Altrimenti, otterremo un lotto 10 volte sovrastimato (questo è ciò che ho osservato sulla coppia XAUUSD fino a quando ho aggiunto il ricalcolo).

se (lSL>0){

lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL; // TICKSIZE/POINT darà un intero (1 o 10), possiamo usare lSL di tipo int

// ecco cos'era.

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

PS: per TC ottimizzato per molti passaggi (>10mln) tutti i parametri immutabili del simbolo(TICKSIZE, POINT, TICKVALUE, LOTSTEP, MINLOT, MAXLOT ecc.) dovrebbero essere assegnati a variabili nella funzioneinit() e usare queste variabili nei calcoli.

Incluso mettere il valore di TickSize/Point in una variabile.

 
EverAlex:

La formula è ancora sbagliata (per un blocco di iSL>0).

TICKVALUE dà il prezzo per TICKSIZE.

E lSL è dato in punti POINT.

POINT non sempre coincide con TICKSIZE (vedi coppia a 3 cifre XAUUSD su Alpari).

Quindi dovete convertire lSL da POINT a TICKSIZE.

Altrimenti, otterremo un lotto 10 volte sovrastimato (questo è ciò che ho osservato sulla coppia XAUUSD fino a quando ho aggiunto il ricalcolo).

se (lSL>0){

lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL; // TICKSIZE/POINT darà un intero (1 o 10), possiamo usare lSL di tipo int

// ecco cos'era.

PS: per i TS che ottimizzano molti passaggi (>10mln) tutti i parametri immutabili del simbolo(TICKSIZE, POINT, TICKVALUE, LOTSTEP, MINLOT, MAXLOT ecc.) devono essere assegnati a variabili nella funzioneinit() e usare variabili nei calcoli.

Incluso mettere il valore di TickSize/Point in una variabile.




Grazie
 
Vinin:

Grazie

Il topicstarter ha mandato i suoi saluti nella prima pagina e non è più tornato.

Qualche anno fa questo problema è stato discusso su un forum da qualche parte. Lo racconterò a memoria, ma senza formule.

Supponiamo di negoziare la coppia AUDCHF. È stato preso abbastanza arbitrariamente per spiegare come si forma il profitto o la perdita su una posizione. Più o meno lo stesso argomento è stato portato su https://www.mql5.com/ru/forum/150912

Se scambiamo un singolo lotto di 100000 AUD, allora (su cinque cifre) ogni pip fa 1 CHF (denominatore della coppia) di profitto o perdita (dipende da quale strada abbiamo preso e dove sta andando il prezzo).

Di conseguenza, in qualsiasi momento, sappiamo quanti CHF abbiamo guadagnato/perduto. Il guadagno/perdita viene convertito nella valuta del deposito, utilizzando il tasso di cambio USDCHF del momento, se la valuta del deposito è USD, o EURCHF, se la valuta del deposito è EUR. Per analogia, per tutte le coppie e le valute di deposito.

Questa è la risposta: non possiamo sempre stimare la dimensione esatta del lotto. MarketInfo() con il parametro di richiesta MODE_TICKVALUE può essere una guida.

 
Mislaid:

Da qui la risposta: non possiamo sempre stimare la dimensione esatta del lotto. MarketInfo() con il parametro di richiesta MODE_TICKVALUE può essere una guida.


È così che è stato contabilizzato per molto tempo. Almeno nel bel post di Vinin (con calcolo del lotto sbagliato per TICKSIZE c POINT non corrispondenti) e nel vecchio post di Martingeil (con calcolo del lotto corretto, ma senza possibilità di impostare drawdown ==0).

La cosa principale è che il valore corretto di TICKVALUE dovrebbe arrivare dalla società di intermediazione (o calcolato correttamente sul cliente, se è calcolato in MT).


Quando questo tema è iniziato, non c'era TICKVALUE .

E con il suo avvento, tutto si è semplificato e questo argomento ha languito per un po'.

PS: presto posterò la mia versione - un ibrido tra la versione di Vinin (ha una formula più semplice e iSL==0) e quella di Martingeil (controllo dei fondi insufficienti anche per il lotto minimo).

Caratteristiche: 1) calcolo del saldo da AccountFreeMargin(), non da AccountBalance().

2) E (per i traslocatori) si tiene conto che il saldo diminuirà di una certa quantità quando un trade aperto si chiude su SL.

Se non c'è abbastanza denaro anche per il saldo minimo - mostrerà il volume del lotto -134 (errore 134 - non abbastanza denaro per aprire una compravendita)

A questo proposito, la domanda a Vinin (e ad altri compagni esperti): questo codice si colora da solo o lo fai tu? Ho provato a impostare lo stile dello snippet "code" ma non l'ha colorato. O si colora solo dopo aver inviato il post?

 
EverAlex:

Una domanda per Vinin (e altri compagni esperti): il codice si colora da solo o lo colorate voi stessi? Ho provato a impostare lo stile dello snippet "codice", ma non è colorato. O si colora solo dopo aver inviato il post?

È colorato da me. Ma non sempre.
 

finalizzato la mia idea (per piattaforme con percentuale di stop-out)... condividendo il codice... si accettano critiche costruttive

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