How To Use Indicators In Expert Advisors?

Do you regularly read my Forex Double Doji blog? I try to write posts that will help improve your trading results. In this post I am going to discuss in detail how to use the build in MT5 indicators as well as custom indicators in your expert advisor. Buy/Sell trading signals are generated by the indicator. We use these buy/sell trading signals in the expert advisor to open buy/sell orders. Coding an indicator or for that matter an expert advisor in MQL5 is different than coding an indicator or an expert advisor  In MQL4, we could only use 8 buffers in building indicators. In MQL5, there is no such limitation. We can use any many buffers as we need.Developing good indicators is a challenge. Expert advisors are just based on indicators. Expert advisor just takes the buy/sell signal and opens and closes positions. If the indicator that you are using in the expert advisor is not good, you will get poor results. Read this post in which I discuss why it is difficult to develop good indicators based on statistical analysis alone.

How To Code A Simple Expert Advisor?

Let’s start with a simple example. Below is the code for a simple expert advisor that will open a buy trade when price closes above exponential moving average. Similarly this simple expert advisor will open a sell position when price closing below exponential moving average. Trade has the option to specify the stop loss as well as take profit. Don’t trade with this simple expert advisor, it is for educational purpose only.

// Input variables
// here we initialize the input variables that you can change
//initialize lot size
input double tradeVolume=0.01;  //A
//initialize stop loss (500 means 50 pips)
input int stopLoss=500;
//initialize take profit target
input int takeProfit=1500;
//initialize the exponential moving average period
input int emaPeriod=11;         //A
// define global variables that will be available throughout the program      
bool globalBuyPlaced, globalSellPlaced;      //B
// OnTick() event handler
void OnTick()                           //C
{
// initialize Trade structures
// initialize MqlTradeRequest structure
MqlTradeRequest request;
//initialize MqlTradeResult structure
MqlTradeResult result;
//initialize MqlTradeRequest structure variables to zero
ZeroMemory(request);
// initialize moving average array
double MA[];
// set the array as a time series
ArraySetAsSeries(MA,true);
int ma_Handle=iMA(_Symbol,0,emaPeriod,MODE_EMA,0,PRICE_CLOSE);
CopyBuffer(ma_Handle,0,0,1,MA);
// initialize close price array
double close[];
ArraySetAsSeries(close,true);
CopyClose(_Symbol,0,0,1,close);
// Current position information
bool openTrade = PositionSelect(_Symbol);
long positionType = PositionGetInteger(POSITION_TYPE);
double currentTradeVolume = 0;
//check if there is a trade open
if(openTrade == true) currentTradeVolume = PositionGetDouble(POSITION_VOLUME);
// Open buy market order
// simple indicator below that checks closing price above moving average
//this if statement checks the condition below and places a trade if true
if(close[1] > MA[1] && globalBuyPlaced == false
&& (TradeType != POSITION_TYPE_BUY || openTrade == false))
{
request.action = TRADE_ACTION_DEAL;
request.type = ORDER_TYPE_BUY;
request.symbol = _Symbol;
request.volume = TradeVolume + currentTradeVolume;
request.type_filling = ORDER_FILLING_FOK;
request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
request.sl = 0;
request.tp = 0;
request.deviation = 50;
OrderSend(request,result);
// Modify Stop loss and Take profit
if(result.retcode == TRADE_RETCODE_PLACED || result.retcode == TRADE_RETCODE_DONE)
{
request.action = TRADE_ACTION_SLTP;
//put some time before retrying
do Sleep(100); while(PositionSelect(_Symbol) == false);
double tradeOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
if(stopLoss > 0) request.sl = tradeOpenPrice - sStopLoss * _Point);
if(takeProfit > 0) request.tp = tradeOpenPrice + (takeProfit * _Point);
if(request.sl > 0 && request.tp > 0) OrderSend(request,result);
globalBuyPlaced = true;
globalSellPlaced = false;
}
}
// Open sell market order
//simple indicator that checks if closing price is below the moving average
//if the condition is true a sell trade will be placed
else if(close[1] < MA[1] && glSellPlaced == false && positionType != POSITION_TYPE_SELL) 
{ request.action = TRADE_ACTION_DEAL; request.type = ORDER_TYPE_SELL; 
request.symbol = _Symbol; request.volume = TradeVolume + currentVolume; 
request.type_filling = ORDER_FILLING_FOK; 
request.price = SymbolInfoDouble(_Symbol,SYMBOL_BID); 
request.sl = 0; request.tp = 0; request.deviation = 50; 
OrderSend(request,result); 
// Modify SL/TP if((result.retcode == TRADE_RETCODE_PLACED || 
result.retcode == TRADE_RETCODE_DONE) && (StopLoss > 0 || TakeProfit > 0))
{
request.action = TRADE_ACTION_SLTP;
do Sleep(100); while(PositionSelect(_Symbol) == false);
double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
if(StopLoss > 0) request.sl = positionOpenPrice + (StopLoss * _Point);
if(TakeProfit > 0) request.tp = positionOpenPrice - (TakeProfit * _Point);
if(request.sl > 0 && request.tp > 0) OrderSend(request,result);
globalBuyPlaced = false;
globalSellPlaced = true;
}
}
}

