# ForwardSimEngine.mq5 ## EMA Crossover Forward Simulation Indicator — Synthetic Candles This repository contains a custom MQL5 indicator built as a forward simulation engine. It does not claim to reproduce any third-party source code. All logic is original and derived from the accompanying article series. --- ## Overview This project implements a chart-native forward projection indicator for MetaTrader 5. The system detects EMA crossover signals on closed bars and immediately projects a sequence of synthetic OHLC candles into the future time slots of the chart. The architecture is built around three independent modules: - a **Signal and Calibration module** that detects crossovers, latches state, and measures real candle metrics from history - a **Prediction Engine** that generates synthetic OHLC candles using the measured baseline, a sine-wave size envelope, and counter-trend injection - a **Renderer** that draws each candle as chart objects and removes the leading projected candle as each new real candle closes The indicator is designed for the **M15 timeframe** but adapts automatically to any timeframe via `PeriodSeconds()`. --- ## Original Article | Field | Value | |------------------|---------------------------------------------------------------| | Article Title | Creating an EMA Crossover Forward Simulation Indicator in MQL5 | | Author | johnhlomohang | | Publication Date | 2026.05.13 | | Category | Indicators | | Article URL | https://www.mql5.com/en/articles/22323 | | Part 1 URL | "This is part 1" | --- ## Repository Purpose This repository should be treated as a reference project accompanying the published article. Its purpose is to: - preserve the full indicator source for study and extension - document every input parameter and its effect - serve as a base for replacing the EMA detector with structure-based or volatility-based triggers - demonstrate the object-lifecycle, calibration, and rendering patterns described in the article series --- ## Key Concepts - fast and slow EMA crossover detection on fully closed bars - automatic anchor placement at the crossover bar - average candle body and wick measurement from recent price history - EMA slope as a momentum scale factor (0.5× – 1.5×) applied on top of the measured baseline - sine-wave body-size envelope producing organic variation across the projection - exponential decay flattening the projection toward the tail - counter-trend candle injection every N bars for realistic pullbacks - wick lengths derived from measured wick-to-body ratios - inter-candle spacing via time-inset OBJ_RECTANGLE bodies - pip-based signal invalidation with automatic object cleanup - interactive projection: the leading synthetic candle is removed as each real candle closes - dual-mode anchoring: automatic (tracks crossover bar) or manual (user-placed OBJ_VLINE) --- ## Algorithm and Architecture Summary ### Signal Detection `OnCalculate` runs on every tick. The two most recently closed bars (index `rates_total-2` and `rates_total-3`) are compared. A bullish signal is latched when the fast EMA crosses above the slow EMA between those two bars. A bearish signal is latched on the reverse cross. Each new signal resets the drawn state and triggers a calibration refresh. ### Calibration `CalcAvgCandleMetrics` reads the last `AvgLookback` closed bars using `CopyOpen`, `CopyHigh`, `CopyLow`, `CopyClose` starting at shift 1 (skipping the live forming bar). It computes: - `g_AvgBody` — mean of `|close - open|` - `g_AvgUpperWick` — mean of `high - max(open, close)` - `g_AvgLowerWick` — mean of `min(open, close) - low` - `g_AvgRange` — mean of `high - low` All values are floored at 1 pip to prevent collapse in flat markets. The function runs once at `OnInit` and again on each new crossover signal. ### Prediction Engine `GeneratePrediction` builds the `PredictedCandle[]` array. Each candle body size is computed as: ``` bodySize = avgBody × momentumScale × sin²(phase) × 0.93^i × jitter ``` where `momentumScale` maps the EMA slope to the range `[0.5, 1.5]`, the sine-squared term pulses sizes across the projection, `0.93^i` is the exponential decay, and jitter adds ±8% noise. Every `CounterCandleFreq` bars a counter-trend candle is injected at 25–45% of the trend body size. Wick lengths use the `avgWick / avgBody` ratio with ±25% jitter and a 20% floor. ### Rendering `DrawAllCandles` places each synthetic candle one bar-width into the future relative to the anchor, inset by `CandleGapFraction` on each side for visible spacing. Each candle is drawn as: - `OBJ_RECTANGLE` — filled body - `OBJ_RECTANGLE` — body outline (unfilled) - `OBJ_TREND` × 2 — upper and lower wicks, centred on the full bar slot Supporting objects include a dashed `OBJ_VLINE` separator at the anchor, an `OBJ_TEXT` zone label, and an `OBJ_TEXT` invalidation notice. ### Invalidation On every tick, the live bar's close is compared against the signal price. If a bullish projection's live price drops more than `InvalidationPips` below the signal price, or a bearish projection's live price rises more than `InvalidationPips` above it, all objects are deleted, an invalidation label is drawn, and the engine waits silently for the next valid cross. ### Interactive Removal `OnCalculate` detects when `rates_total` increases by one, meaning a new real bar has closed. At that point the object group for `FutureCandle_0` is deleted and the remaining projected candles shift down by one index. The projection is always anchored exactly one bar ahead of the current live bar. --- ## Attached Files | File | Description | |-----------------------------|--------------------------------------------------| | `ForwardSimEngine.mq5` | The complete MQL5 custom indicator | --- ## Input Parameters | Parameter | Default | Description | |---------------------|----------------|---------------------------------------------------------------------| | `FastEMA_Period` | 9 | Period of the fast EMA | | `SlowEMA_Period` | 21 | Period of the slow EMA | | `FutureBars` | 30 | Number of synthetic candles to project | | `SpreadMultiplier` | 2.0 | Secondary wick size multiplier (used as floor before calibration) | | `AutoAnchor` | true | Auto-place anchor at the crossover bar; false = manual OBJ_VLINE | | `AnchorLineName` | "FSE_Anchor" | Name of the anchor vertical line chart object | | `BullishColor` | DodgerBlue | Body fill color for bullish projected candles | | `BearishColor` | Crimson | Body fill color for bearish projected candles | | `WickColor` | DimGray | Color for upper and lower wick lines | | `ShowZoneLabel` | true | Show the `[ BULLISH PROJECTION ]` / `[ BEARISH PROJECTION ]` label | | `ShowSeparatorLine` | true | Show a dashed vertical line at the anchor bar | | `InvalidationPips` | 10 | Pip distance from signal price that triggers projection removal | | `CandleGapFraction` | 0.08 | Gap between candles as a fraction of bar width (range: 0.04–0.20) | | `CounterCandleFreq` | 4 | Insert one counter-trend candle every N candles (minimum: 3) | | `AvgLookback` | 50 | Number of recent closed bars used to measure average candle size | --- ## Chart Object Naming Convention All drawn objects use consistent prefixes so `ObjectsDeleteAll` can remove them cleanly in bulk. | Prefix | Object type | |-------------------------|------------------------------------| | `FutureCandle_N_body` | Filled rectangle — candle body | | `FutureCandle_N_bord` | Unfilled rectangle — body outline | | `FutureCandle_N_wU` | Trend line — upper wick | | `FutureCandle_N_wD` | Trend line — lower wick | | `FSE_Sep` | Dashed vertical separator | | `FSE_Label` | Projection zone label text | | `FSE_Invalid` | Invalidation notice text | | `FSE_Anchor` | Gold dash-dot anchor vertical line | --- ## Statistics | Metric | Value | |--------------------------------|----------------------------| | Indicator type | Chart window overlay | | Plot buffers | 2 (Fast EMA, Slow EMA) | | Crossover bars evaluated | 2 (last two closed bars) | | Default projection length | 30 bars | | Default calibration lookback | 50 bars | | Exponential decay base | 0.93 per bar | | Sine envelope range | 0.40× – 1.30× baseStep | | Momentum scale range | 0.5× – 1.5× avgBody | | Counter-trend retrace range | 25% – 45% of body | | Wick minimum floor | 20% of body height | | Timer interval | 3 seconds (manual anchor) | | Chart objects per candle | 4 | --- ## Installation 1. Copy `ForwardSimEngine.mq5` to your MetaTrader 5 data folder: ``` MQL5/Indicators/ForwardSimEngine.mq5 ``` 2. Open MetaEditor (F4 in MT5) and compile the file (F7). 3. In the MT5 Navigator panel under Custom Indicators, drag the indicator onto a chart. 4. Recommended timeframe: **M15**. 5. Configure inputs and click OK. 6. Open the Experts tab in the terminal to confirm the `[INIT]` and `[AVG]` log lines appear. --- ## Tuning Notes - **`AvgLookback`** — increase to 100+ for a smoother long-run average. Lower to 20–30 to react faster to recent volatility shifts such as news events. - **`InvalidationPips`** — increase on wide-spread instruments (XAUUSD, GBPJPY) to avoid premature removal. Lower on tight instruments (EURUSD, USDJPY) for stricter invalidation. - **`CandleGapFraction`** — 0.08 works well on M15. Increase to 0.12–0.15 on higher timeframes where bar width appears wider on screen. - **`CounterCandleFreq`** — set to 3 for more frequent pullbacks. Set to 6–8 for a cleaner directional sequence. - **`FutureBars`** — keep at or below 60. Above that, the exponential decay reduces later candles to near the floor size and the projection becomes visually flat. - **Manual anchor** — set `AutoAnchor = false` and draw an `OBJ_VLINE` named `FSE_Anchor` on any past bar to replay the projection from that point. --- ## Limitations - The projection is a structured visual scenario, not a price forecast. It does not use volume, order flow, or market microstructure data. - Signal detection is limited to EMA crossovers on closed bars. Intra-bar crosses are ignored until the bar closes. - The invalidation threshold is fixed in pips. It does not adapt dynamically to ATR or recent volatility. - The indicator does not place, manage, or close any trades. It is a visualization tool only. - Wick and body calibration depends on the quality and quantity of history available on the active symbol and timeframe. --- ## Tags `MQL5` `MetaTrader5` `CustomIndicator` `ForwardSimulation` `EMA` `Crossover` `SyntheticCandles` `ChartObjects` `Projection` `Visualization` `AlgorithmicTrading` --- ## Difficulty **Intermediate — Advanced** Requires familiarity with: - MQL5 indicator development (`OnCalculate`, `SetIndexBuffer`, `CopyBuffer`) - Chart object creation and lifecycle management (`ObjectCreate`, `ObjectDelete`, `ObjectsDeleteAll`) - MQL5 array indexing conventions (series vs non-series layout) - Basic EMA crossover concepts - MetaTrader 5 Strategy Tester for validation --- ## Reference Original article series: https://www.mql5.com/en/articles/22323