Help with converting William Roeder MT4 code to MT5

 

I am trying to calculate Lot Volume in mt5 based on risk% and stop loss based on ATR(14), also i need pip value for the current instrument.

I am new to MT4/5 and C++, but i have managed to learn a lot and have managed to convert an MT4 Oscar indicator to work in MT5.

1. I have seen the code below posted several times for MT4, and it looks interesting to convert to work in MT5 so i can back-test indicators and my algorithm, and was wondering if this was still an efficient way to calculate the lot size?

2. I am having difficulty understanding a few things, from my studies I have been told that to calculate these things you need to take into account whether the account currency, matches the base currency or counter currency as these affect the result and conversions are necessary. I do not understand how this is handled in this code. Any help would be grateful?

3. What is void    InInitLotSize(), should this be placed somewhere else in an EA?

4. Where does MM_Fix0_Mod1_Geo2 come from?

5. What is ComputeTEF and TEF_value?

6. Where is the Stop loss entered, is it maxRisk = MM_MaxRisk?

7. - You must normalize lots properly and check against min and max. What are min and max?

I tried messaging William Roeder, but he does not accept messages.

//+------------------------------------------------------------------+
//| Lot size computation_                                            |
//+------------------------------------------------------------------+
void    InInitLotSize()
{
    equity_at_risk = 0; balance_at_risk = 0;  chart_at_risk = 0;
}
double  LotSize(double risk)
{
/*double    at_risk_new;                        // Export to init/start
   //double    TEF_value,                          // Import from ComputeTEF
   //          equity_at_risk                      // \ Import from
   //double    chart_at_risk,  balance_at_risk;    // / ModifyStops
   //int       op_code; // 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
     **************************************************************************/
    /*++++ Compute lot size based on account balance and MM mode*/ {
        double ab = AccountEquity() - equity_at_risk;
        switch (MM_Fix0_Mod1_Geo2)
        {
        case MMMODE_FIXED:                                              double
            perChrt = MM_PerChart,
            maxRisk = MM_MaxRisk;
            break;
        case MMMODE_MODERATE:
            // See http://articles_mql4_com/631 Fallacies, Part 1: Money
            // Management is Secondary and Not Very Important_
            maxRisk = MathSqrt(MM_MaxRisk * ab);
            perChrt = MathSqrt(MM_PerChart * ab);
            break;
        case MMMODE_GEOMETRICAL:
            perChrt = MM_PerChart * ab;
            maxRisk = MM_MaxRisk * ab;
            break;
        }
        ComputeTEF();
        double minLot  = MarketInfo(Symbol(), MODE_MINLOT),
               lotStep = MarketInfo(Symbol(), MODE_LOTSTEP),
        //perLotPerPoint  = PointValuePerLot(),
               perLotPerPoint = DeltaValuePerLot(),
               maxLossPerLot  = (risk + Slippage_Pips * pips2dbl) * perLotPerPoint,
               size           = perChrt / maxLossPerLot; // Must still round to lotStep_
               
        /*---- Compute lot size based on account balance and MM mode*/ }
    /* 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_ Using the lesser of size vs
    * AccountFreeMargin / MODE_MARGINREQUIRED should have been sufficient, but
    * the tester was generating error 134 even when marginFree should have been
    * Ok. So I also use AccountFreeMarginCheck < 0 which agrees with the
    * tester_ Reported at http://forum_mql4_com/35056
    *
    * Second problem, after opening the new order, if free margin then drops to
    * zero we get a margin call_ In the tester, the test stops with: "EA:
    * stopped because of Stop Out" So I make sure that the free margin
    * after is larger then the equity risk so I never get a margin call_ */
    
    string status = "SL>AE"; // Assume size < minLot
    while (true)             // Adjust for broker, test for margin, combine with TEF___
    {
        size        = MathFloor(MathMax(0, size) / lotStep) * lotStep;
        at_risk_new = size * maxLossPerLot;             // Export for Comment
        if (size < minLot)
        {
            at_risk_new = 0;    EA_status = status; return(0);
        }

        /* equity_at_risk  += Direction( OrderType() )
         *                  * (OrderClosePrice()-OrderStopLoss())*perPoint;
         * Summed for all open orders_
         * balance_at_risk   += Direction( OrderType() )
         *                  * (OrderOpenPrice()-OrderStopLoss())*perPoint;
         * Summed for all open orders below BE_
         * chart_at_risk is summed for all open orders below BE, this pair/TF */
         
        if (at_risk_new + chart_at_risk > perChrt)              // one pair, one TF
        {
            size   = (perChrt - chart_at_risk) / maxLossPerLot; // Re-adjust lotStep
            status = "PerChrt";     continue;
        }

        if (at_risk_new + balance_at_risk > maxRisk)            // All charts
        {
            size   = (maxRisk - balance_at_risk) / maxLossPerLot;
            status = "MaxRisk";     continue;
        }

        double AFMC  = AccountFreeMarginCheck(Symbol(), op_code, size),
               eRisk = equity_at_risk + at_risk_new;
        if (AFMC * 0.99 <= eRisk)
        {
            size *= 0.95;   status = "Free Margin";
            continue;
        }                   // Prevent margin call if new trade goes against us_
        break;
    }
    if (TEF_Enable01 > 0)
    {
        size = MathFloor(size * MathMin(1, TEF_value) / lotStep) * lotStep;
        if (oo_count == 0 && size < minLot)
            size = minLot;                                  // Not below min
        at_risk_new = size * maxLossPerLot;                 // Export for Comment
        if (size < minLot)
        {
            at_risk_new = 0;  EA_status = "TEF = " + TEF_value;
            return(0);
        }
    }
    return(size); // We're good to go_
}                 // 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_
 *
 * http://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_
   }  */

