função de cálculo automático de tamanho de lote?

 

Olá a todos, de volta para incomodá-los. :-) Alguém teria uma pequena função MQL4 que calcula automaticamente o tamanho do lote (para qualquer símbolo) com base na % de risco do meu patrimônio líquido disponível, e meu tamanho de perda desejado em pips?


Obrigado!

Shawn

 
 


Obrigado Phillip! Mas parece que o código teve alguns problemas com os pares JPY. Será que isso foi resolvido?


Obrigado

Shawn

 
shawnh:


Obrigado Phillip! Mas parece que o código teve alguns problemas com os pares JPY. Será que isso foi resolvido?


Obrigado

Shawn




Não tenho idéia do que você está se referindo? Funciona bem com pares JPY. Como com qualquer código ao qual você possa confiar seu dinheiro, você deve investigar o código e confirmá-lo correto com alguns cálculos manuais. O código é correto, mas não é à prova de tolices :)

 

1. Uma amostra: Cálculo do tamanho do lote https://www.mql5.com/en/code/8583

2. AIS1 Robô comercial https://www.mql5.com/en/code/8700

//< 7.7.2. Risk Management > //<192>
//< 7.7.3. Operation Size Control > //<202>

 
shawnh:

Alguém teria uma pequena função MQL4 que calcula automaticamente o tamanho do lote (para qualquer símbolo) com base no % de risco do meu patrimônio líquido disponível, e o tamanho de minha perda desejada em pips?

