Forward-Simulation/Article-22323-Forward-Sim-V1/README.md

12 KiB

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