MT4 Indicator to Expert Advisor Conversion Case Study
A realistic research-backed workflow for turning a custom MT4 arrow indicator into an EA without the usual mistakes: wrong buffer index, wrong shift, `EMPTY_VALUE`, repainting arrows, chart-object signals and unsafe order execution.
Project Scenario
The client has an MT4 custom indicator that plots blue buy arrows and red sell arrows on XAUUSD M15. They want an EA that opens one trade after the signal candle closes, uses fixed-risk lot sizing, blocks high spread, and avoids duplicate entries.
Indicator EX4/MQ4, screenshots, desired timeframe, risk rules and example signal candles.
The arrow visible on the chart may not be the value the EA reads from `iCustom()`.
Buffer-based Expert Advisor with closed-candle signal reading and broker-safe trade handling.
Research Findings Before Coding
MQL4's official `iCustom()` contract is strict: the custom indicator must be compiled in the Indicators folder; extern inputs must be passed in the exact declaration order; `mode` is the buffer index from `SetIndexBuffer()`; `shift` is the candle index. MQL community threads repeatedly show the same failures: the EA reads bar zero while the screenshot shows an older bar, or the buffer returns `EMPTY_VALUE` because there is no signal at that shift.
| Problem | Why it happens | Fix |
|---|---|---|
| Wrong buffer | Arrow buffer is not the assumed index | Verify source `SetIndexBuffer()` and Data Window values |
| Wrong shift | EA reads current bar while signal confirmed later | Default to shift 1 and new-bar execution |
| EMPTY_VALUE | No signal buffer contains placeholder value | Ignore `EMPTY_VALUE`, 2147483647 and zero where applicable |
| Object arrows | Indicator draws objects but no signal buffer | Rewrite indicator to expose buffers or scan objects carefully |
Conversion Architecture
CustomIndicator.ex4 -> iCustom wrapper -> Buy/Sell buffer validator -> New-bar detector -> Duplicate signal lock -> Risk manager -> Spread/session filters -> OrderSend wrapper -> Trade manager -> Debug logger
The indicator is only the signal source. The EA still needs all production logic: lot sizing, stop/target placement, magic number isolation, broker digit handling, invalid stops protection, spread checks, slippage/deviation, and restart-safe position recognition.
Core `iCustom()` Pattern
int SignalShift = 1; // closed candle
double buy = iCustom(NULL, 0, "MySignalIndicator", PeriodInput, SignalMode, false, 0, SignalShift);
double sell = iCustom(NULL, 0, "MySignalIndicator", PeriodInput, SignalMode, false, 1, SignalShift);
bool hasBuy = (buy != EMPTY_VALUE && buy != 0);
bool hasSell = (sell != EMPTY_VALUE && sell != 0);
if (IsNewBar()) {
if (hasBuy) OpenBuyOncePerSignal();
if (hasSell) OpenSellOncePerSignal();
}
This is a concept snippet, not a complete EA. The production version must include symbol suffix handling, lot normalization, stop-level checks, trade context checks, error logging and duplicate-signal protection.
Acceptance Tests
- Buy buffer signal on closed candle opens exactly one Buy.
- Sell buffer signal on closed candle opens exactly one Sell.
- `EMPTY_VALUE` or zero creates no trade.
- Multiple ticks on the same candle do not duplicate entries.
- Spread above threshold blocks entry.
- EA restart recognizes existing trades by symbol and MagicNumber.
- Invalid lot size, invalid stops, market closed and no-price states fail safely.
- Signal timing matches screenshot candles across at least 30 historical examples.
Plan Your Own Indicator to EA Conversion
Use the planner to generate a technical brief with buffer mapping, repainting risk, EA architecture, order rules, QA tests and estimated effort.
Open Free PlannerSources reviewed: MQL4 official `iCustom()` and custom-indicator documentation, MQL5 forum discussions about `EMPTY_VALUE` and buffer mismatch, ForexFactory custom-indicator EA questions, and public indicator-to-EA builder documentation. Educational content only; exact implementation depends on the indicator source and broker conditions.