The Easiest Way to Place BUY and SELL Orders with your MetaTrader EA
Learn how to get your Expert Advisor automatically placing BUY and SELL orders using MQL5
Learn how to get your Expert Advisor automatically placing BUY and SELL orders using MQL5
There comes a point in every Expert Advisors life where the decision has to be made:
Will I just be a signal, or will become an autotrading EA?
If you’ve been following my series, then you’ll know that in the previous article, I showed you how to convert an RSI Indicator into an RSI Signal.
In this episode, I’m going to show you how to convert this signal into an actual trade.
Read on to learn more.
In this series, I cover everything you need to build your own advanced Expert Advisor from scratch. I cover:
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.
In this episode, I’m going to show you a really easy way to make your EA autotrade.
Get the working GitHub code for this series below:
The CTrade class, part of MQL5, is a super simple way to access all the trade functions in MT5.
The CTrade class has access to most, if not all, of the trading functions you might want to use in a trading bot. It’s also much simpler than trying to build a trade from ground up.
We will start by adding the CTrade class to your EA. To do this, add the line below to your EA, right above your input
parameters:
// CTrade Class
#include <Trade\Trade.mqh>
Next, below your inputs, create a global variable called trade that uses the CTrade class. To do this, add the following code:
// Declare Global Variables
CTrade trade; // Trade Object
Now we’re going to move on to creating a simple trade that your EA can execute whenever a trade signal is received.
What would it take for Crypto, AI, and Cyber to truly change the world?
No spam. Unsubscribe anytime.
Before actually creating a trade, I’m going to define some simple risk management parameters we can use to get started. Later on in this article, I’ll show you how to parameterize them so that they can be fine-tuned by you.
Here they are:
OnSignal()
FunctionNext, we’re going to create a new function called OnSignal()
. This function is responsible for dealing with the signals that are detected from your algorithm functions — i.e. RSIAlgorithm()
if you are following this series.
This function is going to perform the following actions:
Here’s the initial framework for your function. It doesn’t really do much, but will allow us to get going:
//+------------------------------------------------------------------+
// OnSignal Function |
//+------------------------------------------------------------------+
bool OnSignal(string signal){
if(signal == "BUY"){
return(true);
}else if(signal == "SELL"){
return(true);
}else{
return(false);
}
}
With the OnSignal()
function framework in place, let’s add in the ability to make BUY and SELL trades on your behalf.
For now, we’ll set all trades to happen at the current market price. In a future episode, I’ll show you how to adjust these trades to use STOP trades.
To update the function, we need to take into account a few things:
Update your OnSignal()
function so that it looks like this. Note how the Pip Size is 10 x the Point Size:
//+------------------------------------------------------------------+
// 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;
if(signal == "BUY"){
// Make the Take Profit 20 pips above the current price
double takeProfit = ask + (pipSize * 20);
// Make the Stop Loss 10 pips below the current price
double stopLoss = ask - (pipSize * 10);
// Open a Buy Order
trade.Buy(0.1, _Symbol, ask, stopLoss, takeProfit, "RSI Tutorial EA");
return(true);
}else if(signal == "SELL"){
// Make the Take Profit 20 pips below the current price
double takeProfit = ask - (pipSize * 20);
// Make the Stop Loss 10 pips above the current price
double stopLoss = ask + (pipSize * 10);
// Open a Sell Order
trade.Sell(0.1, _Symbol, ask, stopLoss, takeProfit, "RSI Tutorial EA");
return(true);
}else{
return(false);
}
}
Now let's add this function to your previously built OnTick()
function.
Update OnTick()
so that it looks like this:
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
double rsi = GetRSI();
string signal = RSIAlgorithm(rsi);
if(signal == "BUY"){
Print("BUY Signal Detected");
bool result = OnSignal(signal);
}else if(signal == "SELL"){
Print("SELL Signal Detected");
bool result = OnSignal(signal);
}
}
Compile you code and see it run.
You may need to wait for the RSI to hit one of the triggers, but once it does, it should work beautifully!
So far, your EA has been using hard-coded amounts for:
However, many times, traders like to adjust these values to suit various different assets and trading styles. So let’s parameterize these values so you can do the same.
If you’ve been following this series, you will currently have three inputs — liveRSIPrice
, rsiHigh
, rsiLow
. Now we will add three new ones:
takeProfitPips
— which allows you to adjust the number of pips for the Take Profit (or TP)stopLossPips
— which allows you to adjust the number of pips for the Stop Loss (or SL)volume
— which allows you to adjust the amount (or lot size) of each currency you will purchaseTo do this, add the following three lines to your code, under your existing input
parameters:
input int takeProfitPips = 20; // Take Profit in Pips
input int stopLossPips = 10; // Stop Loss in Pips
input double lotSize = 0.1; // Lot Size
Now we need to integrate these parameters into the OnSignal()
function.
Update it so that it looks like this:
//+------------------------------------------------------------------+
// 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;
if(signal == "BUY"){
// Make the Take Profit above the current price
double takeProfit = ask + (pipSize * takeProfitPips);
// Make the Stop Loss below the current price
double stopLoss = ask - (pipSize * stopLossPips);
// 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 - (pipSize * takeProfitPips);
// Make the Stop Loss above the current price
double stopLoss = ask + (pipSize * stopLossPips);
// Open a Sell Order
trade.Sell(lotSize, _Symbol, ask, stopLoss, takeProfit, "RSI Tutorial EA");
return(true);
}else{
return(false);
}
}
Compile you code and see it run.
You may need to wait for the RSI to hit one of the triggers, but once it does, it should work beautifully!
Before we finish up, we’re going to make a couple of changes to make our code conform to the DRY principle.
The DRY programming principle refers to a programming approach of “Don’t Repeate Yourself”. In essence, it means that any time you have repetitive code where you have repeated yourself, there is an opportunity to refactor your code.
There are several advantages to this:
If you check through the EA code so far, there are two updates we can make to improve our code:
OnSignal()
— this function has repeated the Take Profit and Stop Loss parameters in each of the signalsOnTick()
— this function uses the line bool result = OnSignal(signal)
line twiceI’m going to combine these changes into one update.
Update both of these functions so they look like this:
//+------------------------------------------------------------------+
// 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);
}
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
double rsi = GetRSI();
string signal = RSIAlgorithm(rsi);
bool success = OnSignal(signal);
}
Chuck a quick compile to make sure it’s still running!
By now you’ve got a really solid expert advisor up and running. It can even make trades on your behalf!
However, you might notice that we’ve got a critical problem due to the nature of the RSI. Your bot will place lots of trades whenever it hits the triggers you’ve put in.
This can be pretty catastrophic if you make a ton of losses.
In the next episode, I’ll show you how to manage your trades through Order Management.
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:
//+------------------------------------------------------------------+
//| 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
// 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);
}
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
double rsi = GetRSI();
string signal = RSIAlgorithm(rsi);
bool success = OnSignal(signal);
}