Problem Description
Solution
To access values from a custom indicator with multiple buffers (like an arrow and a line) inside an Expert Advisor, you use the iCustom() function.
The key is identifying the Buffer Index (0 to 7) assigned to the arrow and the line, and ensuring you pass all the indicator's input parameters correctly.
Prerequisites: Finding the Buffer Indices
Before writing the code, you must know which buffer index corresponds to which visual element.
- Open the Data Window in MT4 (
Ctrl+D). - Hover your mouse over a bar where the Arrow or Line appears.
- Look at the values listed under your indicator's name.
- The first value is Buffer 0.
- The second value is Buffer 1, and so on.
MQL4 Implementation
Here is a complete, robust example of how to retrieve these values.
//+------------------------------------------------------------------+
//| CustomInd_Example.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 (Should match your Indicator's inputs)
input int InpIndPeriod = 14; // Example Indicator Input 1
input double InpIndDev = 2.0; // Example Indicator Input 2
//--- Constants for Buffer Indices (Update these based on your Data Window check)
const int BUFFER_ARROW = 0; // Assume Buffer 0 is the Arrow
const int BUFFER_LINE = 1; // Assume Buffer 1 is the Line
//--- Name of your custom indicator file (without .ex4)
const string IND_NAME = "NameOfYourIndicator";
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// 1. Define the shift (bar index).
// 1 = Closed bar (confirmed signal), 0 = Current bar (repainting possible)
int shift = 1;
// 2. Get the value of the ARROW buffer
// Note: We pass input parameters (InpIndPeriod, InpIndDev) before the buffer index
double arrowValue = iCustom(NULL, 0, IND_NAME, InpIndPeriod, InpIndDev, BUFFER_ARROW, shift);
// 3. Get the value of the LINE buffer
double lineValue = iCustom(NULL, 0, IND_NAME, InpIndPeriod, InpIndDev, BUFFER_LINE, shift);
// 4. Check for Arrow Signal
// Custom indicators usually return EMPTY_VALUE (approx 2147483647) when no arrow is drawn
if(arrowValue != EMPTY_VALUE && arrowValue != 0)
{
Print("Arrow detected on bar ", shift, ". Value: ", arrowValue);
// Example: If arrow is below price, it might be a Buy signal
if(arrowValue < Close[shift])
{
// Place Buy Logic Here
}
}
// 5. Logic for the Line
// Example: Check if price crossed the line
double lineValuePrev = iCustom(NULL, 0, IND_NAME, InpIndPeriod, InpIndDev, BUFFER_LINE, shift+1);
if(Close[shift] > lineValue && Close[shift+1] < lineValuePrev)
{
Print("Price crossed above the indicator line.");
}
}
//+------------------------------------------------------------------+
Key Explanations
1. The iCustom Syntax
The function signature is:
iCustom(Symbol, Timeframe, Name, ...Inputs..., BufferIndex, Shift)
...Inputs...: You must list every external input parameter of the custom indicator in the exact order and type (int, double, string, etc.) as they appear in the indicator's settings. If you skip one, the buffer mapping will fail.BufferIndex: This is themodeparameter. In the example above, we requestedBUFFER_ARROW(0) in the first call andBUFFER_LINE(1) in the second call.
2. Handling Empty Values (EMPTY_VALUE)
Arrow buffers are sparse; they do not have a value on every bar.
- When no arrow is drawn, MT4 usually fills the buffer with a specific "Empty" number.
- By default, this is
2147483647(represented by the constantEMPTY_VALUE). - Sometimes, poorly written indicators use
0instead. - Best Practice: Check
if(value != EMPTY_VALUE && value != 0)to confirm an arrow actually exists.
3. The Shift Parameter
- Using
shift = 0reads the current forming bar. If the indicator repaints (recalculates), the arrow might appear and disappear. - Using
shift = 1reads the previously closed bar. This is safer for backtesting and live trading as the signal is confirmed and will not vanish.
Q&A: Custom Indicators in MQL4
Q: How do I find the buffer index if I don't have the source code?
A: Use the "Data Window" (Ctrl+D) in the MT4 terminal. Add the indicator to the chart, hover over a bar where the arrow appears, and note which value field (1st, 2nd, 3rd...) populates with a number. The 1st value is Buffer 0, the 2nd is Buffer 1, etc.
Q: Why does my EA run extremely slowly when using iCustom?
A: This usually happens if the custom indicator performs heavy calculations (like nested loops) on every tick. To optimize, ensure you are not calling iCustom on every tick if you only need to check once per bar, or contact the indicator developer to optimize the OnCalculate or start function.
Q: Can I change the indicator inputs dynamically from the EA?
A: Yes. The inputs passed to iCustom are just variables. You can change InpIndPeriod in your EA logic, and the next iCustom call will calculate the indicator based on that new period. Note that this is computationally expensive as MT4 has to recalculate the indicator history for the new parameter.