Now I will explain the above code in detail. In A we define the input variables. These input variables are stop loss, take profit and trade volume. When you double click on the expert advisor an input box will open where you will be able to specify the stop loss, take profit and trade volume.  You can also choose the EMA period. In this case we choose 11. We have chosen stop loss as 50 pips, take profit as 150 pips. Trade volume is 0.01. This is just a test expert advisor. In B, we define two global variables; globalBuyPlace and globalSellPlaced. These two global variables will be used to check whether there is a buy/sell order already open before opening a buy/sell order. These two global variables will ensure that our simple expert advisor doesn’t open a buy order when a buy order has already closed either by the stop loss or take profit being hit. In the same manner, globalSellPlaced variable will ensure the expert advisor doesn’t open a sell order just after a sell order gets closed by a stop loss or a take profit getting hit. Did you read the post on how to make 600 pips in 2 days with a 10 pip SL?

In an expert advisor everything happens inside the OnTIck() event handler. The first thing that we do is idefine MqTradeRequest and MqTradeResult structures request and result. We also use the ZeroMemory() function to reset the request structure. This way all the MqlTradeRequest structure variables are initialized to zero. Before we open a new trade we check whether we have an open trade. If there is an open trade we don’t open another trade. When we open a buy trade if we have already closed a buy trade we don’t open it. This means we only open a sell trade after closing a buy trade. In the same manner we only open a buy trade after closing a sell trade. Now this expert advisor is only for educational purpose. Don’t trade to trade with it. I have put comments in the code so that you can understand the code. Watch these videos on how to trade Camarilla Pivot Points?

How To Use Standard Indicators In An EA?

After going through above MQL5 code. you will have realized by now that most of the code in the expert advisor concerns checking for open orders and placing new orders and modifying the already open orders. You can see above, we have used a very simple indicator in the above expert advisor. We checked if close[1] > MA [1] and there is no buy trade already, we open a new buy trade. In the same manner, we check if close[1] < MA[1] and there is no sell trade already, we open a sell order. We have a very simple indicator in this expert advisor. We check if close[1]  <> MA[1] and then make the buy/sell decision. Below is the definition of iMA indicator:

int iMA(
string symbol, 
// symbol name
ENUM_TIMEFRAMES period, 
// period
int ma_period, 
// averaging period
int ma_shift, 
// horizontal shift
ENUM_MA_METHOD ma_method, 
// smoothing type
ENUM_APPLIED_PRICE applied_price 
// type of price or handle
);

Above is the predefined iMA function. It contains a number of enums. The first enum that is calls is the ENUM_TIMEFRAMES where you set the timeframe. Then we have ma_period and ma_shift which are integers. ENUM_MA_EMTHOD tells whether you want a simple moving average, exponential moving average or a weighted moving average. ENUM_APPLIED_PRICE tells whether you want to use open, high, low or close. Did you observe we saved the IMA value in an integer maHandle. This is a unique identifier. We use the CopyBuffer() function to copy the data from the iMA buffer to the MA array that we have defined in the code. It is good that you take a look at the CopyBuffer() function as we will be using it often when coding expert advisors.

