funzione di calcolo automatico della dimensione del lotto?

 

Ciao a tutti, di nuovo per assillarvi :-) Qualcuno avrebbe una piccola funzione MQL4 che calcola automaticamente la dimensione del lotto (per qualsiasi simbolo) in base alla percentuale di rischio del mio capitale disponibile e alla dimensione dello stoploss desiderata in pip?


Grazie!

Shawn

 
 


Grazie Phillip! Sembra che il codice abbia avuto qualche problema con le coppie JPY. È stato risolto?


Grazie

Shawn

 
shawnh:


Grazie Phillip! Sembra che il codice abbia avuto qualche problema con le coppie JPY. È stato risolto?


Grazie

Shawn




Non ho idea a cosa ti riferisci? Funziona bene con le coppie JPY. Come con qualsiasi codice a cui potresti affidare i tuoi soldi, dovresti investigare il codice e confermarne la correttezza con alcuni calcoli manuali. Il codice è corretto, ma non è infallibile :)

 

1. Un campione: Calcolo delle dimensioni del lotto https://www.mql5.com/en/code/8583

2. AIS1 Trading Robot https://www.mql5.com/en/code/8700

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

 
shawnh:

Qualcuno avrebbe una piccola funzione MQL4 che calcola automaticamente la dimensione del lotto (per qualsiasi simbolo) in base a quanta % di rischio del mio capitale disponibile, e la mia dimensione di stoploss desiderata in pip?

//+------------------------------------------------------------------+
//| 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, ho messo il tuo codice nel mio EA e funziona meravigliosamente - grazie mille. Grazie anche ad AIS e WHRoeder per le loro risposte!


Saluti

Shawn

 

Mi fa piacere sentirlo Shawn!

Sto continuamente armeggiando con i codici, se vuoi una versione più recente (non ci sono bug in quella che hai) sarei più che felice di condividerla.

I cambiamenti si concentrano principalmente sul rendere il file include più facile da integrare e utilizzare con il tuo EA esistente. Dal momento che sei già riuscito a far implementare l'altro potrebbe non fare alcuna differenza per te ora.

 

Phillip, mi piacerebbe molto quel nuovo file include "più facile da usare", potresti postarlo o mandarmelo, sto cercando di farlo oggi stesso.

Grazie!

 

Certo, lo posterò quando tornerò al computer che ha i miei codici.

Probabilmente dovrei caricarlo anche sul codebank ora che ci penso.

 

Passo 1: Metti tutti i file allegati da questo post nel tuo percorso include (...\experts\include\*.mqh)

Passo 2: Aggiungi quanto segue all'inizio del tuo EA in modo che abbia accesso alle funzioni di chiamata contenute nei file allegati

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

Passo 3: Per calcolare la dimensione del lotto sulla base di un importo di capitale a rischio preventivato, aggiungere quanto segue

   // 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);

Assumendo che tu abbia definito MaxPercentEquityAtRisk da qualche parte nel tuo EA per essere il capitale massimo consentito da mettere a rischio di perdita completa per trade nel caso in cui gli stop vengano colpiti, questa porzione di codice determinerà prima la dimensione massima del lotto basata su openprice e stoplossprice (non pips ma il prezzo effettivo di mercato, la stessa cosa che mandi nel tuo ordine al broker) e poi determinerà la dimensione massima della posizione che il broker accetterà pur non superando la tua equity di rischio preventivata.

Passo 4: Se vi piace avere i risultati dei calcoli stampati nel vostro registro o aggiunti alla negoziazione come commento all'ordine, potete anche aggiungere quanto segue

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

Passo 5: Piazzare l'ordine (usando il metodo ordersendreliable)

   // 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