Cálculo correto do lote a partir da % do depósito - página 5

 
EverAlex:

Portanto, lSL é quantos pontos para SL

Ponto = 0,00001 (em citações de 5 dígitos)

dLotStep = 0,01


A fórmula (lSL*dLotCost*dLotStep))*dLotStep está errada

Deve ser algo como (lSL*dLotCost*Point))*dLotStep


Você não tem que inventar nada. O tamanho do lote é diferente para cada corretora e você tem que ajustá-lo ao tamanho certo. Os pontos não têm nada a ver com isso
 
Vinin:

Você não tem que inventar nada. O tamanho do lote é diferente em cada corretora e temos que levá-lo ao tamanho certo. Os pontos não têm nada a ver com isso.


Em nosso caso, lSL é o tamanho do sorteio em pontos de cotações, mas não em pontos do lote.

Isto é, os pontos não têm nada a ver com isso.

Portanto, na fórmula para calculá-la, multiplique (o que está entre parênteses) por Ponto, não por dLotStep.

Outra coisa é que isso já é feito às custas do dLotCost (junto com a conversão para a moeda de depósito)...

Isto é, somos os primeiros no

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

Obtenha um número inteiro e depois recalcule de volta às unidades corretas do lote, multiplicando por 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;
}

Há também uma opção com um depósito de 3 libras para negociar EURUSD e colocar 30% do lado perdedor... mas isso está fora de uma série de perversões

 
EverAlex:


Em termos do problema lSL é o tamanho do sorteio em pontos de cotações, não em pontos do lote.

Isto é, os pontos não têm nada a ver com isso.

Portanto, na fórmula de cálculo devemos multiplicar (o que está entre parênteses) por Ponto, não por dLotStep.

Outra coisa é que isso já é feito às custas do dLotCost (junto com a conversão para a moeda de depósito)...

Isto é, nós somos os primeiros em

obter um número inteiro, e depois recalcular de volta às unidades corretas do lote, multiplicando por dLotStep ?




Sim
 
Vinin:


A fórmula ainda está errada (para um bloco de iSL>0).

TICKVALUE dá o preço do TICKSIZE.

E a lSL é dada em pontos de PONTO.

PONTO nem sempre coincide com TICKSIZE (ver par de 3 dígitos XAUUSD na Alpari).

Portanto, você deve converter a lSL de POINT para TICKSIZE.

Caso contrário, obteremos um lote 10 vezes superestimado (foi o que observei no par XAUUSD até acrescentar um recálculo).

se (lSL>0){

lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL; // TICKSIZE/POINT dará um número inteiro (1 ou 10), podemos usar o tipo int lSL

// aqui está o que era.

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

PS: para TC otimizado para muitos passes (>10mln) todos os parâmetros imutáveis de símbolo(TICKSIZE, POINT, TICKVALUE, LOTSTEP, MINLOT, MAXLOT etc.) devem ser atribuídos a variáveis em funçãoinit() e usar estas variáveis nos cálculos.

Incluindo a colocação de valor de TickSize/Point em uma variável.

 
EverAlex:

A fórmula ainda está errada (para um bloco de iSL>0).

TICKVALUE dá o preço do TICKSIZE.

E a lSL é dada em pontos de PONTO.

PONTO nem sempre coincide com TICKSIZE (ver par de 3 dígitos XAUUSD na Alpari).

Portanto, você deve converter a lSL de POINT para TICKSIZE.

Caso contrário, obteremos um lote 10 vezes superestimado (foi o que observei no par XAUUSD até acrescentar um recálculo).

se (lSL>0){

lSL= (int)(MarketInfo(lSymbol,MODE_TICKSIZE) / MarketInfo(lSymbol,MODE_POINT) )* lSL; // TICKSIZE/POINT dará um número inteiro (1 ou 10), podemos usar o tipo int lSL

// aqui está o que era.

PS: para TS que otimizam muitos passes (>10mln) todos os parâmetros imutáveis de símbolo(TICKSIZE, POINT, TICKVALUE, LOTSTEP, MINLOT, MAXLOT etc.) devem ser atribuídos a variáveis em funçãoinit() e usar variáveis em cálculos.

Incluindo a colocação de valor de TickSize/Point em uma variável.




Obrigado
 
Vinin:

Obrigado

O iniciante do tópico enviou seus respeitos na primeira página e nunca mais voltou.

Há alguns anos, esta questão foi discutida em algum lugar em um fórum. Vou recontar de memória, mas sem fórmulas.

Suponha que comercializamos o par AUDCHF. Foi tomada de forma bastante arbitrária a fim de explicar como o lucro ou a perda é formado sobre uma posição. Aproximadamente o mesmo tópico foi abordado em https://www.mql5.com/ru/forum/150912

Se negociamos um único lote de 100.000 AUD, então (em cinco dígitos) cada pip faz 1 CHF (denominador de par) de lucro ou perda (depende do caminho que tomamos e para onde o preço está indo).

Assim, a qualquer momento, sabemos quanto CHF ganhamos/perdemos. O ganho/perda é convertido para a moeda do depósito, usando a taxa de câmbio USDCHF no momento, se a moeda do depósito for USD, ou EURCHF, se a moeda do depósito for EUR. Por analogia, para todos os pares e moedas de depósito.

Esta é a resposta: nem sempre podemos estimar o tamanho exato do lote certo. MarketInfo() com parâmetro de solicitação MODE_TICKVALUE pode ser um guia.

 
Mislaid:

Daí a resposta: nem sempre podemos estimar o tamanho exato do lote certo. MarketInfo() com o parâmetro de solicitação MODE_TICKVALUE pode ser um guia.


É assim que tem sido contabilizado por muito tempo. Pelo menos no belo posto de Vinin (com cálculo de lote errado para o TICKSIZE c POINT) e no antigo posto de Martingeil (com cálculo de lote correto, mas sem possibilidade de estabelecer drawdown ==0).

O principal é que o valor correto do TICKVALUE deve chegar da corretora (ou calculado corretamente sobre o cliente, se for calculado em MT).


Quando este tema começou, não havia TICKVALUE .

E com seu advento, tudo ficou simplificado e este tópico enfraqueceu por um tempo.

PS: em breve publicarei minha versão - um híbrido da versão de Vinin (tem fórmula mais simples e iSL==0) e Martingeil's (controle de fundos insuficientes mesmo para lote mínimo).

Características: 1) cálculo de saldo de AccountFreeMargin(), não de AccountBalance().

2) E (no caso dos shifters) é levado em conta que o saldo diminuirá em um certo valor quando um comércio aberto fechar em SL.

Se não houver dinheiro suficiente mesmo para o saldo mínimo - mostrará volume de lote -134 (erro 134 - não há dinheiro suficiente para abrir um comércio)

A este respeito, a pergunta para Vinin (e outros camaradas experientes): este código é colorido por si mesmo ou você mesmo o faz? Tentei definir o "código" no estilo "snippet", mas ele não o coloriu. Ou ele só é colorido depois de enviar o correio?

 
EverAlex:

Uma pergunta para Vinin (e para outros camaradas experientes): o código colorido em si ou você mesmo o pinta? Tentei definir o "código" no estilo "snippet", mas não é colorido. Ou ele só é colorido depois de enviar o correio?

É colorido por mim mesmo. Mas nem sempre.
 

finalizei minha idéia (para plataformas com porcentagem de stop-out)... compartilhando o código... críticas construtivas aceitas

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;
}
Razão: