Summary: This comprehensive guide covers the three most essential MQL4 technical indicator functions: iMA for moving averages, iRSI for relative strength, and iMACD for MACD. Learn proper syntax, parameter configuration, and practical EA implementation.




Why Technical Indicators Are Essential for EA Development
Technical indicators are the eyes of your Expert Advisor. They transform raw price data into actionable trading signals. Without indicators, your EA can only react to basic price movements. Mastering iMA, iRSI, and iMACD gives you the ability to implement most professional trading strategies used by successful traders worldwide.

Complete Technical Indicators Reference Table
| Indicator | Function | Parameters | Return Value | Primary Use |
|-----------|----------|------------|--------------|--------------|
| iMA (Moving Average) | iMA() | symbol, timeframe, period, shift, method, applied price, shift index | double (MA value) | Trend direction and strength |
| iRSI (RSI) | iRSI() | symbol, timeframe, period, applied price, shift index | double (0-100) | Overbought/oversold conditions |
| iMACD (MACD) | iMACD() | symbol, timeframe, fast period, slow period, signal period, applied price, mode, shift | double (MACD line or signal line) | Momentum and trend changes |

1. iMA - Moving Average (Trend Following)
The Moving Average is the most widely used indicator in forex trading. It smooths price data to identify trend direction and potential reversal points.

iMA Function Syntax and Parameters
```mql4
double iMA(
string symbol, // Symbol name (NULL for current)
int timeframe, // Timeframe (0 for current chart)
int period, // MA period (e.g., 14, 20, 50, 200)
int ma_shift, // MA shift (usually 0)
int ma_method, // MA method (MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA)
int applied_price, // Applied price (PRICE_CLOSE, PRICE_OPEN, etc.)
int shift // Shift index (0=current, 1=previous)
);
```

MA Method Constants
| Constant | Value | Description |
|----------|-------|-------------|
| MODE_SMA | 0 | Simple Moving Average |
| MODE_EMA | 1 | Exponential Moving Average |
| MODE_SMMA | 2 | Smoothed Moving Average |
| MODE_LWMA | 3 | Linear Weighted Moving Average |

Applied Price Constants
| Constant | Value | Description |
|----------|-------|-------------|
| PRICE_CLOSE | 0 | Close price |
| PRICE_OPEN | 1 | Open price |
| PRICE_HIGH | 2 | High price |
| PRICE_LOW | 3 | Low price |
| PRICE_MEDIAN | 4 | Median price (High+Low)/2 |
| PRICE_TYPICAL | 5 | Typical price (High+Low+Close)/3 |
| PRICE_WEIGHTED | 6 | Weighted close (High+Low+2*Close)/4 |

