MT4 EA Course: ATR Stops And Position Sizing

This article is part of a series. Here are the other parts:

 

Welcome to the fifth part of our MetaTrader4 Expert Advisor course! If you haven’t done so, please have a look at the previous instalments.

Forex Wall-E

 

Note: Do you have a trading strategy you want to automate using expert advisors? I can help with the development! Have a look at my MetaTrader 4 Expert Advisor development services and get in touch today to make your project a success!

 

We’ve been doing pretty well with our expert advisor. We created a fully functioning EA that can make buy and sell orders, and also can trail our stops. However, up until now, we’ve always used a fixed stop loss of 50 pips.

 

That might often be ok but what if you want a dynamic stop loss? In order to better reflect the market dynamics, we could use a volatility indicator such as ATR (Average True Range) to determine our stop-loss.

 

When we use dynamic stop loss distances, we still want to keep our risk per trade the same. We do this using dynamic position sizing. In other words, we will change the lot size per trade to reflect our desire to use a 1% stop loss. Let’s see how we can add this to our Wall-E expert advisor!

 

 

ATR-based Dynamic Stops

 

Let’s refresh what we’ve been doing so far. Up until now, we’ve always created a stop loss of 50 pips (or 500 points), like this:

 

    int stopLoss = 500;

 

This is fine to start with, but it doesn’t take into account the volatility of the market. Additionally, if we want to trade this expert advisor on the 10-minute chart, it will obviously need a different stop than when we trade this on the daily charts. 50 pips is definitely not a one size fits all value.

 

We can solve this by using the ATR indicator. The ATR indicator is a technical analysis indicator that shows us the volatility of the market over a specific period. It doesn’t show the direction of the market, just whether that market is volatile or not. It uses the range of price movements to determine this.

 

 

 

How can we use this ATR indicator? We would create a stop loss distance that is a multiple of this ATR value. That way, whenever the market is more volatile, our stop loss will be bigger and when the market is consolidating, it will use a tighter stop loss. Here’s how we can do this:

 

    // Here, we fetch the current 3-period ATR value
    double atr = iATR(NULL, 0, 3, 0);

    // Since the stop loss will be a multiple of this ATR value,
    // we define this multiple. 2.5 times the ATR value
    // is often a good start:
    double atrMultiple = 2.5;

    // Now, we set our stop loss.
    // We multiply the ATR value by the ATR multiple
    // and divide by the Point constant
    // in order to get a value in points:
    int stopLoss = (int)(atr * atrMultiple / Point);

    // And, since we have a dynamic stop loss value,
    // it makes sense to use the same pips amount as our take profit
    int takeProfit = stopLoss;

 

There we go. Keep in mind that we are still using a fixed lot size of 0.01. A quick backtest shows us promising results:

 

 

However, as you can see, we start with $10,000 and only end at $10,166, after a total of almost 250 trades. There’s nothing wrong with that, but this is clearly still a reflection of our small lot size we’re using. Let’s see how we can change this in order to take a 1% risk per trade.

 

 

Dynamic Position Sizing

 

We have just managed to make our stop losses dynamic but due to that and the fact that we use a fixed lot size, we are risking different amounts per trade. That’s not ideal, as we would prefer to take the same percentage amount of risk with every trade.

 

Let’s assume our risk per trade should be 1%. If we have a trading account that is $1,000, every trade will be just 1% of that $1,000, so we risk $10 per trade if the price hits our stop loss. A low-risk stop is one of the hallmarks in a solid trading strategy so that sounds good, but how do we implement this in our code?

 

 

The calculateLotSize Function

 

The first thing we need to change is to add a new function, called calculateLotSize(). We can add this to the bottom of our expert advisor file:

 

/**
* Calculate the amount of lots needed based on stop loss
*
* @return double
*/
double calculateLotSize(int stopLoss)
{
    // 1% risk per trade
    int risk = 1;
    
    // Fetch some symbol properties
    double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
    double minLot  = MarketInfo(Symbol(), MODE_MINLOT); 
    double maxLot  = MarketInfo(Symbol(), MODE_MAXLOT);
    double tickVal = MarketInfo(Symbol(), MODE_TICKVALUE);

    // Calculate the actual lot size
    double lotSize = AccountBalance() * risk / 100 / (stopLoss * tickVal);

    return MathMin(
        maxLot,
        MathMax(
            minLot,
            NormalizeDouble(lotSize / lotStep, 0) * lotStep // This rounds the lotSize to the nearest lotstep interval
        )
    ); 
}

 