int CopyBuffer(
int indicator_handle, 
// indicator handle
int buffer_num, 
// indicator buffer number
int start_pos, 
// start position
int count, 
// amount of bars to copy
double buffer 
// target array to copy to
);

You can see above this CopyBuffer() function calls a number of variables. First is the indicator_handle which is an integer. We use it to copy the data. Then we have the buffer_num which is an integer. In the case of iMA we had only one line so there was only buffer. But there are some indicators that have more than one buffer like MACD, Stochastic etc. Both have 2 lines meaning 2 buffers. RSI is a very popular indicator. RSI only has one line in the indicator window meaning it only uses one buffer. Read this post on how to predict weekly prices with kernel ridge regression.

int iRSI(
string symbol, 
// symbol name
ENUM_TIMEFRAMES period, 
// period
int ma_period, 
// averaging period
ENUM_APPLIED_PRICE applied_price 
// type of price or handle
);

You can see above iRSI predefine function that has only 4 calling variables. If you have been proogramming in MQL4, you would have seen by now how MQL5 is different when it comes to defining price and indicators. The output of iRSI is an integer that we call handle just like that we did for iMA. Below are the predefined MACD and Stochastic indicators.

// predefine iMACD function
int  iMACD(
   string              symbol,              
// symbol name
   ENUM_TIMEFRAMES     period,              
// period
   int                 fast_ema_period,     
// period for Fast average calculation
   int                 slow_ema_period,     
// period for Slow average calculation
   int                 signal_period,       
// period for their difference averaging
   ENUM_APPLIED_PRICE  applied_price        
// type of price or handle
   );

//predefined iStochastic function
int  iStochastic(
   string           symbol,          
// symbol name
   ENUM_TIMEFRAMES  period,          
// period
   int              Kperiod,         
// K-period (number of bars for calculations)
   int              Dperiod,         
// D-period (period of first smoothing)
   int              slowing,         
// final smoothing
   ENUM_MA_METHOD   ma_method,       
// type of smoothing
   ENUM_STO_PRICE   price_field      
// stochastic calculation method
   );

You can see in the above both these oscillators have two buffer that we will have to initialize. Below we initialize the MACD indicator. Algorithmic trading is ruling the markets now. Today more than 80% of the trades at Wall Street are being placed by algorithmic trading black boxes. Days of manual trading have come to an end. if you want to succeed as a trader, you need to develop a few algorithmic trading systems yourself. Read this post in which I discuss how to develop a high frequency trading algorithmic trading system.

// initialize MACD input parameters
//initialize the fast ema
input int fastEMA = 12;
//initialize the slow ema
input int slowEMA = 29;
//initialize the signal period
input int signalPeriod = 3;
//choose which price to use
input ENUM_APPLIED_PRICE macdPrice = PRICE_CLOSE;

    
// define the indicator buffers
double         macd[];
double         signal[];

// OnTick() event handler
ArraySetAsSeries(macdBuffer,true);
ArraySetAsSeries(signal,true);
int  macdHandle = iMACD( _Symbol, _Period, fastEMA, slowEMA, signalPeriod, macdPrice);
CopyBuffer(macdHandle,0,0,5,macd);
CopyBuffer(handle,1,0,5,signal);
double currentMACD = macd[0];
double currentSignal = signal[0];
double previousMACD = macd[1];
double previousSignal = signal[1];

As you can see above we define two arrays macd[] and signal[] and then used the CopyBuffer() function to copy MACD value plus the MACD signal value into these two array. We only copied the most recent 5 values. We don’t need to go back longer than that.

"MACD

MQL5 also has an inbuilt CIndicator class that has every standard indicator as a derived class. For example we have CiMACD that has the class hierarchy CObject -> CArray -> CArrayObj -> CSeries -> Cindicator -> CiMACD. Below I have defined an MACD1 indicator using the CiMACD class which is the derived CIndicator class.