Complete iMA Examples
```mql4
// Basic moving average crossover detection
int CheckMACrossover() {
// Get current and previous MA values
double maFastCurrent = iMA(NULL, 0, 10, 0, MODE_EMA, PRICE_CLOSE, 0);
double maSlowCurrent = iMA(NULL, 0, 30, 0, MODE_EMA, PRICE_CLOSE, 0);
double maFastPrevious = iMA(NULL, 0, 10, 0, MODE_EMA, PRICE_CLOSE, 1);
double maSlowPrevious = iMA(NULL, 0, 30, 0, MODE_EMA, PRICE_CLOSE, 1);

// Check for crossover
if(maFastCurrent > maSlowCurrent && maFastPrevious <= maSlowPrevious) {
return SIGNAL_BUY; // Golden cross
}
else if(maFastCurrent < maSlowCurrent && maFastPrevious >= maSlowPrevious) {
return SIGNAL_SELL; // Death cross
}
return SIGNAL_NONE;
}

// Multi-timeframe moving average analysis
void AnalyzeMultiTimeframeMA() {
int timeframes[] = {PERIOD_M15, PERIOD_H1, PERIOD_H4, PERIOD_D1};
string tfNames[] = {"M15", "H1", "H4", "D1"};

for(int i = 0; i < 4; i++) {
double ma50 = iMA(NULL, timeframes[i], 50, 0, MODE_SMA, PRICE_CLOSE, 0);
double ma200 = iMA(NULL, timeframes[i], 200, 0, MODE_SMA, PRICE_CLOSE, 0);

string trend = (ma50 > ma200) ? "BULLISH" : "BEARISH";
Print(tfNames[i], " - MA50: ", ma50, " MA200: ", ma200, " Trend: ", trend);
}
}

// Moving average slope (direction and strength)
double GetMASlope(int period, int lookbackBars = 5) {
double maNow = iMA(NULL, 0, period, 0, MODE_EMA, PRICE_CLOSE, 0);
double maPast = iMA(NULL, 0, period, 0, MODE_EMA, PRICE_CLOSE, lookbackBars);

// Calculate slope in points per bar
double slope = (maNow - maPast) / lookbackBars / Point();
return slope;
}

// Price vs Moving Average distance
double GetPriceToMADistance(int period, double &distancePercent) {
double ma = iMA(NULL, 0, period, 0, MODE_SMA, PRICE_CLOSE, 0);
double currentPrice = Close[0];

double distancePoints = (currentPrice - ma) / Point();
distancePercent = (currentPrice - ma) / ma * 100;

return distancePoints;
}

// Complete trend strength assessment using multiple MAs
int AssessTrendStrength() {
double ma20 = iMA(NULL, 0, 20, 0, MODE_EMA, PRICE_CLOSE, 0);
double ma50 = iMA(NULL, 0, 50, 0, MODE_EMA, PRICE_CLOSE, 0);
double ma100 = iMA(NULL, 0, 100, 0, MODE_EMA, PRICE_CLOSE, 0);
double ma200 = iMA(NULL, 0, 200, 0, MODE_EMA, PRICE_CLOSE, 0);

// Count bullish alignments
int bullishCount = 0;
if(ma20 > ma50) bullishCount++;
if(ma50 > ma100) bullishCount++;
if(ma100 > ma200) bullishCount++;

// Count bearish alignments
int bearishCount = 0;
if(ma20 < ma50) bearishCount++;
if(ma50 < ma100) bearishCount++;
if(ma100 < ma200) bearishCount++;

if(bullishCount >= 3) return TREND_STRONG_BULLISH;
if(bearishCount >= 3) return TREND_STRONG_BEARISH;
if(bullishCount >= 2) return TREND_WEAK_BULLISH;
if(bearishCount >= 2) return TREND_WEAK_BEARISH;
return TREND_SIDEWAYS;
}
```

2. iRSI - Relative Strength Index (Momentum Oscillator)
The RSI measures the magnitude of recent price changes to evaluate overbought or oversold conditions. Values above 70 indicate overbought, below 30 indicate oversold.

iRSI Function Syntax and Parameters
```mql4
double iRSI(
string symbol, // Symbol name (NULL for current)
int timeframe, // Timeframe (0 for current chart)
int period, // RSI period (typical 14)
int applied_price, // Applied price (PRICE_CLOSE is standard)
int shift // Shift index (0=current, 1=previous)
);
```

Complete iRSI Examples
```mql4
// Basic RSI signal generation
int GenerateRSISignal(int rsiPeriod = 14, int overbought = 70, int oversold = 30) {
double rsi = iRSI(NULL, 0, rsiPeriod, PRICE_CLOSE, 0);
double rsiPrevious = iRSI(NULL, 0, rsiPeriod, PRICE_CLOSE, 1);

// Overbought/Oversold levels
if(rsi < oversold && rsiPrevious >= oversold) {
return SIGNAL_BUY; // Exit oversold - buy signal
}
else if(rsi > overbought && rsiPrevious <= overbought) {
return SIGNAL_SELL; // Exit overbought - sell signal
}

// Extreme levels
if(rsi < 20) return SIGNAL_STRONG_BUY;
if(rsi > 80) return SIGNAL_STRONG_SELL;

return SIGNAL_NONE;
}

// RSI divergence detection (advanced)
int DetectRSIDivergence(int rsiPeriod = 14) {
// Get current and previous price and RSI values
double priceCurrent = Close[0];
double pricePrevious = Close[1];
double priceTwoBarsAgo = Close[2];

double rsiCurrent = iRSI(NULL, 0, rsiPeriod, PRICE_CLOSE, 0);
double rsiPrevious = iRSI(NULL, 0, rsiPeriod, PRICE_CLOSE, 1);
double rsiTwoBarsAgo = iRSI(NULL, 0, rsiPeriod, PRICE_CLOSE, 2);

// Bullish divergence: price makes lower low, RSI makes higher low
bool bullishDivergence = (priceCurrent < pricePrevious &&
pricePrevious < priceTwoBarsAgo &&
rsiCurrent > rsiPrevious &&
rsiPrevious > rsiTwoBarsAgo);

// Bearish divergence: price makes higher high, RSI makes lower high
bool bearishDivergence = (priceCurrent > pricePrevious &&
pricePrevious > priceTwoBarsAgo &&
rsiCurrent < rsiPrevious &&
rsiPrevious < rsiTwoBarsAgo);

if(bullishDivergence) return SIGNAL_BUY;
if(bearishDivergence) return SIGNAL_SELL;
return SIGNAL_NONE;
}

// RSI failure swings (classic reversal patterns)
int DetectRSIFailureSwing() {
double rsi0 = iRSI(NULL, 0, 14, PRICE_CLOSE, 0);
double rsi1 = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);
double rsi2 = iRSI(NULL, 0, 14, PRICE_CLOSE, 2);
double rsi3 = iRSI(NULL, 0, 14, PRICE_CLOSE, 3);

// Bullish failure swing: RSI falls below 30, pulls back, doesn't reach 30 again
if(rsi2 < 30 && rsi1 < 30 && rsi0 > 30 && rsi0 > rsi1) {
return SIGNAL_BUY;
}

// Bearish failure swing: RSI rises above 70, pulls back, doesn't reach 70 again
if(rsi2 > 70 && rsi1 > 70 && rsi0 < 70 && rsi0 < rsi1) {
return SIGNAL_SELL;
}

return SIGNAL_NONE;
}

// Multi-timeframe RSI confirmation
bool IsMultiTimeframeRSIConfirmed(int higherTimeframe = PERIOD_H1) {
double rsiCurrent = iRSI(NULL, 0, 14, PRICE_CLOSE, 0);
double rsiHigher = iRSI(NULL, higherTimeframe, 14, PRICE_CLOSE, 0);

// Both must be in same direction (both oversold or both overbought)
bool bothOversold = (rsiCurrent < 30 && rsiHigher < 30);
bool bothOverbought = (rsiCurrent > 70 && rsiHigher > 70);

return (bothOversold || bothOverbought);
}

// RSI trend line break detection
bool IsRSITrendLineBroken(int lookback = 10, bool isUptrend = true) {
double rsiValues[];
ArrayResize(rsiValues, lookback);

for(int i = 0; i < lookback; i++) {
rsiValues[i] = iRSI(NULL, 0, 14, PRICE_CLOSE, i);
}

if(isUptrend) {
// Check if RSI breaks below the uptrend line
// Simplified: check if current RSI is lower than recent lows
double recentLow = rsiValues[ArrayMinimum(rsiValues, 1, lookback-1)];
return (rsiValues[0] < recentLow);
} else {
double recentHigh = rsiValues[ArrayMaximum(rsiValues, 1, lookback-1)];
return (rsiValues[0] > recentHigh);
}
}
```

3. iMACD - Moving Average Convergence Divergence (Trend and Momentum)
MACD shows the relationship between two moving averages. It consists of the MACD line (fast MA - slow MA), signal line (EMA of MACD), and histogram (MACD - signal).

iMACD Function Syntax and Parameters
```mql4
double iMACD(
string symbol, // Symbol name
int timeframe, // Timeframe
int fast_ema_period, // Fast EMA period (typical 12)
int slow_ema_period, // Slow EMA period (typical 26)
int signal_period, // Signal line period (typical 9)
int applied_price, // Applied price (PRICE_CLOSE)
int mode, // MODE_MAIN or MODE_SIGNAL
int shift // Shift index
);
```

MACD Mode Constants
| Constant | Value | Description |
|----------|-------|-------------|
| MODE_MAIN | 0 | MACD main line (fast MA - slow MA) |
| MODE_SIGNAL | 1 | MACD signal line (EMA of MACD line) |

Complete iMACD Examples
```mql4
// Basic MACD crossover signal
int GenerateMACDSignal() {
double macdMain = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 0);
double macdSignal = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, 0);
double macdMainPrev = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1);
double macdSignalPrev = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, 1);

// Bullish crossover: MACD line crosses above signal line
if(macdMain > macdSignal && macdMainPrev <= macdSignalPrev) {
return SIGNAL_BUY;
}
// Bearish crossover: MACD line crosses below signal line
else if(macdMain < macdSignal && macdMainPrev >= macdSignalPrev) {
return SIGNAL_SELL;
}
return SIGNAL_NONE;
}

// MACD histogram (MACD line - Signal line) for zero-line crossing
double GetMACDHistogram() {
double macdMain = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 0);
double macdSignal = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, 0);
return macdMain - macdSignal;
}

// MACD zero-line crossover
int CheckMACDZeroLine() {
double macdCurrent = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 0);
double macdPrevious = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1);

if(macdCurrent > 0 && macdPrevious <= 0) {
return SIGNAL_BUY; // Crossed above zero - bullish
}
else if(macdCurrent < 0 && macdPrevious >= 0) {
return SIGNAL_SELL; // Crossed below zero - bearish
}
return SIGNAL_NONE;
}

// MACD divergence detection
int DetectMACDDivergence() {
// Price data
double priceCurrent = Close[0];
double pricePrevious = Close[1];
double priceTwoBarsAgo = Close[2];

// MACD data
double macdCurrent = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 0);
double macdPrevious = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1);
double macdTwoBarsAgo = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 2);

// Bullish divergence: price makes lower low, MACD makes higher low
bool bullishDiv = (priceCurrent < pricePrevious &&
pricePrevious < priceTwoBarsAgo &&
macdCurrent > macdPrevious &&
macdPrevious > macdTwoBarsAgo);

// Bearish divergence: price makes higher high, MACD makes lower high
bool bearishDiv = (priceCurrent > pricePrevious &&
pricePrevious > priceTwoBarsAgo &&
macdCurrent < macdPrevious &&
macdPrevious < macdTwoBarsAgo);

if(bullishDiv) return SIGNAL_BUY;
if(bearishDiv) return SIGNAL_SELL;
return SIGNAL_NONE;
}

// MACD slope (momentum strength)
double GetMACDSlope(int lookbackBars = 3) {
double macdNow = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 0);
double macdPast = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, lookbackBars);

return (macdNow - macdPast) / lookbackBars;
}
```

4. Complete EA Using All Three Indicators
```mql4
//+------------------------------------------------------------------+
//| MultiIndicatorEA.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024"
#property version "1.00"
#property strict

input double InpLotSize = 0.1;
input int InpMagic = 12345;
input int InpStopLoss = 50;
input int InpTakeProfit = 100;

// Signal constants
#define SIGNAL_NONE 0
#define SIGNAL_BUY 1
#define SIGNAL_SELL 2

//+------------------------------------------------------------------+
//| Combined signal generation using all three indicators |
//+------------------------------------------------------------------+
int GenerateCombinedSignal() {
// Get indicator values
double maFast = iMA(NULL, 0, 10, 0, MODE_EMA, PRICE_CLOSE, 0);
double maSlow = iMA(NULL, 0, 30, 0, MODE_EMA, PRICE_CLOSE, 0);
double rsi = iRSI(NULL, 0, 14, PRICE_CLOSE, 0);
double macdMain = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 0);
double macdSignal = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, 0);
double macdPrev = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1);
double signalPrev = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, 1);

// Trend condition (MA)
bool bullishTrend = (maFast > maSlow);
bool bearishTrend = (maFast < maSlow);

// Momentum condition (RSI)
bool oversold = (rsi < 30);
bool overbought = (rsi > 70);

// MACD condition
bool macdBullish = (macdMain > macdSignal && macdPrev <= signalPrev);
bool macdBearish = (macdMain < macdSignal && macdPrev >= signalPrev);

// Combined signals (confirmation from at least 2 indicators)
if(bullishTrend && oversold && macdBullish) {
return SIGNAL_BUY;
}
else if(bearishTrend && overbought && macdBearish) {
return SIGNAL_SELL;
}

// Fallback to simpler signals
if(bullishTrend && oversold) return SIGNAL_BUY;
if(bearishTrend && overbought) return SIGNAL_SELL;
if(macdBullish) return SIGNAL_BUY;
if(macdBearish) return SIGNAL_SELL;

return SIGNAL_NONE;
}

//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick() {
static datetime lastBarTime = 0;
if(Time[0] == lastBarTime) return;
lastBarTime = Time[0];

int signal = GenerateCombinedSignal();

if(signal == SIGNAL_BUY && CountOrders(InpMagic) == 0) {
OpenBuyOrder();
}
else if(signal == SIGNAL_SELL && CountOrders(InpMagic) == 0) {
OpenSellOrder();
}
}

//+------------------------------------------------------------------+
//| Open buy order |
//+------------------------------------------------------------------+
void OpenBuyOrder() {
double sl = Ask - InpStopLoss * Point();
double tp = Ask + InpTakeProfit * Point();
int ticket = OrderSend(Symbol(), OP_BUY, InpLotSize, Ask, 30, sl, tp, "MultiIndicator EA", InpMagic, 0, clrGreen);
if(ticket > 0) Print("Buy order opened: ", ticket);
}

//+------------------------------------------------------------------+
//| Open sell order |
//+------------------------------------------------------------------+
void OpenSellOrder() {
double sl = Bid + InpStopLoss * Point();
double tp = Bid - InpTakeProfit * Point();
int ticket = OrderSend(Symbol(), OP_SELL, InpLotSize, Bid, 30, sl, tp, "MultiIndicator EA", InpMagic, 0, clrRed);
if(ticket > 0) Print("Sell order opened: ", ticket);
}

//+------------------------------------------------------------------+
//| Count orders by magic number |
//+------------------------------------------------------------------+
int CountOrders(int magic) {
int count = 0;
for(int i = 0; i < OrdersTotal(); i++) {
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
if(OrderMagicNumber() == magic) count++;
}
}
return count;
}
```

Multi-Timeframe Indicator Strategy
```mql4
// Multi-timeframe confirmation strategy
int GetMultiTimeframeSignal() {
int buyVotes = 0;
int sellVotes = 0;

int timeframes[] = {PERIOD_M15, PERIOD_H1, PERIOD_H4};

for(int i = 0; i < 3; i++) {
int tf = timeframes[i];

double rsi = iRSI(NULL, tf, 14, PRICE_CLOSE, 0);
double maFast = iMA(NULL, tf, 10, 0, MODE_EMA, PRICE_CLOSE, 0);
double maSlow = iMA(NULL, tf, 30, 0, MODE_EMA, PRICE_CLOSE, 0);

bool bullish = (maFast > maSlow && rsi < 40);
bool bearish = (maFast < maSlow && rsi > 60);

if(bullish) buyVotes++;
if(bearish) sellVotes++;
}

if(buyVotes >= 2) return SIGNAL_BUY;
if(sellVotes >= 2) return SIGNAL_SELL;
return SIGNAL_NONE;
}
```

Indicator Best Practices Checklist
  • [ ] Always validate indicator handles and return values (non-zero is valid)

  • [ ] Use shift index 0 for current bar, 1 for previous bar to avoid look-ahead bias

  • [ ] Cache indicator values when repeatedly calling the same indicator in one tick

  • [ ] Use multi-timeframe analysis for stronger signal confirmation

  • [ ] Combine multiple indicators to filter false signals

  • [ ] Adjust indicator parameters based on market conditions (trending vs ranging)

  • [ ] Test indicator strategies on historical data before live deployment

  • [ ] Be aware that indicators on higher timeframes may repaint

  • [ ] Use iCustom() for custom indicators when built-in ones are insufficient


  • Reference:
  • MetaQuotes Ltd. "MQL4 Documentation - Technical Indicators" (2024)

  • Wilder, J. Welles. "New Concepts in Technical Trading Systems" (1978)

  • Murphy, John J. "Technical Analysis of Financial Markets" (1999)


  • 9. Next Step
    Part 14 will explain Account and Market Information Functions – Complete guide to account balance, equity, margin, bid/ask prices, and market info with practical risk management examples.