Precisa de uma fórmula de tamanho LOT de gerenciamento de dinheiro baseada em SL e Risco de Conta! - página 3

 

OK, pessoal! Este código foi escrito por mim e é o que eu uso em minhas próprias EA's. É bastante complexo porque, além do Risk% e StopLoss, ele também leva em conta o Margin Risk%, bem como corrige o tamanho do lote com base no Mínimo, Máximo e Tamanho da etapa. Também usa sempre o valor mínimo de Equilíbrio Corrente e Equilíbrio, em vez de usar apenas um deles. Sinto que é mais seguro dessa forma.

Observe, entretanto, que não utiliza o spread no cálculo, pois eu o calculo separadamente ao calcular o StopLoss a ser utilizado. A função abaixo, portanto, usa um tamanho relativo de StopLoss. No meu EA o argumento dblStopLossPips é calculado de antemão dependendo de vários fatores como a estratégia, spread, ATR, etc.; assim, o valor final passado para a função dblLotsRisk() já é um valor final para calcular o tamanho do lote a ser utilizado.

// Function to Determine Tick Point Value in Account Currency

        double dblTickValue( string strSymbol )
        {
                return( MarketInfo( strSymbol, MODE_TICKVALUE ) );
        }
        

// Function to Determine Pip Point Value in Account Currency

        double dblPipValue( string strSymbol )
        {
                double dblCalcPipValue = dblTickValue( strSymbol );
                switch ( MarketInfo( strSymbol, MODE_DIGITS ) )
                {
                        case 3:
                        case 5:
                                dblCalcPipValue *= 10;
                                break;
                }
                
                return( dblCalcPipValue );
        }
        

// Calculate Lot Size based on Maximum Risk & Margin

        double dblLotsRisk( string strSymbol, double dblStopLossPips,
                double dblRiskMaxPercent, double dblMarginMaxPercent,
                double dblLotsMin, double dblLotsMax, double dblLotsStep )
        {
                double
                        dblValueAccount = MathMin( AccountEquity(), AccountBalance() )
                ,       dblValueRisk    = dblValueAccount * dblRiskMaxPercent / 100.0
                ,       dblValueMargin  = AccountFreeMargin() * dblMarginMaxPercent / 100.0
                ,       dblLossOrder    = dblStopLossPips * dblPipValue( strSymbol )
                ,       dblMarginOrder  = MarketInfo( strSymbol, MODE_MARGINREQUIRED )
                ,       dblCalcLotMin
                                = MathMax( dblLotsMin, MarketInfo( strSymbol, MODE_MINLOT ) )
                ,       dblCalcLotMax
                                = MathMin( dblLotsMax, MarketInfo( strSymbol, MODE_MAXLOT ) )
                ,       dblModeLotStep  = MarketInfo( strSymbol, MODE_LOTSTEP )
                ,       dblCalcLotStep  = MathCeil( dblLotsStep / dblModeLotStep ) * dblModeLotStep
                ,       dblCalcLotLoss
                                = MathFloor( dblValueRisk / dblLossOrder / dblCalcLotStep ) * dblCalcLotStep
                ,       dblCalcLotMargin
                                = MathFloor( dblValueMargin / dblMarginOrder / dblCalcLotStep ) * dblCalcLotStep
                ,       dblCalcLot = MathMin( dblCalcLotLoss, dblCalcLotMargin )
                ;
                
                if ( dblCalcLot < dblCalcLotMin ) dblCalcLot = dblCalcLotMin;
                if ( dblCalcLot > dblCalcLotMax ) dblCalcLot = dblCalcLotMax;

                return ( dblCalcLot );
        }
 
GumRai:

Isso me dá uma dor de cabeça só de tentar resolver os parênteses!

Para ser honesto, não tenho a menor idéia do que você está tentando alcançar aqui.

Não consigo ver como MODE_STOPLEVEL ou SPREAD são relevantes, certamente você deveria estar baseando seus cálculos na distância de stop-loss do preço atual?

Não deve fazer diferença qual é a moeda da conta, o cálculo deve ser o mesmo porque TICKVALUE está na moeda da conta.

Observe que, ao colocar sua linha de código em 2 linhas, o correio não é tão largo e facilita a leitura sem rolar para a direita e para a esquerda :)

Eu postei algumas páginas atrás, uma imagem na qual ilustrei minha fórmula como calcular o lote. Mas o pipvalue ou tickvalue ou o que quer que esteja sempre mexendo.Quote->moeda base e outras coisas que são confusas, mas até agora minha fórmula fez um bom trabalho, embora eu não tenha certeza de que esteja correta.