// include the oscillator.mqh file
#include <Indicators\Oscilators.mqh>

// Create an object based on the CiMACD class
CiMACD MACD1;

// initialize MACD input parameters 
//initialize the fast ema 
input int fastEMA = 12; 
//initialize the slow ema 
input int slowEMA = 29; 
//initialize the signal period 
input int signalPeriod = 3; 
//choose which price to use input 
ENUM_APPLIED_PRICE macdPrice = PRICE_CLOSE; 

// OnInit() event handler
MACD1.Create(_Symbol,_Period, fastEMA, slowEMA, signalPeriod, macdPrice);
// OnTick() event handler
double currentMACD1 = MACD1.Main(0);
double currentMACD1Signal = MACD1.Signal(0);
double previousMACD1 = MACD1.Main(1);
double previousMACD1Signal = MACD1.Signal(1);

As you can see there is no handle in the above code. First we include the oscillator.mqh file that holds the class definition and its methods. Then we define a CiMACD class object MACD1. After defining the input parameters we use its Create() constructor to create an obkect MACD1. After that we use Main() and Signal() methods to get the oscillator values. You can use either of the above two methods to define the standard indicators. It is upto you..

How To Use Custom Indicators In An EA?

I am going to now discuss how to create a custom indicator and then how to use them in your expert advisor. We will be using iCustom() function. Custom indicator file should be placed in the MQL5\Indicators\Examples folder. Below is iCustom() function definition:

int  iCustom(
   string           symbol,     
// symbol name
   ENUM_TIMEFRAMES  period,     
// period
   string           name        
// folder/custom_indicator_name
   ...                          
// list of indicator input parameters
   );

Bollinger Bands are loved by many traders who develop trading strategies revolving around it. Bollinger Bands comprises of three lines meaning it uses three buffers. Below is an example of how we are going to pass the Bollinger Bands indicator to an expert advisor using this iCustom indicator!

// Bollinger Bands Input variables
input int BBPeriod = 20; // Period
input int BBShift = 0; // Shift
input double BBDeviation = 2; // Deviation

// OnTick() event handler
double bbUpper[], bbLower[], bbMiddle[];
ArraySetAsSeries(bbUpper,true);
ArraySetAsSeries(bbLower,true);
ArraySetAsSeries(bbMiddle,true);
int BBHandle = iCustom(_Symbol,_Period,"Examples\\BB",BBPeriod,BBShift,BBDeviation);
CopyBuffer(BBHandle,0,0,10,bbMiddle);
CopyBuffer(BBHandle,1,0,10,bbUpper);
CopyBuffer(BBHandle,2,0,10,bbLower);
double currentBBMiddle = bbMiddle[0];
double currentBBUpper = bbUpper[0];
double currentBBLower = bbLower[0];

As you can see in the above code, we have used three arrays to hold Bollinger Bands Upper, Middle and Lower bands.Most of the trading signals compriise if else statements. Now you might wonder how much effective if else statements can be in capturing the righr conditios.I love to trade with MACD. MACD can give a lot o f false signals. The best signal is when it crosses the zero line. When MACD crosses the zero line from below to above, it is a buy signal and when it crosses the zero line from above to below, it is a sell signal.

if(macd[2] < 0 && macd[1] > 0 && PositionType(_Symbol) != POSITION_TYPE_BUY)
{
// Open buy position
}

if(macd[2] > 0 && macd[1] < 0 && PositionType(_Symbol) != POSITION_TYPE_SELL)
{
// Open sell position
}

You can turn indicators on and off in an expert advisor. It is a good idea to always trade in the direction of the trend on the higher timeframe. For example, when the trend is up on the daily, we should look for a buy signal on H4. Similarly when the trend is down on the daily, we should look for a sell signal. First we check the trend on daily timeframe. If MACD is increasing on daily, we have an uptrend. MACD is just a histogram which displays EMA29 and EMA12 difference. If this difference is increasing we have an uptrend and if this difference is decreasing then we have a downtrend. We place the EA on lower timeframes. It will automatically check the trend on daily and only open the trade on the lower timeframe when the trend matches with the daily timeframe.

// include the oscillator.mqh file 
#include <Indicators\Oscilators.mqh>

// initialize MACD input parameters 
//initialize the fast ema 
input int fastEMA = 12; 
//initialize the slow ema 
input int slowEMA = 29; 
//initialize the signal period 
input int signalPeriod = 3; 
//choose which price to use 
input ENUM_APPLIED_PRICE macdPrice = PRICE_CLOSE;

CiMACD MACD1
CiMACD MACD2
MACD1.Create(_Symbol,_Period, fastEMA, slowEMA, signalPeriod, macdPrice);
MACD2.Create(_Symbol,_Period_D1, fastEMA, slowEMA, signalPeriod, macdPrice);  
// OnTick() event handler

double currentMACD1 = MACD1.Main(1); 
double previousMACD1 = MACD1.Main(2);
double currentMACD2 = MACD1.Main(1); 
double previousMACD2 = MACD1.Main(2);

if (currentMACD2 > previousMACD2) Uptrend=TRUE;
if(previousMACD1 < 0 && currentMACD1 > 0 && PositionType(_Symbol) != POSITION_TYPE_BUY) 
&& Uptrend=TRUE
{ // Open buy position }

if (currentMACD2 < previousMACD2) Uptrend=FALSE; 
if(previousMACD1 > 0 && currentMACD1 < 0 && PositionType(_Symbol) != POSITION_TYPE_SELL) 
&& Uptrend=FALSE
{ // Open sell position }

Always makes sure that you trade in the direction of the main trend on the higher timeframe. This will save you from a lot of lsoing trades. This is a simple filter that I have included in the above code that will filter out a lot of false signals on the lower timeframes.

I have developed a few courses that will help you learn algorithmic trading and how to develop good trading indicators that you can use in expert advisors. Time series analysis is very important for you to learn as a trader. Price data that we download is Open, High, Low and Close with the time stamp which is a time series. Time series analysis will teach you how to use this OHLC time series to forecast the closing price after a few time stamps. You can use this forecast in your indicators. You can take a look at my course Time Series Analysis For Traders.MQL5 has limitations. It lacks libraries for doing data science, machine and deep learning. Today deep learning has created a revolution in the field of artificial intelligence. If you want to use deep learning in developing algorithmic trading systems, you will have to learn Python. Python is a powerful modern object oriented programming language. Check this post on Neural Network Forex Trading System.

Today Python is the leader when it comes to data science, machine learning, deep learning and artificial intelligence. Learning Python will help you immensely. There are many brokers lthat includes Oanda and Interactive Brokers that provide APIs that you can use to develop algorithmic trading systems in Python.You can take a look at my course Python Machine Learning For Traders . In this course I teach you how to use Python in building machine learning algorithms that you can use in your trading system.

Deep learning has created a revolution in the fileld of artificial intelligence. Deep learning has a lot of potential for traders. The third course in the Python series course that I have developed is Python Deep Learning For Traders. In this course I show you how to traing Long Short Term Memory Recurrent Neural Networks as well as Convolutional Neural Networsk in developing predictive models that you can use in your trading. Once you have taken this course, you can take the second course Algorithmic Trading With Python that will show you how to develop algorithmic trading systems using Oanda Python API and Interactive Brokers API.

Important question that comes to mind is how do we use Python while tradong on MT4/MT4. Developing optimized code for machine learning and deep learning algorithms is a time consuming and tedious task that can take many months. We don’t have the training and expertise to devlop optimize machine learning and deep learning algorithms in Python.Best option is to somehow connect, Python interpreter with MT4/MT4 and call Python right from within MQL4/MQL5 code. In the future I will write a post in which I will discuss in detail how you can connect MQL5 with Python. I will use C/C++ to write a DLL that will connect MQL5 with Python. So keep on reading my post if you are interested. Learning algorithmic trading is an interesting challenge. Today we are living in a world of algorithms. Algorithms are ruling the markets. Learning algorithmic trading and how to develop good expert advisors will take your trading to the next higher levels.