MQL4 - How To Create a Simple Forex MT4 Expert Advisor Template Using the RSI That Trades Once Per Bar


This is a two-part  MQL4 code tutorial discussing how to create a simple Metatrader expert advisor using the RSI that trades only once per bar. At the end of part 2, a fully functioning RSI EA template may be downloaded.   Additionally, the code will reference a different time frame chart for the RSI. So if you're interested in learning how to reference a different time frame from within an EA, this tutorial should prove informative. This MQL4 code tutorial is the sequal to How to place only one trade per bar on a forex MT4 expert advisor. This article will expand on that simple concept and present code that may be used as a template in many different expert advisor applications and with many different types of indicators, including the RSI.

As was discussed in the previous MQL4 tutorial, the key to trading only once per bar is to encapsulate the trading logic within a conditional block that uses a module level variable to keep track of the bar number using the Bars variable. MQL4 has many built-in indicator functions that may be used in system building. 

Using the RSI in MQL4

The iBarShift function returns the bar shift for a given time. In the code below, the current bar Time[0] is referenced. If this code is used on a chart other than the 1 hour chart, the bar sequence could be unpredictable. IBarShift allows for determination of the correct bar, or the closest bar if the last term is set to false. The return value may be entered wherever a shift parameter is required, such as in the iRSI  function.

The RSI or Relative Strength Index may be referenced in the MQL4 code and is declared as follows:
double iRSI(string symbol, int timeframe, int period, int applied_price, int shift)

The first term is symbol and if it refers to the current symbol may be entered as NULL or Symbol(), or even successfully as 0 (though best practice suggests you should use NULL instead of 0) all with equivalent meaning. 

The second term is timeframe and may be entered as 0 for the currently selected chart's timeframe, or as one of the pre-built timeframe enumeration values (see your help file under "iRSI" for more details). 

In this example the PERIOD_H1 variable is used for referencing data from a 1 hour chart. 

The third term period refers to the length of the RSI where the variable RSILength is used (below). 

applied_price refers to bar prices like close (PRICE_CLOSE) or high (PRICE_HIGH).

shift refers to how many bars to shift the RSI for the calculation. For instance, to calculate the RSI of 5 bars ago you would use 5 in the 5th term. For this example no shift is used so 0 is used (below).

After creating an external input for RSILength and two inputs for Buy and Sell thresholds for the RSI value at 70 and 30 respectively, the code looks like this:
extern int RSILength =         14;
extern int BuyThreshold =      70;
extern int SellThreshold =     30;
extern double Lots =           0.01;
extern int Slippage =          7;
extern string comment =        "RSI_Template";
extern int MagicNumber =       0;
/////////////////////////////////////
int ThisBarTrade        =      0;
int Position            =      0;
int start() {
    double RSI = 0.0;
    if ( ThisBarTrade != Bars) {
        int iShift = iBarShift(Symbol() PERIOD_H1, Time[0], false);
        RSI = iRSI(NULL, PERIOD_H1, RSILength, PRICE_CLOSE, iShift);

        // Buy Condition
        if ( RSI >= BuyThreshold ) {
            ThisBarTrade = Bars;
            // Buy code goes here
        }
        // Sell Condition
        if ( RSI <= SellThreshold) {
            ThisBarTrade = Bars;
            // Sell code goes here
        }
    }
}

By setting the buy threshold to 70, buy orders are created when the RSI crosses above 70. When the RSI crosses below 30 the sell condition is triggered and a sell trade is placed.
The RSI system in this MQL4 tutorial will trade as a stop and reversal (SAR) system, going from long to short and short to long with only single positions long or short being opened. The buy code must determine the currently open position. If the position is already long, nothing is done. If the position is short, the short trade must be exited first. Then when the position is flat, a long trade may be initiated. 

The opposite will be done when the sell condition is met. A routine called CalcPosition (shown below) loops through all open trades and adds up the current position into the Position module level variable. Long trades (OP_BUY) are added up as positive numbers Position += 1; while short trades (OP_SELL) are added up as negative numbers Position -=1;.
void CalcPosition() {
    Position = 0;
    for (int i = 0; i < OrdersTotal(); i++) {
        OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
        if( OrderSymbol() == Symbol() ) {
            if (OrderType() == OP_BUY) Position += 1;
            if (OrderType() == OP_SELL) Position -=1;
        }
    }
}

Open trades need to be closed for buy and sell trades respectively. This can be done by creating two routines. A close routine called CloseSingleBuy, and a second routine called CloseSingleSell to close out the open Buy or Sell orders respectively. As the code is essentially the same for both, for brevity only the CloseSingleBuy code will be shown below.
bool CloseSingleBuy() {
    bool closed;
    for (int i = 0; i < OrdersTotal(); i++) {
        OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
        if(Symbol() == OrderSymbol()) {
            while(IsTradeAllowed() == false)  Sleep(100);
            RefreshRates();
            if ( OrderType() == OP_BUY) {
                closed = OrderClose( OrderTicket(), OrderLots(), Bid, Slippage, White);
                Print ("Attempting to CloseSingleBuy order # " + i + " " + Bid);
                if (closed == -1) {
                    return(false);
                } else {
                    return(true);
                }
            }
        }
    }
}

The CloseSingleBuy routine is a typical looping block of code that works through all open orders and trades (OrdersTotal), matching up by Symbol() = OrderSymbol() and using the OrderClose() function to close a single open trade.

In the next part, all the pieces are put together into a single simple RSI EA template that you may download and use.

For updates Follow patrickmwhite on Twitter
Comments