🚀 AI One-Click Generation of mql4 Strategy Code

Building a Volume-Based Trading Robot with the A/D Indicator in Mql4

mql4 | Published on: 2025/12/5
The following content is generated by EasyQuant .

Problem Description

How can I build a trading robot that uses the Accumulation/Distribution indicator to confirm trends?

Solution

To build a trading robot (Expert Advisor) using the Accumulation/Distribution (A/D) indicator, it is important to understand that A/D is primarily a volume-based trend confirmation tool. It is rarely used as a standalone trigger for entering trades.

A robust strategy usually combines a Trend Trigger (like a Moving Average crossover) with the A/D Indicator acting as a filter to confirm the volume supports the price movement.

The Strategy Logic

  1. Primary Trigger (Moving Average Crossover):
    • Buy: Fast Moving Average crosses above Slow Moving Average.
    • Sell: Fast Moving Average crosses below Slow Moving Average.
  2. Confirmation (Accumulation/Distribution):
    • Buy Confirmation: The A/D line must be trending upwards (Current A/D > Previous A/D).
    • Sell Confirmation: The A/D line must be trending downwards (Current A/D < Previous A/D).
  3. Risk Management:
    • Fixed Stop Loss and Take Profit.
    • One open trade at a time per symbol.

MQL4 Code Implementation

//+------------------------------------------------------------------+
//|                                       AD_Trend_Confirm_Robot.mq4 |
//|                        Copyright 2023, Quantitative Trading AI   |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative Trading AI"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

//--- Input Parameters
input double Lots          = 0.1;      // Trading volume
input int    StopLoss      = 50;       // Stop Loss in pips
input int    TakeProfit    = 100;      // Take Profit in pips
input int    FastMAPeriod  = 12;       // Fast Moving Average Period
input int    SlowMAPeriod  = 26;       // Slow Moving Average Period
input int    MagicNumber   = 123456;   // Unique identifier for this EA
input int    Slippage      = 3;        // Max slippage in pips

//--- Global Variables
double pipModifier;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // Adjust pips for 3 or 5 digit brokers (Jpy pairs vs others)
   if(Digits == 3 || Digits == 5)
      pipModifier = 10 * Point;
   else
      pipModifier = Point;

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // 1. Check if we already have an open position for this symbol
   if(OrdersTotal() > 0)
   {
      for(int i = 0; i < OrdersTotal(); i++)
      {
         if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
               return; // Exit if a trade is already active
         }
      }
   }

   // 2. Define Indicator Values
   // Moving Averages (Shift 1 is the closed bar, Shift 2 is the bar before that)
   double fastMA_Curr = iMA(NULL, 0, FastMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
   double fastMA_Prev = iMA(NULL, 0, FastMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 2);
   
   double slowMA_Curr = iMA(NULL, 0, SlowMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
   double slowMA_Prev = iMA(NULL, 0, SlowMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 2);

   // Accumulation/Distribution
   double ad_Curr = iAD(NULL, 0, 1);
   double ad_Prev = iAD(NULL, 0, 2);

   // 3. Trading Logic
   
   // BUY SIGNAL
   // Logic: Fast MA crosses Above Slow MA AND A/D is rising
   if(fastMA_Prev < slowMA_Prev && fastMA_Curr > slowMA_Curr)
   {
      if(ad_Curr > ad_Prev) // A/D Confirmation
      {
         OpenBuyOrder();
      }
   }

   // SELL SIGNAL
   // Logic: Fast MA crosses Below Slow MA AND A/D is falling
   if(fastMA_Prev > slowMA_Prev && fastMA_Curr < slowMA_Curr)
   {
      if(ad_Curr < ad_Prev) // A/D Confirmation
      {
         OpenSellOrder();
      }
   }
}

//+------------------------------------------------------------------+
//| Function to Open Buy Order                                       |
//+------------------------------------------------------------------+
void OpenBuyOrder()
{
   double sl = 0, tp = 0;
   
   if(StopLoss > 0)     sl = Ask - (StopLoss * pipModifier);
   if(TakeProfit > 0)   tp = Ask + (TakeProfit * pipModifier);

   int ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, sl, tp, "AD Buy", MagicNumber, 0, clrGreen);
   
   if(ticket < 0)
      Print("OrderSend failed with error #", GetLastError());
}

//+------------------------------------------------------------------+
//| Function to Open Sell Order                                      |
//+------------------------------------------------------------------+
void OpenSellOrder()
{
   double sl = 0, tp = 0;
   
   if(StopLoss > 0)     sl = Bid + (StopLoss * pipModifier);
   if(TakeProfit > 0)   tp = Bid - (TakeProfit * pipModifier);

   int ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, sl, tp, "AD Sell", MagicNumber, 0, clrRed);
   
   if(ticket < 0)
      Print("OrderSend failed with error #", GetLastError());
}
//+------------------------------------------------------------------+

Code Breakdown

  1. Inputs:

    • FastMAPeriod and SlowMAPeriod: Define the sensitivity of the trend trigger.
    • StopLoss and TakeProfit: Standard risk management inputs defined in pips.
  2. OnInit():

    • Calculates pipModifier. This ensures the Stop Loss and Take Profit are calculated correctly regardless of whether the broker uses 4-digit or 5-digit pricing (e.g., EURUSD at 1.1000 vs 1.10005).
  3. OnTick() - The Main Logic:

    • Order Check: The code loops through existing orders. If a trade with the specific MagicNumber on the current Symbol exists, the function returns immediately. This prevents the bot from opening multiple trades on the same signal.
    • Indicator Calculation:
      • iMA: Calculates the Moving Average. We retrieve values for shift 1 (the last closed candle) and shift 2 (the candle before that) to detect the "crossover" moment.
      • iAD: Calculates the Accumulation/Distribution value.
    • Signal Logic:
      • Buy: We check if the Fast MA was previously below the Slow MA and is now above it (Crossover). We then check if ad_Curr > ad_Prev to confirm that volume accumulation is supporting the move.
      • Sell: We check if the Fast MA was previously above the Slow MA and is now below it. We confirm this by checking if ad_Curr < ad_Prev.
  4. Order Execution:

    • OpenBuyOrder and OpenSellOrder handle the specific OrderSend calls, calculating the correct SL and TP prices based on the current Ask/Bid prices.

How to Use This Robot

  1. Open MetaEditor in MT4 (Press F4).
  2. Create a new Expert Advisor, name it "AD_Trend_Confirm".
  3. Paste the code above into the file, replacing everything.
  4. Click Compile. Ensure there are no errors.
  5. Go back to the MT4 Terminal.
  6. Drag the EA from the Navigator onto a chart (e.g., EURUSD H1).
  7. Ensure "Allow Live Trading" is checked in the EA properties and the "AutoTrading" button at the top of MT4 is green.

Q&A: Quantitative Strategy Details

Q: Why use A/D instead of standard Volume?
A: Standard volume only tells you intensity. Accumulation/Distribution attempts to quantify the flow of money into or out of an asset by considering the close price relative to the high-low range. It provides a directional bias to the volume.

Q: Can I use A/D as the primary trigger?
A: It is not recommended. The A/D line is cumulative and unbounded. It does not oscillate between 0 and 100 like RSI. Therefore, it is difficult to define specific "overbought" or "oversold" levels to trigger a trade. It works best as a filter for price-action triggers.

Q: How can I reduce false signals with this bot?
A: Currently, the bot compares A/D of the current bar vs the previous bar. This can be noisy. To smooth this out, you could calculate a Moving Average of the A/D indicator itself and require the A/D line to be above its own Moving Average for a Buy, rather than just higher than the previous candle.