9 min read

The Simplest Way to Manage Your Expert Advisor Trades on MetaTrader

Learn how to use your Expert Advisor to manage all your open trades. Super simple, and super helpful.
The Simplest Way to Manage Your Expert Advisor Trades on MetaTrader
Title Image for the Series "Build Your Own MetaTrader 5 Expert Advisor". Built using Leonardo.ai

So, you’ve developed a fantastic trading algorithm.

You’ve invested time into building it into an Expert Advisor. You’re excited, pumped! It’s go time!

Then you realize something.

How can you make sure your trading bot only trades a certain number of trades?

For instance, if you’re trading the RSI, you might not want to enter every. single. candle. while the RSI stays below your RSI low value.

In this article, I’ll show you how you can get your EA to automanage your trades.


About This Series

In this series, I cover everything you need to build your own advanced Expert Advisor from scratch. I cover:

  • How to get started
  • Using built in technical indicators from MetaTrader
  • Making your EA autotrade
  • Adding some simple-yet-powerful risk management techniques to your EA
  • Backtesting and Optimizing your soon-to-be-awesome algorithm
  • Adding some advanced features

All of the code that I use is available on my public GitHub repo, and each episode contains working code snippets you can immediately use in your own trading bot.

If you’d like some more general help, join our Discord server here, and if you prefer content in a video format, you can check out my YouTube channel here.

Get the Code on GitHub

Get working code on my GitHub, linked below:

GitHub - jimtin/build-your-own-mt5-ea: Learn how to build your own MetaTrader 5 Expert Advisor from Scratch!
Learn how to build your own MetaTrader 5 Expert Advisor from Scratch! - jimtin/build-your-own-mt5-ea

About This Episode

In this episode, I’ll show you a simple way to manage your Expert Advisor trades.

What You’ll Need to Complete This Episode

  1. A working MT5 terminal
  2. A working algorithm which is autotrading. If you’d like to learn how to build one using the RSI, check out this article.
💡
All trading is at your own risk, and in no way shape or form should you consider any of what I write to be investment or trading advice. My goal is to simply educate and inform, not provide investment advice.

Why You Need Trade Management in Your Expert Advisor

When you set your Expert Advisor to autotrade, you are handing over your trading decisions to your trading bot. While this can be a great thing, and many traders use it to eliminate things like emotions and downtime while sleeping, it also means that you need a way to manage your trades.

For instance, in previous episodes, I’ve been demonstrating how to build an autotrading EA that uses the RSI technical indicator. Without order management, I could end up with a situation where my trading bot keeps opening up trades every time the RSI goes above or below the RSIHigh and RSILow values I’ve set.

To demonstrate, have a look at this screenshot of all my trades:

No order management

While this is an extreme example where I was using the Current Close value, it does a demonstrate a critical requirement for my trading bot EA:

I need a way to restrict how many trades my Expert Advisor enters simultaneously

Without it I am at risk of:

  • Stacking my losses
  • Generating margin calls (especially if my lot size was greater than 0.1)
  • Losing track of my risk management

So let’s start adding in some order management


Adding Trade Management to Your Trading Bot

For the simplest of order management approaches, there are two items we must manage:

  • Orders — these are trades we have proposed but not yet converted into positions. This is more relevant if you are using Stop trades, such as a Buy Stop or Sell Stop.
  • Positions — these are trades where we have converted a BUY or SELL order into an actual position. I.e. we have $$$ on the line!

The Trade Management Function

In the interests of keeping all our code nice and neat, we will be collecting all our order management into one function: TradeManagement(). This function will be responsible for:

  • Managing the concurrent number of trades we have (this episode)
  • Managing current open positions (in a later episode)
  • Tracking the number trades made in a single session (in a later episode)
To manage the concurrent number of trades, we need to make sure that the sum of orders and positions is less than or equal to the number of trades we desire.

Getting Your EA to Manage the Number of Concurrent Trades You Enter

To get started, we’re going to assume that your EA should not allow any more than one trade to be active at any given time.

Add the code below to your EA, above the OnTick() function if you are following the series:

//+------------------------------------------------------------------+
//| TradeManagement Function                                         |
//+------------------------------------------------------------------+
bool TradeManagement(){
    // Get the total number of orders
    int totalOrders = OrdersTotal();
    // Get the total number of positions
    int totalPositions = PositionsTotal();
    // If there are no orders or positions, return true
    if(totalOrders == 0 && totalPositions == 0){
        return(true);
    }else{
        int totalTrades = totalOrders + totalPositions;
        if (totalTrades < 1){
            return (true);
        }else{
            return (false);
        }
    }
}

This function:

  1. Gets the number of existing orders and positions
  2. Sums them together
  3. Returns true if the number of trades is below the threshold of 1
  4. Returns false otherwise

Update OnTick()

Next, we need to incorporate these updates into the OnTick() function. For code efficiencies sake, we’re going to make a design decision here that the first check that OnTick() will make is to see if it can do any more trades.

Update your OnTick() so that it looks like this:

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
    bool tradeManagement = TradeManagement();
    if(tradeManagement == true){
        double rsi = GetRSI();
        string signal = RSIAlgorithm(rsi);
        bool success = OnSignal(signal);
    }
}

Compile + Run 💻

Compile your code and add it to your MT5.

Congratulations, you’ve just added some simple Trade Management to Your EA!


Make Trade Management More Dynamic

Of course, you might prefer to a have different number of trades open. Depending on what you’re trying to do with your trading, maybe you want 2 or even 3 trades open at a time.

To do this, we’ll be adding a new input parameter to your trading bot.

Start by adding this line to the bottom of all your current input parameters:

input int concurrentTrades = 1;                 // Maximum number of concurrent trades

Then, update your TradeManagement() function to include this input parameter, as follows:

//+------------------------------------------------------------------+
//| TradeManagement Function                                         |
//+------------------------------------------------------------------+
bool TradeManagement(){
    // Get the total number of orders
    int totalOrders = OrdersTotal();
    // Get the total number of positions
    int totalPositions = PositionsTotal();
    // If there are no orders or positions, return true
    if(totalOrders == 0 && totalPositions == 0){
        return(true);
    }else{
        int totalTrades = totalOrders + totalPositions;
        if (totalTrades < concurrentTrades){
            return (true);
        }else{
            return (false);
        }
    }
}

Compile + Run 💻

Compile your code and test it out.


Wrapping Up

By now you’ve got a fully featured EA which will happily trade away whenever the markets for your chose asset are open.

Pretty cool!

However, you might be wondering:

How could I test this algorithm to see if it actually works?

In the next episode, I’ll show you how to use the built in MT5 backtester to learn how to do that.

List of Articles in this Series

  1. Build Your Own AutoTrading MetaTrader 5 Expert Advsior
  2. The Easiest Way to Add the RSI Indicator to Your MetaTrader 5 EA
  3. The Easiest RSI Algorithm for Your MetaTrader Expert Advisor
  4. The Easiest Way to Place BUY and Sell Orders with your MetaTrader EA
  5. The Simplest Way to Manage Your Expert Advisor Trades on MetaTrader
  6. Four Simple Steps to Backtest and Optimize Your EA on MetaTrader 5

Connect With Me

My name is James, and you’ll often see me online using the AppnologyJames handle. Although my background and training is in Cyber Security, I’ve spend the last few years building trading algorithms for clients, along with a powerful market analysis platform called TradeOxy.

I love hearing from my readers and viewers, so feel free to reach out and connect with me:

Full Code for this Article

//+------------------------------------------------------------------+
//|                                  RSI_EA_from_TradeOxy.mq5        |
//|                              AppnologyJames, TradeOxy.com        |
//|                                  https://www.tradeoxy.com        |
//+------------------------------------------------------------------+

// CTrade Class
#include <Trade\Trade.mqh>

input bool liveRSIPrice = false;                // Use live RSI price?
input int rsiHigh = 70;                         // RSI High threshold
input int rsiLow = 30;                          // RSI Low threshold
input int takeProfitPips = 20;                  // Take Profit in Pips
input int stopLossPips = 10;                    // Stop Loss in Pips
input double lotSize = 0.1;                     // Lot Size
input int concurrentTrades = 1;                 // Maximum number of concurrent trades