/*
   Simon Gniadkowski  ? =RaptorUK
   If I understand correctly you keep track of the equity at risk ( ModifyStops() ) not only for the chart
   where the EA is placed (chart_at_risk) but also for all orders placed on all charts (equity_at_risk) ?
   In the calculation of the equity you use a variable called perLotPerPoint this comes from a function
   PointValuePerLot(), looking at this function it only works on the current chart symbol
   _ _ _ so I'm a little confused how equity_at_risk can be correct ?

   whroeder1 2011.08.04 13:50 #19
   Nice catch_ Obviously PointValuePerLot() isn't right for other pairs and the calculation can't be correct_

   The idea was to avoid margin calls when opening multiple trades (ie grid trading)_ Calculation result is
   used in LotSize() with AccountFreeMarginCheck()

   This expanded to same pair/other time frames and then to other possible pairs_

   Passing the symbol fixes the function and the variable is no longer a constant so must be inside the loop_
 */
// I renamed PointValuePerLot to DeltaValuePerLot since aCurrencyChange = aPriceChange * OrderSize() * DeltaValuePerLot()_ Also added more comments_
/*
   double  PipValuePerLot(string pair = "")
   {
    return(DeltaValuePerLot(pair) * pips2dbl);
   }
 */
double  DeltaValuePerLot(string pair = "")
{
    /* Value in account currency of a Point of Symbol_
    * In tester I had a sale: open=1_35883 close=1_35736 (0.0147)
    * 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.0/pip_
    *
    * https://www_mql5_com/en/forum/127584 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.0001 respectively, I've seen this
    * (intermittently) change to 14.00 and 0.0002 respectively (just example
    * tick values to illustrate)_
    * https://www_mql5_com/en/forum/135345 zzuegg reports for non-currency DE30:
    * MarketInfo(Symbol(),MODE_TICKSIZE) returns 0.5
    * MarketInfo(Symbol(),MODE_DIGITS) return 1
    * Point = 0.1
    * Prices to open must be a multiple of ticksize */
    if (pair == "")
        pair = Symbol();
    return(MarketInfo(pair, MODE_TICKVALUE)
           / MarketInfo(pair, MODE_TICKSIZE));  // Not Point_
}     /*

- You place the stop where it needs to be - where the reason for the trade is no longer valid.
- Account Balance * percent = RISK = |OrderOpenPrice - OrderStopLoss| * OrderLots * - DeltaPerlot (Note OOP-OSL includes the SPREAD)
- Do NOT use TickValue by itself - DeltaPerlot
- You must normalize lots properly and check against min and max.
- You must also check FreeMargin to avoid stop out

*/
Reason: