ℹ️ Introduction
FxMath Elite Pro is a fully self-contained trading Expert Advisor that combines a Random Forest machine learning model with an adaptive grid trading strategy. It is written entirely in native MQL4/MQL5 — no DLLs, no external libraries, no dependencies.
The EA continuously trains four independent Random Forest models directly on the latest market data, retraining every N bars to stay adaptive. It detects whether the market is ranging or trending and adjusts grid parameters, position sizing, and lot sizes accordingly.
🧠 Pure MQL ML
Random Forest trained inside the EA — bootstrap sampling, Gini impurity, class weighting, and OOB estimation — all from scratch.
📈 120 Features
60 price-relative features (open/high/low/close ratios) + 60 technical indicators (SMA, RSI, MACD, ATR, Bollinger, ADX, Momentum).
🎯 4 Models
Buy (B), Sell (S), Trend (W), and Hedge (H) forests work together via a consensus voting system for trade signals.
🔄 Online Learning
Retrains on the latest N bars every N bars — no manual training, no external Python scripts.
🌊 Regime Adaptation
Detects ranging vs trending markets using ADX + Bollinger width + momentum. Adjusts grid distance, levels, and lot size automatically.
🛡️ Account Protection
Max drawdown %, daily loss limit, strong trend auto-exit, and consecutive loss circuit breaker built in.
🏗️ Architecture
The EA runs a stateless tick handler that processes this pipeline every cycle:
The cycle repeats every tick (throttled to 1s). The EA also integrates:
- GetLiveFeatures() — computes the same 120 features used during training
- GetSignal() — runs all 4 forests + applies the trend filter
- CloseAllPositions() — triggered by protection or strong trend exit
🚀 Quick Start
Prerequisites
- MetaTrader 5 or MetaTrader 4 terminal installed and running
- A funded trading account (demo or live)
- The compiled EA file (
FxMath_Elite_Pro.ex5for MT5 orFxMath_Elite_Pro.ex4for MT4)
Installation
- Copy the
.ex5(MT5) or.ex4(MT4) file to your terminal'sExpertsfolder - Restart MetaTrader or refresh the Navigator panel
- Drag the EA onto your preferred chart
- Enable Allow Algorithmic Trading (DLL imports not required)
- Click OK to start
First Run
On the first tick, the EA will:
- Fetch the last
TrainBarscandles (default 1000) - Compute 120 features per candle
- Generate labels (signalB, signalS, Target_H, Target_W)
- Train 4 Random Forests (default 20 trees × 8 depth)
- Begin live trading immediately after training
⏱ Training takes roughly 5–30 seconds depending on chart timeframe, bar count, and tree count. The EA will not trade until training completes.
⚙️ Trading Parameters
Core trading configuration — symbol, timeframe, position sizing, and grid.
| Parameter | Type | Default | Description |
|---|---|---|---|
| InpSymbol | string | "XAUUSD" | Trading instrument. Must match the symbol name in your broker's terminal (e.g. XAUUSD, EURUSD, BTCUSD). |
| InpTF | tf enum | PERIOD_H1 | Chart timeframe the EA operates on. All features, labels, and grid timings are based on this period. H1 is recommended for balanced training data size and trade frequency. |
| InpStopLoss | double | 0 | Stop Loss in price units (direct value, not points). For example, 20 means SL is 20 price units away from entry — on XAUUSD at 4000, SL = 3980. Set to 0 to disable. |
| InpTakeProfit | double | 20 | Take Profit in price units (direct value, not points). For example, 20 means the total TP target is 20 price units above entry — buy at 4000, TP at 4020. This total is divided equally among all open positions of the same direction. |
| InpLotSize | double | 0.01 | Base lot size for the first grid level. When InpFixedLot=true (default), ALL levels use exactly this lot. When InpFixedLot=false, each subsequent level is multiplied by InpLotRatio. |
| InpFixedLot | bool | true | When enabled (default), ALL grid levels use exactly InpLotSize — no scaling, no regime multipliers. When disabled, lot = base × regime multiplier × InpLotRatioⁿ for each grid step. Set to false for martingale/antimartingale scaling. |
| InpLotRatio | double | 1.0 | Lot size multiplier per grid step (only used when InpFixedLot=false). Lot at step N = baseLot × ratio^N. 1.0 = equal lot sizes; >1 = martingale scaling; <1 = antimartingale. |
| InpTrailing | int | 1000 | Trailing stop distance in price units (direct value). 0 = disabled. Moves SL behind price as it moves favorably, locking in profit. Now 15 for both MT4 and MT5. |
| InpMagic | int | 606 | Magic number to identify the EA's own trades. Must be unique per symbol/chart to avoid interference with other EAs or manual trading. |
| InpComment | string | "ee" | Comment added to every order. Useful for identifying trades in the terminal or by external tools. |
| InpGridDistance | double | 20 | Fixed grid distance in price units (used when InpGridATRmult = 0). Price must move this far against the position before a new grid level is added. This is also the hard minimum — even with regime multipliers applied, the effective grid distance never drops below this value. |
| InpMaxGrid | int | 10 | Maximum number of grid levels per direction (buy or sell). Further modified by regime multipliers (×1.5 in range, ×0.5 in strong trend). |
| InpBuyEnable | bool | true | Enable buy trades. When disabled, no buy positions are opened. |
| InpSellEnable | bool | true | Enable sell trades. When disabled, no sell positions are opened. |
| InpLotRatio | double | 1.0 | Lot size multiplier per grid step. Lot at step N = baseLot × ratio^N. 1.0 = equal lot sizes; >1 = martingale scaling; <1 = antimartingale. |
🧠 Model Parameters
Controls how the label signals and features are computed. These parameters must match the market characteristics.
| Parameter | Type | Default | Description |
|---|---|---|---|
| InpWindow | int | 12 | Look-ahead window in candles. Used to compute signal labels: signalB = TP hit before SL within this window; Target_W = close higher after window candles. Larger = longer-term prediction. |
| InpBack | int | 15 | Feature look-back in candles. Each candle contributes 4 features (open, high, low, close relative changes), so total price-relative features = 4 × InpBack = 60. |
| InpLabelSL | double | 0 | SL threshold in price units for training label generation. A buy signalB = 1 only if price moves up by TP before moving down by SL within the window. 0 = ignore downside check. |
| InpLabelTP | double | 20 | TP threshold for training labels. Minimum price movement in price units in the target direction to qualify as a positive signal. |
🔄 Online Learning
Controls the Random Forest training cycle and tree architecture.
| Parameter | Type | Default | Description |
|---|---|---|---|
| InpTrainBars | int | 1000 | Number of historical candles used for each training session. More bars = more training data but slower training. The EA uses the latest N closed candles. |
| InpRetrainBars | int | 24 | Retrain frequency in bars. The EA retrains all 4 forests every N new candles. Lower = more adaptive but more CPU time. |
| InpForestTrees | int | 20 | Number of decision trees per forest (total trees = 4 × this). More trees = better accuracy, slower training and prediction. Max 100. |
| InpMaxDepth | int | 8 | Maximum depth of each decision tree. Deeper = more complex splits = risk of overfitting. Max node count per tree = 2^(depth+1) − 1. |
| InpMinSamples | int | 10 | Minimum samples required to split a node. Higher = simpler trees, less overfitting. |
| InpClassWeight | double | 2.0 | Weight multiplier for the minority (class 1) during Gini impurity computation. 1.0 = balanced; >1 = upweights positive signals. Helps when buy/sell signals are rare compared to no-trade samples. |
📊 Trend Filter
A multi-indicator consensus system that blocks trades against the dominant trend direction.
| Parameter | Type | Default | Description |
|---|---|---|---|
| InpTrendFilter | bool | true | Master switch for the trend filter. When enabled, the EA builds a consensus score from SMA, ADX, MACD, and RSI on multiple timeframes. |
| InpTrendTF | tf enum | PERIOD_H4 | Higher timeframe for SMA-based trend detection. H4 is recommended for H1 trading, D1 for H4 trading. |
| InpTrendSMA | int | 200 | SMA period on the higher timeframe for long-term trend direction. Price above SMA = bullish, below = bearish. |
| InpTrendADXMin | double | 20.0 | Minimum ADX value to consider the market as trending. The ADX +DI/-DI direction is only factored into the consensus score when ADX exceeds this threshold. |
| InpTrendStrength | double | 0.6 | Minimum consensus ratio (0.0–1.0) required to block trades. A consensus below -0.6 blocks buys, above +0.6 blocks sells. Lower = filter more aggressive. |
Consensus Signals
| Signal | Weight | Source |
|---|---|---|
| HTF SMA slope | 33% | SMA 200 slope + price vs SMA on InpTrendTF |
| ADX direction | 25% | +DI vs -DI on trading TF (only when ADX ≥ InpTrendADXMin) |
| MACD histogram | 25% | Histogram slope + signal line cross on trading TF |
| RSI regime | 17% | RSI 14: >60 = bullish, <40 = bearish |
🛡️ Account Protection
Safety mechanisms to limit losses and protect account equity.
| Parameter | Type | Default | Description |
|---|---|---|---|
| InpProtectEnable | bool | true | Master switch for all protection features. |
| InpMaxDrawdownPct | double | 30.0 | Maximum drawdown from account balance, in percent. When equity falls X% below balance, all positions are closed immediately. 0 = disabled. |
| InpMaxDailyLoss | double | 0 | Maximum daily loss in account currency. The EA tracks the starting balance at the beginning of each day. If equity drops below this threshold, all positions close. 0 = disabled. |
| InpStopOnProtect | bool | true | After protection is triggered, also block opening new trades (existing positions still get SL/TP/trail updates until closed). |
🌊 Adaptive Range / Regime
The core innovation — detects market regimes and adjusts grid behavior automatically.
| Parameter | Type | Default | Description |
|---|---|---|---|
| InpRegimeAdapt | bool | true | Master switch for regime adaptation. When disabled, the EA uses fixed parameters (InpGridDistance, InpMaxGrid, InpLotSize). |
| InpRegimePeriod | int | 20 | Look-back period for regime detection indicators (ADX, Bollinger Bands, momentum consistency). |
| InpRangeADXMax | double | 22.0 | Maximum ADX value for the market to be classified as ranging. Below this = range mode. |
| InpTrendADXExit | double | 35.0 | ADX value at which the EA auto-closes all positions (strong trend exit). Prevents heavy drawdown in runaway trends. |
| InpBBRangeMin | double | 0.001 | Minimum normalised Bollinger Band width for ranging classification. Very narrow bands = compressed (potential breakout). |
| InpBBRangeMax | double | 0.008 | Maximum BB width for ranging. Wider bands = trending or highly volatile. |
| InpGridATRmult | double | 0 | ATR-based grid distance multiplier. Actual grid distance = ATR(14) × this (direct price value). 0 = use fixed InpGridDistance instead. When set >0, grid distance self-adapts to volatility. Combined with regime multipliers (×0.8 range, ×1.5 trend) and always clamped to a minimum of InpGridDistance. |
| InpRangeLotMult | double | 1.0 | Lot size multiplier when in range mode. 1.0 = base lot. |
| InpTrendLotMult | double | 0.3 | Lot size multiplier when in strong trend mode. Default 0.3 reduces risk by 70% in adverse conditions. |
| InpRangeMaxGridMult | double | 1.5 | Max grid multiplier when ranging. 1.5 × base max grid = more room for grid levels in range. |
| InpTrendMaxGridMult | double | 0.5 | Max grid multiplier in trend. 0.5 × base = fewer levels, reducing trend exposure. |
Regime Classification Logic
The regime score is a weighted combination of three independent signals:
| Signal | Weight | Ranging | Trending |
|---|---|---|---|
| ADX | 50% | ≤ InpRangeADXMax → score 0 | ≥ InpTrendADXExit → score 1 |
| BB Width | 30% | Within [min, max] → score 0 | Narrow or wide → score increases |
| Momentum | 20% | Mixed up/down bars → |ratio| near 0 | Strong directional → |ratio| near 1 |
Adaptive Parameter Summary
| Parameter | Range Mode | Weak Trend | Strong Trend |
|---|---|---|---|
| Grid distance | ATR × mult × 0.8 | ATR × mult | ATR × mult × 1.5 |
| Grid minimum | Always ≥ InpGridDistance — even after regime multipliers, the effective grid distance is never smaller than the configured minimum. This prevents overly tight grids in any regime. | ||
| Max grid | InpMaxGrid × 1.5 | InpMaxGrid | InpMaxGrid × 0.5 |
| Lot size | InpLotSize × 1.0 | InpLotSize × 1.0 | InpLotSize × 0.3 |
| BB entry | Active | No | No |
| Auto close | No | No | When ADX ≥ TrendADXExit |
🌲 Random Forest Engine
Built entirely from scratch in MQL4/MQL5 — no external libraries.
Training Algorithm
- Bootstrap Sampling — each tree trains on a random sample with replacement, same size as training set
- Random Feature Subset — at each split, only √m ≈ 11 random features are considered (decorrelates trees)
- Gini Impurity — weighted split criterion with class weight support for imbalanced data
- Recursive Splitting — stops when max depth, min samples, or pure node reached
- OOB Estimation — out-of-bag samples are tracked during training for unbiased error estimation
- Feature Importance — each feature's usage as a split node is counted across all trees
Tree Node Structure
Each tree is stored as 6 flat arrays (for MQL compatibility):
feat[i]— feature index for split (‑1 = leaf node)thresh[i]— split threshold valueleft[i],right[i]— child node indicesvalue[i]— leaf probability of class 1 (0 for internal nodes)treeStart[t]— root node index of tree t in the flat array
📐 Feature Engineering
120 features total: 60 price-relative + 60 technical indicators.
Price-Relative Features (60)
For each of the last 15 candles (InpBack), 4 relative change ratios:
| Feature Group | Count | Formula |
|---|---|---|
| open_i | 15 | (Open[i] − Open[0]) / Open[0] |
| high_i | 15 | (High[i] − High[0]) / High[0] |
| low_i | 15 | (Low[i] − Low[0]) / Low[0] |
| close_i | 15 | (Close[i] − Close[0]) / Close[0] |
Technical Indicators (60)
| Group | Count | Description |
|---|---|---|
| SMA ratios | 6 | Price relative to SMA 10/20/30/50/100/200 |
| RSI | 3 | RSI 7/14/21 normalised to [0,1] |
| MACD histogram | 3 | Normalised histogram for 3 MACD configs |
| ATR | 3 | ATR 7/14/21 normalised by price |
| Bollinger %B | 3 | %B for periods 10/20/50 |
| ADX | 3 | ADX 7/14/21 normalised |
| Momentum ROC | 6 | Rate of change over 3/5/10/15/20/30 bars |
| Candle anatomy | 4 | Body ratio, lower wick, upper wick, direction |
| Volatility ratios | 2 | Current range / avg range, current body / avg body |
🔲 Grid Trading Logic
Trade Conditions
| Action | Buy Model (B) | Sell Model (S) | Trend (W) | Hedge (H) |
|---|---|---|---|---|
| BUY | ≥ 0.5 | — | ≥ 0.5 | ≥ 0.5 |
| SELL | — | ≥ 0.5 | < 0.5 | < 0.5 |
Grid Entry
- First entry — when RF signal meets conditions (or BB touch in range mode)
- Grid levels — added after 1 candle period when price moves ≥ grid distance against the position
- Range mode — tighter grid (0.7×) + more levels (1.5×) + BB mean reversion entries
- Trend mode — wider grid (1.5×) + fewer levels (0.5×) + reduced lot size (0.3×)
Position Management
- TP — recalculated every cycle:
avgPrice ± totalTP / count - SL — set on last grid entry price ± SL distance once price moves favorably
- Trailing — SL follows price at configured distance, locks profit
🌊 Regime Detection System
The regime detection runs every candle and produces a score from 0.0 (strong range) to 1.0 (strong trend).
RANGE Score < 0.35
Tighter grid, more levels, BB mean reversion entries, normal lot sizing. The EA aggressively captures range bounces.
WEAK TREND Score 0.35–0.65
Standard grid parameters, trend filter active. Normal operation with directional awareness.
STRONG TREND Score ≥ 0.65
Fewer levels, wider gaps, reduced lot size. All positions auto-close when ADX ≥ InpTrendADXExit.
Bollinger Band Mean Reversion (Range Mode)
When the market is classified as ranging, the EA also opens trades when price touches the outer Bollinger Bands: Buy when Bid ≤ lower BB + gridDist, Sell when Ask ≥ upper BB − gridDist. This acts as a simple mean-reversion entry mechanism in addition to the ML signal.
❓ Frequently Asked Questions
How long does the first training take?
Typically 5–30 seconds for 1000 bars × 20 trees × 8 depth on H1. Training runs once on the first tick, then every `InpRetrainBars` candles.
Can I use this with any symbol?
Yes. The feature engineering is purely price-based — no symbol-specific parameters. However, performance varies by market. The EA is designed for forex, metals, and indices that exhibit mean-reverting behaviour.
Does it work in backtesting?
Yes. Each training run uses historical data only (no future leak). The labels are generated using forward-looking windows but the EA only sees closed candles at prediction time.
What's the recommended starting config?
Start with defaults on H1 XAUUSD or EURUSD. Monitor for 1–2 weeks. If drawdown is high, increase InpTrendStrength, lower InpRangeADXMax, or decrease InpLotSize.
Why does the EA sometimes not trade for many bars?
The signal conditions are strict — all 3 relevant models must agree (B+W+H or S+W+H). If the market is random or the models assign low probabilities, no trades will be taken. This is by design.
How much CPU does training use?
Training is CPU-intensive but runs only every 24+ bars (~once per day on H1). It uses the terminal's main thread so you may see slight UI lag during training. The EA throttles to 1 tick per second.
📬 Contact & Support
For bug reports, feature requests, or custom EA development, please reach out via email or Telegram. Include the EA version number, your MT5/MT4 build version, and a brief description of the issue.