TriZone Semafor
- Indicators
-
Ahmed Hamed Hamed Eadwan
Hello, I'm Ahmed — a trader and MQL5 developer based in the
United Arab Emirates, and the founder of R protocols.
I've been writing code since 1984 and trading the markets since 2006.
For many years, I developed trading tools for my own use, refining them
through real market experience. - Version: 1.0
If you have ever stared at a chart covered in ZigZag arrows and wondered which ones actually matter — this indicator was built for that frustration.
TriZone Semafor runs three independent ZigZag algorithms simultaneously: Fast (Period 5), Medium (Period 13), and Slow (Period 34). When they detect pivots on the same candle, only the most significant signal survives. Level 3 always overrides Level 2. Level 2 always overrides Level 1. One clean arrow per candle per direction — no stacking, no double-counting.
Why three levels instead of one
A single ZigZag treats all swings equally. The same indicator marks a two-bar pullback and a major trend reversal with identical arrows. TriZone classifies every pivot by significance so you read the chart hierarchy at a glance.
- Level 1 — Fast: Small pullbacks and minor pivots. The structure beneath the structure.
- Level 2 — Medium: Intraday swings and meaningful reactions. The pivots your trading journal references.
- Level 3 — Slow: Major structural turns. The points where trend continuation is genuinely in question.
Each level has its own arrow shape and color so you see the hierarchy instantly, without consulting a legend.
Exclusive signal system
Every candle passes through one rule: if a higher level claims a pivot on that candle, all lower-level claims are removed — not hidden, removed. This happens inside the indicator buffer before anything reaches the chart. The chart reflects the real state, not a layered overlay.
Anti-repaint mode
With AntiRepaint = ON, a signal is only drawn after the configured number of confirmation bars have passed. The arrow you see has already passed its stability window and will not move. The indicator shows the current mode and confirmation depth in the chart title bar — full transparency about what you are reading.
With AntiRepaint = OFF, signals appear immediately on the forming bar. Useful for visual reference. Not recommended for automated logic.
Alert system
Alerts are queued during calculation and delivered only after the exclusivity pass confirms the signal survived. You will never receive a popup for a Level 1 signal overridden by Level 3 a moment later. One confirmed pivot — one alert. Configurable per level independently.
What is included
- Three ZigZag detection levels with fully independent parameters
- Exclusive signal priority at buffer level — highest level wins per candle
- Popup alerts on confirmed pivots only — no phantom alerts
- Anti-repaint mode with configurable confirmation bars per level
- Any symbol, any timeframe — MetaTrader 5
- Single file — zero external dependencies, no DLL, no custom includes
Recommended starting point
Open H1 or H4 with default parameters. The default depths 5 / 13 / 34 follow the standard Fibonacci sequence — a natural fit for most instruments and timeframes.
Level 3 pivots are your structural reference. Level 2 are your intraday reference points. Level 1 shows the minor structure in between. Adjust depth (Period) and confirmation bars (ConfirmBars) to match your style.
Compatibility
MetaTrader 5 — any broker, any symbol, any timeframe. No external libraries. No DLL imports. Single .ex5 file, fully standalone.
iCustom Reference — TriZone_Semafor
Output Buffers
Only the highest active level is non-empty per candle.
EMPTY_VALUE = no pivot at that bar/level.
With AntiRepaint ON, read at shift ≥ max(ConfirmBars1, ConfirmBars2, ConfirmBars3) — default: shift ≥ 4.
| Buffer | Index | Signal | Content |
|---|---|---|---|
| BufLow1 | 0 | BUY | Level 1 Low pivot price — Fast ZigZag |
| BufHigh1 | 1 | SELL | Level 1 High pivot price — Fast ZigZag |
| BufLow2 | 2 | BUY | Level 2 Low pivot price — Medium ZigZag |
| BufHigh2 | 3 | SELL | Level 2 High pivot price — Medium ZigZag |
| BufLow3 | 4 | BUY | Level 3 Low pivot price — Slow ZigZag |
| BufHigh3 | 5 | SELL | Level 3 High pivot price — Slow ZigZag |
Input Parameters
# = position in iCustom() call (0-based, after Symbol / Period / FileName)
| # | Name | Type | Default | Range | Description |
|---|---|---|---|---|---|
| LEVEL 1 — Fast ZigZag | |||||
| 0 | Period1 | int | 5 | 2–500 | Pivot lookback depth (bars) |
| 1 | Deviation1 | int | 1 | 1–100 | Minimum deviation in points |
| 2 | Backstep1 | int | 3 | 1–(P-1) | Min bars between consecutive pivots |
| 3 | HighSymbol1 | int | 159 | Wingdings | Arrow for Highs (159=dot, 108=circle, 116=diamond) |
| 4 | LowSymbol1 | int | 159 | Wingdings | Arrow for Lows |
| 5 | ConfirmBars1 | int | 2 | 1–50 | Confirmation bars before signal is final |
| LEVEL 2 — Medium ZigZag | |||||
| 6 | Period2 | int | 13 | 2–500 | Pivot lookback depth |
| 7 | Deviation2 | int | 8 | 1–100 | Minimum deviation in points |
| 8 | Backstep2 | int | 5 | 1–(P-1) | Min bars between consecutive pivots |
| 9 | HighSymbol2 | int | 108 | Wingdings | Arrow for Highs |
| 10 | LowSymbol2 | int | 108 | Wingdings | Arrow for Lows |
| 11 | ConfirmBars2 | int | 3 | 1–50 | Confirmation bars |
| LEVEL 3 — Slow ZigZag | |||||
| 12 | Period3 | int | 34 | 2–500 | Pivot lookback depth |
| 13 | Deviation3 | int | 21 | 1–100 | Minimum deviation in points |
| 14 | Backstep3 | int | 12 | 1–(P-1) | Min bars between consecutive pivots |
| 15 | HighSymbol3 | int | 108 | Wingdings | Arrow for Highs |
| 16 | LowSymbol3 | int | 108 | Wingdings | Arrow for Lows |
| 17 | ConfirmBars3 | int | 4 | 1–50 | Confirmation bars |
| INSTANCE MANAGEMENT | |||||
| 18 | InstanceID | string | "A" | any | Unique tag — must differ from any visible chart copy |
| 19 | DebugMode | ENUM_ONOFF | OFF (0) | 0 / 1 | Print diagnostics to Journal |
| 20 | HeadlessMode | ENUM_ONOFF | OFF (0) | 0 / 1 | Set 1 (ON) when using via iCustom — suppresses all UI and alerts |
| ANTI-REPAINT | |||||
| 21 | AntiRepaint | ENUM_ONOFF | ON (1) | 0 / 1 | ON = confirmed signals only — required for stable EA logic |
| 22 | SafeArrows | ENUM_ONOFF | OFF (0) | 0 / 1 | ON = arrows use full retroactive-safe shift (stricter) |
| ALERT SYSTEM | |||||
| 23 | AlertMode | ENUM_ALERT_MODE | 1 (Popup) | 0–3 | 0=None 1=Popup 2=Push 3=All — set 0 inside EA |
| 24 | AlertLevel1 | ENUM_ONOFF | OFF (0) | 0 / 1 | Alert on Level 1 pivots |
| 25 | AlertLevel2 | ENUM_ONOFF | ON (1) | 0 / 1 | Alert on Level 2 pivots |
| 26 | AlertLevel3 | ENUM_ONOFF | ON (1) | 0 / 1 | Alert on Level 3 pivots |
Total: 27 parameters (indices 0–26)
iCustom Code Example
//+------------------------------------------------------------------+ //| iCustom handle — TriZone_Semafor | //+------------------------------------------------------------------+ int g_tzsHandle = INVALID_HANDLE; int OnInit() { g_tzsHandle = iCustom( _Symbol, PERIOD_CURRENT, "TriZone_Semafor", // exact file name, no .ex5 // ---- Level 1: Fast ---- 5, // Period1 1, // Deviation1 3, // Backstep1 159, // HighSymbol1 (dot) 159, // LowSymbol1 (dot) 2, // ConfirmBars1 // ---- Level 2: Medium ---- 13, // Period2 8, // Deviation2 5, // Backstep2 108, // HighSymbol2 (circle) 108, // LowSymbol2 (circle) 3, // ConfirmBars2 // ---- Level 3: Slow ---- 34, // Period3 21, // Deviation3 12, // Backstep3 108, // HighSymbol3 (circle) 108, // LowSymbol3 (circle) 4, // ConfirmBars3 // ---- Instance ---- "EA1", // InstanceID — must differ from any chart copy false, // DebugMode = OFF true, // HeadlessMode = ON ← required for EA usage // ---- Anti-Repaint ---- true, // AntiRepaint = ON (stable EA signals) false, // SafeArrows = OFF // ---- Alerts: all OFF inside EA ---- 0, // AlertMode = ALERT_NONE false, // AlertLevel1 false, // AlertLevel2 false // AlertLevel3 ); if(g_tzsHandle == INVALID_HANDLE) { PrintFormat("[EA] TriZone_Semafor handle failed: err=%d", GetLastError()); return INIT_FAILED; } return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Reading buffers at confirmed shift | //+------------------------------------------------------------------+ void OnTick() { // Minimum safe read shift = max(ConfirmBars1, ConfirmBars2, ConfirmBars3) // Default values: max(2, 3, 4) = 4 int safeShift = 4; double lo1[1], hi1[1]; // Buffer 0, 1 — Level 1 double lo2[1], hi2[1]; // Buffer 2, 3 — Level 2 double lo3[1], hi3[1]; // Buffer 4, 5 — Level 3 if(CopyBuffer(g_tzsHandle, 0, safeShift, 1, lo1) != 1) return; if(CopyBuffer(g_tzsHandle, 1, safeShift, 1, hi1) != 1) return; if(CopyBuffer(g_tzsHandle, 2, safeShift, 1, lo2) != 1) return; if(CopyBuffer(g_tzsHandle, 3, safeShift, 1, hi2) != 1) return; if(CopyBuffer(g_tzsHandle, 4, safeShift, 1, lo3) != 1) return; if(CopyBuffer(g_tzsHandle, 5, safeShift, 1, hi3) != 1) return; double ev = EMPTY_VALUE; // Exclusivity already applied by the indicator // Only one level non-empty per candle int buyLevel = (lo3[0] != ev) ? 3 : (lo2[0] != ev) ? 2 : (lo1[0] != ev) ? 1 : 0; int sellLevel = (hi3[0] != ev) ? 3 : (hi2[0] != ev) ? 2 : (hi1[0] != ev) ? 1 : 0; if(buyLevel > 0 && sellLevel == 0) PrintFormat("BUY signal | Level %d | shift %d", buyLevel, safeShift); else if(sellLevel > 0 && buyLevel == 0) PrintFormat("SELL signal | Level %d | shift %d", sellLevel, safeShift); } //+------------------------------------------------------------------+ //| OnDeinit — Release the handle | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(g_tzsHandle != INVALID_HANDLE) { IndicatorRelease(g_tzsHandle); g_tzsHandle = INVALID_HANDLE; } }
Common Mistakes
| Mistake | Symptom | Fix |
|---|---|---|
| Same InstanceID as chart copy | INIT_PARAMETERS_INCORRECT | Unique ID: "EA1" , "EA2" … |
| HeadlessMode = false in EA | Indicator draws chart objects + fires alerts per EA instance | Set parameter #20 to true |
| Reading shift = 0 with AntiRepaint ON | EMPTY_VALUE always — bar not yet confirmed | Read at shift ≥ 4 (default CB max) |
| AlertMode ≠ 0 inside EA | Alert() popups block Tester execution | Set parameter #23 to 0 |
| Wrong file name in iCustom | INVALID_HANDLE | Use exact name: "TriZone_Semafor" |
| No IndicatorRelease in OnDeinit | Memory leak on EA reload | Call IndicatorRelease(g_tzsHandle) |