//+------------------------------------------------------------------+
//| Lot size computation.                                            |
//+------------------------------------------------------------------+
double  LotSize(double risk){
/*double    TEF.value,                          // Import from ComputeTEF
//double    at.risk;                            // Export to init/start
//bool      need2refresh;                       // Import from RelTradeContext
//int       op.code; // -1/OP_BUY/OP_SELL       // Import from setDIR */
    /* This function computes the lot size for a trade.
     * Explicit inputs are SL relative to bid/ask (E.G. SL=30*points,)
     * Implicit inputs are the MM mode, the MM multiplier, count currently
     * filled orders by all EA's vs this EA/pair/period count and history.
     * Implicit inputs are all used to reduce available balance the maximum
     * dollar risk allowed. StopLoss determines the maximum dollar risk possible
     * per lot. Lots=maxRisk/maxRiskPerLot
     **************************************************************************/
    if (need2refresh)   Refresh();
    /*++++ Compute lot size based on account balance and MM mode*/{
    double  ab  = AccountBalance();
    switch(Money.Management.F0M1G2){
    case MMMODE_FIXED:
        at.risk = Money.Management.Multiplier;
        break;
    case MMMODE_MODERATE:
        // See https://www.mql5.com/en/articles/1526 Fallacies, Part 1: Money
        // Management is Secondary and Not Very Important.       // %used/trade=
        at.risk = MathSqrt(Money.Management.Multiplier * ab)/ab; // ~const rate.
        at.risk = MathSqrt(Money.Management.Multiplier * ab
                            * MathPow( 1 - at.risk, OrdersTotal() ));
        break;
    case MMMODE_GEOMETRICAL:
        at.risk = Money.Management.Multiplier * ab *
                MathPow(1 - Money.Management.Multiplier, OrdersTotal());
        break;
    }
    double  maxLossPerLot   = risk * PointValuePerLot(),
    /* Number of lots wanted = at.risk / maxLossPerLot rounded/truncated to
     * nearest lotStep size.
     *
     * However, the broker doesn't care about the at.risk/account balance. They
     * care about margin. Margin used=lots used*marginPerLot and that must be
     * less than free margin available. */
            marginFree      = AccountFreeMargin(),
            marginPerLot    = MarketInfo( Symbol(), MODE_MARGINREQUIRED ),
    // So I use, the lesser of either.
            size = MathMin(marginFree / marginPerLot, at.risk / maxLossPerLot),
            minLot  = MarketInfo(Symbol(), MODE_MINLOT),
            LotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
    /*---- Compute lot size based on account balance and MM mode*/}
    double  adjFact = IfD(MathMin(1, TEF.value), 1, TEF.Enable01);
    while (true){   // Adjust for broker, test for margin, combine with TEF
        size =  MathFloor(size/LotStep)*LotStep;
        if (size < minLot){ // Insufficient margin.
            Print(
            "LotSize(SL=", DoubleToStr(risk/pips2dbl, Digits.pips), ")=",
            size, " [risk=", at.risk, AccountCurrency(),    "/", maxLossPerLot,
                    ", margin=",    marginFree,             "/", marginPerLot,
                    ", MMM=",       Money.Management.F0M1G2,"x",
                    Money.Management.Multiplier,    ", OO=",   OrdersTotal(),
                "]" );
            size=0; break;  }
        /* size<minLot should be sufficient, but the tester was generating error
         * 134 even when marginFree should have been OK. So I also use
         * AccountFreeMarginCheck which aggrees with the tester.
         * https://forum.mql4.com/35056 */
        double AFMC = AccountFreeMarginCheck(Symbol(), op.code, size);
        /**/ if (AFMC < 0)      size *= 0.95;
        else if (adjFact < 1){  size  = MathMax(minLot,size*adjFact);adjFact=1;}
        else break; // We're good to go.
    }
    at.risk = size * maxLossPerLot;                     // Export for Comment
    return(size);
}   // LotSize
double PointValuePerLot() { // Value in account currency of a Point of Symbol.
    /* In tester I had a sale: open=1.35883 close=1.35736 (0.00147)
     * gain$=97.32/6.62 lots/147 points=$0.10/point or $1.00/pip.
     * IBFX demo/mini       EURUSD TICKVALUE=0.1 MAXLOT=50 LOTSIZE=10,000
     * IBFX demo/standard   EURUSD TICKVALUE=1.0 MAXLOT=50 LOTSIZE=100,000
     *                                  $1.00/point or $10.00/pip.
     *
     * https://forum.mql4.com/33975 CB: MODE_TICKSIZE will usually return the
     * same value as MODE_POINT (or Point for the current symbol), however, an
     * example of where to use MODE_TICKSIZE would be as part of a ratio with
     * MODE_TICKVALUE when performing money management calculations which need
     * to take account of the pair and the account currency. The reason I use
     * this ratio is that although TV and TS may constantly be returned as
     * something like 7.00 and 0.00001 respectively, I've seen this
     * (intermittently) change to 14.00 and 0.00002 respectively (just example
     * tick values to illustrate). */
    return(  MarketInfo(Symbol(), MODE_TICKVALUE)
           / MarketInfo(Symbol(), MODE_TICKSIZE) ); // Not Point.
}
 

Phillip, coloquei seu código no meu EA e ele funciona lindamente - muito obrigado. Obrigado também ao AIS e ao WHRoeder por suas respostas!


Abraço

Shawn

 

Fico feliz em ouvir isso, Shawn!

Estou continuamente mexendo nos códigos, se você quiser uma versão mais recente (não há bugs nos que você tem) eu ficaria mais do que feliz em compartilhá-la.

As mudanças se concentram principalmente em facilitar a integração e o uso do arquivo com seu EA existente. Uma vez que você já conseguiu implementar o outro, isso pode não fazer nenhuma diferença para você agora.

 

Phillip, eu adoraria que o novo "mais fácil de usar" incluísse arquivo, você poderia postá-lo ou enviá-lo para mim, estou tentando fazer isso hoje mesmo.

Obrigado!

 

Claro, eu a postarei quando voltar ao computador que tem meus códigos.

Provavelmente eu também deveria carregá-lo para o banco de códigos agora que penso nisso.

 

Etapa 1: Coloque todos os anexos do arquivo deste posto em seu caminho de inclusão (...perito inclui*.mqh)

Passo 2: Adicione o seguinte ao topo de sua EA para que ela tenha acesso às funções de chamada contidas nos arquivos anexos

#include <OrderReliable_2010.10.12.mqh>
#include <Trade_Position_Management_2010.10.29.mqh>

Etapa 3: Para calcular os lotes com base em uma quantia orçada de capital próprio para o risco, acrescente o seguinte

   // Determine position lotsize based on order direction and market prices
   double CurrentEquityAtRisk=(MaxPercentEquityAtRisk/100.)*AccountBalance();
   double CurrentLotSize=LotSize(CurrentEquityAtRisk,OpenPrice_ND,StopLossPrice_ND,CurrentOrderType); // Compute the max possible lotsize for the risk equity
   Print("Max allowed EquityAtRisk = $",DoubleToStr(CurrentEquityAtRisk,2)," and Max computed Lotsize = ",CurrentLotSize);
   CurrentLotSize=NormalizeLotSize(CurrentLotSize);   // Normalize the lotsize to conform with the Broker's specific quantized position allowances
   if(CurrentLotSize<MarketInfo(CurrentSymbol,MODE_MINLOT)) CurrentLotSize=MarketInfo(CurrentSymbol,MODE_MINLOT);
   if(CurrentLotSize> MarketInfo(CurrentSymbol,MODE_MAXLOT)) CurrentLotSize=MarketInfo(CurrentSymbol,MODE_MAXLOT);

Assumindo que você tenha definido MaxPercentEquityAtRisk em algum lugar em sua EA como sendo o patrimônio líquido máximo permitido para colocar em risco de perda completa por operação caso as paradas sejam atingidas, esta porção de código determinará primeiro o tamanho máximo de lotes com base no preço aberto e no preço de stoploss (não pips mas o preço real de mercado, o mesmo que você envia em seu pedido ao corretor) e então determinará o tamanho máximo de posição que o corretor aceitará enquanto não exceder seu patrimônio líquido de risco orçado.

Passo 4: Se você gosta de ter os resultados dos cálculos impressos em seu registro ou adicionados ao negócio como um comentário de ordem, você também pode adicionar o seguinte

   // Determine the actual equity at risk of total loss for the position's normalized lotsize
   CurrentEquityAtRisk=EquityAtRisk(CurrentLotSize,OpenPrice_ND,StopLossPrice_ND,CurrentOrderType);
   if(TakeProfitBidPrice>0.01)
      {
      CurrentProfitPotential=ProfitPotential(CurrentLotSize,OpenPrice_ND,TakeProfitPrice_ND,CurrentOrderType);
      Print("Current EquityAtRisk = $",DoubleToStr(CurrentEquityAtRisk,2)," and Current Lotsize = ",CurrentLotSize," and Profit Target = $"
            ,DoubleToStr(CurrentProfitPotential,2)," for a ",DoubleToStr(CurrentProfitPotential/CurrentEquityAtRisk,1),":1 Profit:Loss ratio");
      Order_Comment=StringConcatenate("EaR = $",DoubleToStr(CurrentEquityAtRisk,2)," & Profit = $",DoubleToStr(CurrentProfitPotential,2));
      }
   else
      {
      Print("Current EquityAtRisk = $",DoubleToStr(CurrentEquityAtRisk,2)," and Current Lotsize = ",CurrentLotSize);
      Order_Comment=StringConcatenate("EquityAtRisk = $",DoubleToStr(CurrentEquityAtRisk,2));
      }

Etapa 5: Faça seu pedido (utilizando o método de encomenda confiável)

   // Place the order
   ticket = OrderSendReliable(CurrentSymbol,CurrentOrderType,CurrentLotSize,OpenPrice_ND,MarketInfo(CurrentSymbol,MODE_SPREAD)
            ,StopLossPrice_ND,TakeProfitPrice_ND,Order_Comment,0,0,Aqua);

https://c.mql5.com/mql4/forum/2010/10/OrderReliable_2010.10.12.mqh

Razão: