🚀 AI One-Click Generation of mql4 Strategy Code

Mastering the Mql4 iCustom() Function to Call Any Indicator in Your EA

mql4 | Published on: 2025/11/28
The following content is generated by EasyQuant .

Problem Description

How do I call a custom indicator from an Expert Advisor and get its buffer values?

Solution

To call a custom indicator from an Expert Advisor (EA) in MQL4 and retrieve its buffer values, you use the iCustom() function. This function allows access to any compiled indicator (.ex4 file) located in the MQL4\Indicators folder.

The iCustom Function Syntax

The function signature is as follows:

double iCustom(
   string symbol,           // Symbol name (NULL for current)
   int timeframe,           // Timeframe (0 for current)
   string name,             // Name of the custom indicator file (without extension)
   ...                      // Input parameters of the indicator (if any)
   int mode,                // Line index (Buffer index, 0-7)
   int shift                // Shift relative to the current bar (0 is current)
);

Step-by-Step Implementation

To successfully retrieve data, you must identify two specific details about the custom indicator before writing the code:

  1. Input Parameters: You must pass the indicator's input parameters in the exact order and type as they are declared in the indicator. If you omit them, the indicator will use its default values.
  2. Buffer Index (mode): You need to know which buffer holds the data you want. You can find this by looking at the "Data Window" (Ctrl+D) in MetaTrader 4 while the indicator is on the chart. The first value listed is usually Buffer 0, the second is Buffer 1, and so on.

MQL4 Code Example

Below is a complete example of an Expert Advisor that calls a hypothetical custom indicator named "MyCustomIndicator".

Assumptions for this example:

  • Indicator Name: MyCustomIndicator.ex4
  • Inputs: It accepts two parameters: an int (Period) and a double (Multiplier).
  • Buffers: It has two lines. Buffer 0 is the Main Line, and Buffer 1 is the Signal Line.
//+------------------------------------------------------------------+
//|                                            CustomIndCall_EA.mq4  |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

//--- Input parameters for the EA (to pass to the indicator)
input int      IndPeriod = 14;   // Period for the custom indicator
input double   IndMulti  = 2.0;  // Multiplier for the custom indicator

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // Check if the indicator file exists to prevent runtime errors
   // Note: This check is logical; MQL4 doesn't have a direct "FileExists" for indicators 
   // outside the sandbox easily, but iCustom will return 0 or Empty value if not found.
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // --- 1. Define the Indicator Name ---
   string indicatorName = "MyCustomIndicator"; 
   
   // --- 2. Call iCustom for Buffer 0 (Main Line) ---
   // We retrieve the value for the PREVIOUS bar (shift 1) to ensure the bar is closed
   double mainLineValue = iCustom(
      NULL,             // Symbol: NULL means current chart symbol
      0,                // Timeframe: 0 means current chart timeframe
      indicatorName,    // Exact name of the ex4 file
      IndPeriod,        // 1st Input Parameter of the indicator
      IndMulti,         // 2nd Input Parameter of the indicator
      0,                // Buffer Index: 0 (The first line/buffer)
      1                 // Shift: 1 (Previous bar)
   );

   // --- 3. Call iCustom for Buffer 1 (Signal Line) ---
   double signalLineValue = iCustom(
      NULL, 
      0, 
      indicatorName, 
      IndPeriod, 
      IndMulti, 
      1,                // Buffer Index: 1 (The second line/buffer)
      1                 // Shift: 1
   );

   // --- 4. Error Handling and Validation ---
   // Check if the indicator returned an error or empty value
   if(GetLastError() > 0)
   {
      Print("Error calling iCustom: ", GetLastError());
      return;
   }

   // Many indicators return EMPTY_VALUE (approx 2147483647) when nothing is drawn
   if(mainLineValue == EMPTY_VALUE || signalLineValue == EMPTY_VALUE) 
   {
      // Data is not valid for this bar, do not trade
      return; 
   }

   // --- 5. Trading Logic Example ---
   // Example: Buy if Main Line crosses above Signal Line
   
   // To check a cross, we need values from 2 bars ago as well
   double mainLinePrev   = iCustom(NULL, 0, indicatorName, IndPeriod, IndMulti, 0, 2);
   double signalLinePrev = iCustom(NULL, 0, indicatorName, IndPeriod, IndMulti, 1, 2);

   // Crossover Logic
   if(mainLinePrev < signalLinePrev && mainLineValue > signalLineValue)
   {
      Print("Crossover Detected: BUY Signal");
      // OrderSend logic would go here...
   }
}
//+------------------------------------------------------------------+

Key Considerations

  1. Parameter Matching: The list of parameters passed to iCustom (after the indicator name and before the mode/shift) must match the extern or input variables in the custom indicator's source code exactly. If the indicator has 5 inputs, you should pass 5 values, or pass none to use defaults.
  2. Empty Values: Custom indicators often use the value 2147483647 (constant EMPTY_VALUE) to represent "no drawing" or "no data" for a specific bar (e.g., an arrow indicator that only appears on specific bars). Always check against EMPTY_VALUE before using the data in calculations.
  3. Performance: Calling iCustom on every tick can be resource-intensive if the indicator code is heavy. If your strategy only runs on bar close, consider checking Volume[0] == 1 or tracking Time[0] to run the logic only once per new bar.
  4. Repainting: Ensure the custom indicator does not "repaint" (change past values). If it does, backtesting results will be unrealistic. Always use shift=1 (closed bar) rather than shift=0 (current forming bar) unless you specifically intend to trade intra-bar price action.

Q&A: Custom Indicators in MQL4

Q: How do I find the correct Buffer Index (mode) for a compiled indicator?
A: Attach the indicator to a chart in MetaTrader 4. Open the "Data Window" (View -> Data Window or Ctrl+D). Hover your mouse over a bar where the indicator draws a line or arrow. The values shown in the Data Window correspond to buffers. The top value is usually Buffer 0, the next is Buffer 1, etc.

Q: Why does iCustom return a huge number like 2147483647?
A: This is the value of the constant EMPTY_VALUE. Indicators use this to signify that nothing is drawn on that specific bar (for example, a Buy Arrow indicator will return this value on candles where there is no buy signal). You should filter these out using if(value != EMPTY_VALUE).

Q: Can I call an indicator located in a subfolder?
A: Yes. If your indicator is in MQL4\Indicators\MyFolder\MyInd.ex4, you pass the name as "MyFolder\\MyInd" (note the double backslash to escape the directory separator).

Q: Do I have to pass all input parameters to iCustom?
A: No. You have two choices:

  1. Pass no parameters (skip directly to mode and shift). The indicator will use its default settings.
  2. Pass all parameters defined in the indicator. You cannot pass "only the first two" if the indicator has five inputs; the compiler or runtime may misinterpret the mode and shift as input parameters.