O SPREAD pode ser irrelevante, mas é necessário o stoplevel. Coloco o SL o mais próximo possível do preço do pedido aberto que é o stoplevel, mas devido a flutuações e picos, às vezes preciso ajustá-lo manualmente, por isso coloquei uma variável STOPSLIP com a qual posso ajustar o SL à volatilidade ou o que quer que seja.

FMIC:

OK, pessoal! Este código foi escrito por mim e é o que eu uso nas minhas próprias EA's. É bastante complexo porque, além do Risk% e StopLoss, ele também leva em conta o Margin Risk%, bem como corrige o tamanho do lote com base no Mínimo, Máximo e Tamanho do Passo. Também usa sempre o valor mínimo de Equilíbrio Corrente e Equilíbrio, em vez de usar apenas um deles. Sinto que é mais seguro dessa forma.

Observe, entretanto, que ele não usa o spread no cálculo, porque eu o calculo separadamente ao calcular o StopLoss a ser usado. A função abaixo, portanto, usa um tamanho relativo de StopLoss. No meu EA o argumento dblStopLossPips é calculado de antemão dependendo de vários fatores como a estratégia, spread, ATR, etc.; assim, o valor final passado para a função dblLotsRisk() já é um valor final para calcular o tamanho do lote a ser usado.

Obrigado, vou testá-lo e contar meu feedback!

Embora eu não entenda porque você coloca tantas variáveis lá, o código inteiro pode ser ajustado em 1 linha :)

 
Proximus:

Eu postei algumas páginas atrás, uma foto na qual ilustrei minha fórmula como calcular o lote. Mas o pipvalue ou tickvalue ou o que quer que esteja sempre mexendo.Quote->moeda base e outras coisas que são confusas, mas até agora minha fórmula fez um bom trabalho, embora eu não tenha certeza de que esteja correta.

O SPREAD pode ser irrelevante, mas é necessário o stoplevel. Coloco o SL o mais próximo possível do preço de pedido aberto que é o stoplevel, mas devido a flutuações e picos, às vezes preciso ajustá-lo manualmente, por isso coloquei uma variável STOPSLIP com a qual posso ajustar o SL à volatilidade ou o que quer que seja.

Obrigado, vou testá-la e contar meu feedback!

Embora eu não entenda porque você coloca tantas variáveis ali, o código inteiro pode ser encaixado em 1 linha :)


Sim, o código poderia ser todo colocado em uma linha, mas acredite, NUNCA é uma boa maneira de codificar, a menos que você esteja tentando espremer cada último ciclo de CPU de seu código para ser o mais rápido do planeta.

É por isso que "GumRai " reclamou de ter uma dor de cabeça tentando fazer a cabeça ou a cauda do outro código. Simplesmente não era muito legível ou de fácil compreensão e isso torna muito difícil fazer a depuração.

Meu caminho pode ser mais verboso, mas é mais fácil de depurar e manter, assim como mais legível e mais fácil de entender por outros como você.

Mas fique à vontade para compactar tudo em uma única linha. Apenas não reclame se não der os mesmos resultados. Deixarei a você a tarefa de depurar isso.

 

Desculpe por reabrir este tópico, mas é crucial para confirmar algo, portanto, esta é a função que eu criei (vou colocá-la em público, você pode me agradecer mais tarde):

double LOTUNITSTORISK()
{
double LOTS=((AccountBalance()*RISKPERCENT/100) / (  MarketInfo(Symbol(), MODE_TICKVALUE)*MarketInfo(Symbol(), MODE_TICKSIZE)*STOPSIZE     ));
return LOTS;
}


Esta função deve retornar as unidades de lote com base no risco da conta, e calculado através de uma conta EUR, já que o EUR é sempre a moeda base.

Unidade de lote significa = o tamanho real do dinheiro de uma posição, portanto, para uma conta de 100 euros de risco de 1%, deve retornar 1 euro que, com base no STOPLOSS, por exemplo, uma perda de 100 pipetas deve ser de 1000 unidades de lote ( 0,01 LOTE EM MT4 EQUIVALENTE)

É fundamental que a moeda da conta seja EURO, nada mais.

Uma vez que chamamos o LOTUNITTORISK(), devemos dividir os resultados por 100.000 para obter o tamanho real do lote no formato MT4 (1000 unidades de caixa 0,01 LOT em MT4)

RISKPERCENT = é uma int e pode ser 1,2,3,4 o risco % que corremos

STOPSIZE = é uma int e seu número de pipetas (pips/10 em corretor de 5 dígitos) que nosso tamanho de stoploss é, então por exemplo 60 pipetas SL é uma 6 pipetas SL

Quero saber se a função calcula as UNIDADES DE LOTE corretamente, por favor teste-a e se você encontrar algum erro, por favor me ajude :)

Mil agradecimentos!

 
Proximus:
MarketInfo(Symbol(), MODE_TICKVALUE)* MarketInfo(Symbol(), MODE_TICKSIZE)*STOPSIZE

Risk  = lotsize * StopSize * TickValue /  TickSize
         1      *  0.0100  *  $10.00   / 0.0001
$1000 = one lot * 100 pips *  $10.00   / pip
  1. Você coloca a parada onde ela precisa estar - onde a razão para o comércio não é mais válida. Por exemplo, a troca de um suporte de apoio faz com que a parada fique abaixo do suporte.
  2. Saldo da conta *% = RISK = (OrderOpenPrice - OrderStopLoss)*DIR * OrderLots * DeltaPerlot (Nota OOP-OSL inclui o SPREAD)
  3. NÃO utilize TickValue por si só - DeltaPerlot
  4. Você também deve verificar o FreeMargin para evitar parar
 
WHRoeder:
  1. Você coloca a parada onde ela precisa estar - onde a razão para o comércio não é mais válida. Por exemplo, a troca de um suporte de apoio faz com que a parada fique abaixo do suporte.
  2. Saldo da conta *% = RISK = (OrderOpenPrice - OrderStopLoss)*DIR * OrderLots * DeltaPerlot (Nota OOP-OSL inclui o SPREAD)
  3. NÃO utilize TickValue por si só - DeltaPerlot
  4. Você também deve verificar o FreeMargin para evitar parar

1) A função só devolve o TAMANHO TOTAL em unidade monetária e não em unidade MT4 nada mais, quando eu coloco os pedidos então, respectivamente, o STOPSIZE será adicionado /sustraído de Bid em caso de COMPRAR e Perguntar em caso de venda.

BUY aberto na ASK, fechado na BID

VENDA aberta na BID, fechada na ASK

2) Eu não posso usar OrderOpenprice man porque nenhuma ordem é aberta antes desta função ser calculada.

Mas antes disso, precisamos determinar o tamanho do lote, isto é lógico.

3) Eu não entendo isto.

4) Obviamente, mas ressalto novamente que a função de colocação do pedido é executada depois disto, e tem pouco a ver com esta função.A única finalidade desta função é determinar o tamanho do lote, nada mais.


TickValue /  TickSize

Incorreto, se eu os dividir, então eu recebo o número errado, talvez por contas em USD, mas é uma conta em EUR, que deve ser multiplicada.

 
Proximus:

COMPRAR aberto na ASK, fechado na BID VENDER aberto na BID, fechado na ASK

2) Eu não posso usar OrderOpenprice

3) Eu não entendo isto.

4)t, se eu os dividir, então eu recebo o número errado, talvez para contas em USD, mas é uma conta em EUR, que deve ser multiplicada.

  1. A pergunta é o Preço Aberto para uma compra
  2. A Licitação é o OrderOpenPrice para uma venda. Por que você não pode usá-la, você tem que saber para passá-la para a OrderSend?
  3. Você DEVE usar o valor/tamanho do carrapato. O valor do tick por si só não tem sentido.
  4. Você DEVE dividir para obter as unidades corretas (Alteração no preço) * (tickValue) /(alteração no preço) lhe dá um valor. $10 por pip = $1 por ponto = valor/alteração. Lembre-se de que o resultado é a moeda da conta, então quando você a divide por seu risco você recebe um número puro, novamente as unidades cancelam $risk(BAL%)/$risk(SL). Se você tiver que multiplicar, você está fazendo algo errado ou os valores dos corretores estão confusos.
 
WHRoeder:
Proximus:

COMPRAR aberto em ASK, fechado em BID SELL aberto em BID, fechado em ASK

2) Eu não posso usar OrderOpenprice

3) Eu não entendo isto.

4)t, se eu os dividir, então eu recebo o número errado, talvez para contas em USD, mas é uma conta em EUR, que deve ser multiplicada.

  1. A pergunta é o Preço Aberto para uma compra
  2. A Licitação é o OrderOpenPrice para uma venda. Por que você não pode usá-lo, você tem que saber para passá-lo para a OrderSend?
  3. Você DEVE usar o valor/tamanho do carrapato. O valor do tick por si só não tem sentido.
  4. Você DEVE dividir para obter as unidades corretas (Alteração no preço) * (tickValue) /(alteração no preço) lhe dá um valor. $10 por pip = $1 por ponto = valor/alteração. Lembre-se de que o resultado é a moeda da conta, então quando você a divide por seu risco você recebe um número puro, novamente as unidades cancelam $risk(BAL%)/$risk(SL). Se você tiver que multiplicar, você está fazendo algo errado ou os valores dos corretores estão confusos.


1,2 Eu sei disso, mas entenda que isso é tratado por outra função, não tem nada a ver com esta

3) Como entendo o valor do tick value é o valor de 1 pip na moeda base, portanto, dependendo do par que eu usar, terá que dividir ou multiplicar por ele. No caso de uma conta em EUR, parece que temos que multiplicar e não dividir.

Aqui está uma imagem que o ilustra melhor:


No EUR/USD para uma negociação de risco de 3%, precisamos abrir 1798 unidades, arredondando 0,02 LOTES em unidades MT4 para conseguir isso.

O tamanho do STOPLOSS é determinado por outra função.

Parece estar correto, pois eu o testei, mas não tenho certeza se a fórmula é realmente precisa, isso é o que estou tentando determinar aqui, portanto, por favor, ajude nisso.

 

Eu também tenho tentado descobrir este cálculo de tamanho de lote com base no SL, risco de conta e nível de chamada de margem, especialmente quando o nível de chamada de margem não é 100%, mas é, por exemplo, 120%. A melhor resposta que encontrei foi o que WHRoeder compartilhou aqui em seu código whrea.mq4. O código whrea.mq4 precisava de alguma correção, mas WHRoeder já oferece essa correção aqui em sua resposta ao comentário do RaptorUK. Portanto, a resposta completa ao cálculo do tamanho do lote está lá, mas algum esforço é necessário para entender completamente o que WHRoeder compartilhou.

Anexei o código que extraí e modifiquei do WHRoeder whrea.mq4 para compilar com o último novo build MT4 para calcular o tamanho do lote para um comércio longo onde o Nível de Chamada de Margem é mais de 100%.

Entretanto, não tenho certeza se a multiplicação pelo Nível de Chamada de Margem % é correta para levar em conta o Nível de Chamada de Margem % para evitar uma chamada de margem. Se o MarginCallLevel for 100%, então ambas as linhas de código estariam corretas, mas se o MarginCallLevel for 120%, a multiplicação pelo MarginCallLevel % seria um teste de Chamada de Margem correto? Se não, então qual é a maneira correta de fazer isso? WHRoeder, você pode ajudar com isso? William, eu tentei o meu melhor.

Aqui está o código dessa seção de Teste de Margem para um comércio longo:

extern double MarginCallLevel = 120; //As a percentage

double MarginCallLevel1 = MarginCallLevel * 0.01; 

        double  AFMC    = AccountFreeMarginCheck(Symbol(), OP_BUY, tradesize),
                        eRisk   = equityatrisk + atrisknew;

        //Test for margin
        //Note: Not sure if multiplying by the MarginCallLevel % here is correct to 
        //take the Margin Call Level % into account for avoiding a margin call.
        //If the MarginCallLevel is 100% then both lines of code would be correct
        //but if the MarginCallLevel is 120% would multiplying by the MarginCallLevel %
        //be a correct Margin Call test? If not, then what is the correct way to do this?

        //if (AFMC*0.99 <= eRisk){
        if (AFMC*0.99 <= eRisk*MarginCallLevel1){
            tradesize *= 0.95;    // Must still round to lotStep.
            continue;   }   // Prevent margin call if new trade goes against us.
Arquivos anexados:
 

... nesta parte do código é um problema de nova compilação (erro ---> 'MarketInfo' - tipo de expressão de mudança ilegal) talvez tudo estivesse bem até a atualização para MT4 build 600+ ... mas desde então não funciona mais.

// Function to Determine Pip Point Value in Account Currency

        double dblPipValue( string strSymbol )
        {
                double dblCalcPipValue = dblTickValue( strSymbol );
                switch ( MarketInfo( strSymbol, MODE_DIGITS ) )
                {
                        case 3:
                        case 5:
                                dblCalcPipValue *= 10;
                                break;
                }
                
                return( dblCalcPipValue );
        }
        

Então, você poderia por favor postar uma versão mais nova ... se, é claro, você ainda estiver por perto.