// Declare Global Variables
CTrade trade;                                   // Trade Object

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    // Print the name of the Expert Advisor and a Welcome message
    Print("RSI Trading Bot Expert Advisor from TradeOxy.com");
    // Return value of initialization
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // Deinitialization code
    Print("Expert advisor deinitialized. Reason: ", reason);
}


//+------------------------------------------------------------------+
//| GetRSI                                                           |
//+------------------------------------------------------------------+
double GetRSI()
{
    // Initialize a buffer
    double rsiBuffer[];
    // Make it into an array
    ArraySetAsSeries(rsiBuffer, true);
    // Get the RSI Handle
    int rsiHandle = iRSI(_Symbol, _Period, 14, PRICE_CLOSE);
    // If the handle is invalid, return 0
    if (rsiHandle == INVALID_HANDLE)
    {
        return(0);
    }
    // Copy the RSI values to the buffer
    int rsiCount = CopyBuffer(rsiHandle, 0, 0, 2, rsiBuffer);
    // If the copy failed, return 0
    if (rsiCount == 0)
    {
        return(0);
    }
    // Get the actual RSI value
    if(liveRSIPrice == true)
    {
        double rsi = rsiBuffer[0];
        return(rsi);
    }else{
        double rsi = rsiBuffer[1];
        return(rsi);
    }
}


//+------------------------------------------------------------------+
//| RSIAlgorithm Function                                            |
//+------------------------------------------------------------------+
string RSIAlgorithm(double rsiValue){
    // See if the value is below the 30 threshold
    if(rsiValue < rsiLow){
        return("BUY");
    // See if the value is above the 70 threshold
    }else if (rsiValue > rsiHigh){
        return("SELL");
    // Otherwise return HOLD
    }else{
        return("HOLD");
    }
}


//+------------------------------------------------------------------+
// OnSignal Function                                                 |
//+------------------------------------------------------------------+   
bool OnSignal(string signal){
    // Get the current ask price
    double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    // Get the pip size for the current symbol
    double pointSize = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
    // Multiply the point size by 10 to get pips
    double pipSize = pointSize * 10;
    // Get the Take Profit, which is the pipSize * takeProfitPips
    double takeProfitSize = pipSize * takeProfitPips;
    // Get the Stop Loss, which is the pipSize * stopLossPips
    double stopLossSize = pipSize * stopLossPips;
    if(signal == "BUY"){
        // Make the Take Profit above the current price
        double takeProfit = ask + takeProfitSize;
        // Make the Stop Loss below the current price
        double stopLoss = ask - stopLossSize;
        // Open a Buy Order
        trade.Buy(lotSize, _Symbol, ask, stopLoss, takeProfit, "RSI Tutorial EA");
        return(true);
    }else if(signal == "SELL"){
        // Make the Take Profit below the current price
        double takeProfit = ask - takeProfitSize;
        // Make the Stop Loss above the current price
        double stopLoss = ask + stopLossSize;
        // Open a Sell Order
        trade.Sell(lotSize, _Symbol, ask, stopLoss, takeProfit, "RSI Tutorial EA");
        return(true);
    }else if (signal == "HOLD"){
        return(true);
    }else{
        return(false);
    }
}


//+------------------------------------------------------------------+
//| TradeManagement Function                                         |
//+------------------------------------------------------------------+
bool TradeManagement(){
    // Get the total number of orders
    int totalOrders = OrdersTotal();
    // Get the total number of positions
    int totalPositions = PositionsTotal();
    // If there are no orders or positions, return true
    if(totalOrders == 0 && totalPositions == 0){
        return(true);
    }else{
        int totalTrades = totalOrders + totalPositions;
        if (totalTrades < concurrentTrades){
            return (true);
        }else{
            return (false);
        }
    }
}


//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
    bool tradeManagement = TradeManagement();
    if(tradeManagement == true){
        double rsi = GetRSI();
        string signal = RSIAlgorithm(rsi);
        bool success = OnSignal(signal);
    }
}