The code
An Expert Advisor that trades nothing: it reads the ZigZag indicator that ships with MetaTrader 5 and prints the last two confirmed swing points on each new bar.
Save it as MQL5/Experts/icustom-read-custom-indicator.mq5 and compile it in MetaEditor (F7): 0 errors, 0 warnings.
// Ships the indicator to the Strategy Tester's agents. Detected on its own when iCustom() gets a constant name,
// required when the name is built at run time: harmless here, and it keeps working if you make the name an input.
#property tester_indicator "Examples\\ZigZag.ex5"
input int InpDepth = 12; // ZigZag depth
input int InpDeviation = 5; // ZigZag deviation
input int InpBackstep = 3; // ZigZag back step
input int InpLookback = 300; // Bars to search for swing points
int zigzag = INVALID_HANDLE;
int OnInit()
{
// Path relative to MQL5\Indicators, without the extension. Inputs in the indicator's own order and types.
zigzag = iCustom(_Symbol, PERIOD_CURRENT, "Examples\\ZigZag", InpDepth, InpDeviation, InpBackstep);
if(zigzag == INVALID_HANDLE)
{
PrintFormat("iCustom failed: error %d. Is MQL5\\Indicators\\Examples\\ZigZag.ex5 there?", GetLastError());
return INIT_FAILED;
}
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
if(zigzag != INVALID_HANDLE)
IndicatorRelease(zigzag);
}
// The newest `max` swing points, newest first. ZigZag writes 0.0 on every bar that isn't a swing point.
int SwingPoints(double &price[], int &shift[], const int max)
{
int count = MathMin(InpLookback, BarsCalculated(zigzag));
if(count <= 0)
return 0; // not calculated yet
double buf[];
ArraySetAsSeries(buf, true);
int copied = CopyBuffer(zigzag, 0, 0, count, buf); // buffer 0: the ZigZag line
if(copied <= 0)
return 0;
int found = 0;
for(int i = 0; i < copied && found < max; i++)
{
if(buf[i] == 0.0 || buf[i] == EMPTY_VALUE)
continue;
price[found] = buf[i];
shift[found] = i;
found++;
}
return found;
}
void OnTick()
{
static datetime lastBar = 0;
datetime bar = iTime(_Symbol, PERIOD_CURRENT, 0);
if(bar == 0 || bar == lastBar)
return;
double price[3];
int shift[3];
if(SwingPoints(price, shift, 3) < 3)
return; // retry on the next tick
lastBar = bar;
// Point 0 is the end of the leg still being drawn: it moves until the next swing confirms it.
// Points 1 and 2 are the last two confirmed swings.
bool lastIsHigh = price[1] > price[2];
PrintFormat("Last confirmed swing %s %s (%d bars ago), the one before %s %s",
lastIsHigh ? "high" : "low", DoubleToString(price[1], _Digits), shift[1],
lastIsHigh ? "low" : "high", DoubleToString(price[2], _Digits));
}How it works
"Examples\\ZigZag". The path relative toMQL5/Indicators, with the backslash doubled inside an MQL5 string and no extension. The ZigZag example is installed with every terminal, so the EA runs as it is.- The inputs. ZigZag.mq5 declares
InpDepth,InpDeviationandInpBackstep, threeintinputs, in that order.iCustom()passes values by position: the names don't matter, the order and types do. - Buffer 0. ZigZag's source calls
SetIndexBuffer(0, ZigZagBuffer, INDICATOR_DATA), then 1 and 2 for two calculation buffers. The index inCopyBuffer()is that number. buf[i] == 0.0. ZigZag writes 0 on every bar that isn't a swing point (it setsPLOT_EMPTY_VALUEto 0). Many other indicators useEMPTY_VALUEinstead, so the loop checks both.- Point 0 is skipped. The newest point is the end of the leg ZigZag is still drawing: it moves while price extends and can disappear. Points 1 and 2 are confirmed.
#property tester_indicator. The Strategy Tester finds indicators named by a constant string by itself; the property is needed when the name is built at run time, and costs nothing here.
Pitfalls
- The file isn't where
iCustom()looks. A wrong path, a missing .ex5 or an indicator only in another terminal's folder givesINVALID_HANDLEand 4802 indicator cannot be created. - Inputs in the wrong order or type. Values are matched by position and converted silently: pass a deviation where the depth is expected and you get a different indicator, not an error. Inputs you leave out take their default values.
- Counting plots instead of buffers. A color line (
DRAW_COLOR_LINE) uses two buffers, values and color index, so the buffer after it isn't the next plot. Read theSetIndexBuffer()calls, or print each buffer once and compare with the Data Window. - Using the repainting point. Trading ZigZag's newest point means trading a swing that may vanish on the next bar. In the Strategy Tester this looks far better than it is live.
- Copying before the indicator is ready. Right after start,
CopyBuffer()fails with 4806; reading the arrays anyway can stop the EA with array out of range.
Variations
- Inputs decided at run time.
IndicatorCreate()takes the inputs as an array ofMqlParam, useful when their number or types vary. It then needs#property tester_indicatorfor the Strategy Tester. - Indicators from the Market. Purchased indicators are installed under
MQL5/Indicators/Market, so their name starts with"Market\\". - Only the .ex5.
iCustom()needs the compiled file, not the source. Without the source, the Data Window shows the plotted values in order, which helps match buffer numbers. - Built-in indicators. For the moving average, RSI and the other standard indicators, the dedicated functions are simpler: see reading iMA and iRSI.
Questions
How do I find a custom indicator's buffer numbers?
In the source, look at the SetIndexBuffer() calls: the first argument is the number CopyBuffer() needs. Without the source, print each buffer's value for one bar from the EA and compare it with the Data Window.
Do I need the .mq5 source to use iCustom()?
No. iCustom() loads the compiled .ex5 file. You only need to know its inputs, in order, and which buffer holds the value you want.
Can I call an MT4 indicator from an MT5 EA with iCustom()?
No. MetaTrader 5 can't run .ex4 files: the indicator has to be converted to MQL5 and compiled first. How to convert MQL4 to MQL5 covers the changes indicators need.
This program is a minimal example written to show one technique, not a trading system, and none of it is a recommendation to trade. Trading involves substantial risk of loss and is not suitable for every investor. Edgoro is a software tool, not a broker or financial adviser: nothing it produces is investment advice, and past or backtested performance does not guarantee future results.