Since this is the most complex part of the code of this chapter, let’s go over this one by one. First, we define how much our risk per trade should be, in our case 1 per cent. This risk variable will be used in the lot size calculation a few lines down.

 

    int risk = 1;

 

Next up, we are fetching a number of properties of the current symbol in order to calculate how much our lot size should be. The most important one here is tickVal, which holds the price of a single tick of this symbol. Then, we calculate the actual lot size. In order to do this, we fetch the account balance, take one per cent of that balance so we have the maximum dollar amount of risk we want to take. Then, we divide this value by the price of our stop in order to get to the lot size:

 

    // Fetch some symbol properties
    double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
    double minLot  = MarketInfo(Symbol(), MODE_MINLOT); 
    double maxLot  = MarketInfo(Symbol(), MODE_MAXLOT);
    double tickVal = MarketInfo(Symbol(), MODE_TICKVALUE);

    // Calculate the actual lot size
    double lotSize = AccountBalance() * risk / 100 / (stopLoss * tickVal);

 

Finally, we use the minimum lot and maximum lot limits so we don’t try to open an order that is too big or too small and round the lot size value to the nearest lot step. An example where this would be useful would be for example on the DAX, where the minimum lot size is 0.1, then 0.2, 0.3 etc. The last step makes sure we don’t use lot size values like 0.05, 0.13 and so on, which would not be accepted by our broker.

 

    return MathMin(
        maxLot,
        MathMax(
            minLot,
            NormalizeDouble(lotSize / lotStep, 0) * lotStep // This rounds the lotSize to the nearest lotstep interval
        )
    );

 

 

Using Dynamic Lot Sizes

 

Now that we have our lot size calculation function, we only need to update one piece of the code, where we defined our lot size. Remember that it looked like this:

 

    double lots = 0.01;

 

We will update this line, so it uses our new lot size function instead of a fixed lot amount:

 

    double lots = calculateLotSize(stopLoss);

 

Just make sure that you have already defined the stopLoss variable, which means that you might need to move the above line a few lines below the stop loss calculation. But that’s it, we have finished all of our changes needed in order to implement both dynamic stop losses based on ATR and dynamic lot sizes in order to always use a 1% risk per trade!

 

You can find the full code of our updated ForexWall-E expert advisor here.

 

 

Conclusion

 

Now that we have implemented everything, let’s have another look at our equity graph:

 

 

As you can see, over the same 250 trade period, we are now able to run up our initial $10,000 balance to a much nicer $12,586! These are profits we can start to be a bit proud of! Also notice that a new panel has been added to the bottom of the equity graph, indicating how the lot size varies, depending on the position we are taking.

 

Our expert advisor is getting better and better results! Let’s recap what we have done in this chapter:

 

  • We’ve recognized that, in order to accommodate the changing volatility of the markets, it’s better to use a dynamic stop loss
  • We’ve used a multiple of the ATR indicator as a dynamic stop loss value that incorporates this volatility
  • We learned why we should use dynamic position sizing: to keep an equal risk per trade, regardless of our stop loss distance
  • We’ve implemented dynamic position sizing, a.k.a. dynamic lot sizing, using a new calculateLotSize() function

 

Stay tuned for the next chapter, where we will have a look at using configuration parameters for a number of settings. If you have questions, please let me know in the comments or use the contact form!

 

I can help with your expert advisor or indicator development! If you have a strategy that you want to have automated, check out my Expert Advisor services page and make sure to get in touch!

Felix

I'm a full-time, independent forex trader. I've been trading for over 10 years and specialize in price action trading, reversal trading, trading psychology and algorithmic trading. If you're determined to become a pro trader, I offer a select pro trading program. When I'm not trading, I'll either be travelling the world or rock climbing (likely both). Read my story here.