P
PipsGrowth
Mean ReversionOpen Source – Free

Pipsgrowth EX09021 MeanReversion

MT5 Expert Advisor (Open Source) · XAUUSD · M5, H1

Pipsgrowth.com EX09021 ExpWPRBB — WPR + Bollinger Bands mean-reversion with ATR SL/TP, full 12-layer stack.

Overview

EX09021 is a Bollinger-Bands-and-Williams-Percent-Range mean-reversion EA that requires both indicators to agree before it fires. The WPR(32) is unusually long for a momentum oscillator (most MR EAs use 14) and the BB(58) is similarly stretched well past the default 20 — that combination is deliberate. The longer periods filter out single-bar noise and only flag exhaustion events that have actually built up over hundreds of bars, which is why the EA was tuned to M5 and up rather than M1. ATR(64) feeds the dynamic stop and target distances and tracks recent volatility on the same slow timeframe, so SL/TP scale with whatever regime the symbol is actually in.

The signal pipeline runs in two stages. SignalWPR() looks at the WPR on bar-1 versus bar-2 — a long fires when the WPR on bar-1 is above its value on bar-2 and the bar-2 value was at or below -80 (the oversold line). A short is the mirror: bar-1 below bar-2 with bar-2 at or above -20 (the overbought line). So the trigger is WPR exiting an extreme zone, not WPR being in one. SignalBB() then checks the bar-0 open against the midpoints of the outer half of the BB envelope — (lower+middle)/2 for the long side, (upper+middle)/2 for the short side. A long fires when the open is below the lower-midpoint, meaning price is in the outer half of the band, not just touching the lower rail. The two signals are AND-ed in OnTick(): only when both agree does TradeProcess() see a long or short. If WPR says oversold-exit but price is still near the middle, or vice versa, the EA does nothing.

Position management is where EX09021 differs from a vanilla band-touch bot. The TradeProcess() function checks IsPresentPosOnCurrentBar() first — only one new entry per direction per bar, which prevents over-trading when an oscillating market flips WPR on the same bar twice. More importantly, the pyramiding rule is better-price-only: for a long, the EA compares the open price of the most recent buy position against the current ask and only adds when the new ask is lower (price_last > SymbolInfoDouble(SYMBOL_ASK)). For shorts, it adds only when the new bid is higher than the previous short. That makes the scaling a quality-averager, not a martingale — it tightens the average entry on a continued move, not the other way around. There is no fixed cap on pyramid count; the gating condition is the price-improvement check, and the per-bar dedup.

Stops and targets default to dynamic ATR and BB widths. The InpStopLoss input accepts three states: 0 = no SL, positive integer = fixed points, -1 = derived from HalfSizeBB(0) * InpSLMltp (default 2.6). The InpTakeProfit input does the same: 0 = none, positive = fixed points, -1 = ATR(0) * InpTPMltp (default 1.3, in points). So at defaults, the SL is 2.6 times the half-width of the BB envelope and the TP is 1.3 times the 64-period ATR — typically a 1.5:1 to 2.5:1 reward-to-risk on M5 metals depending on the volatility regime. On netting accounts, OpenPosition() zeroes out both SL and TP (line 958) because the broker will only hold one position per symbol and a static SL/TP would block averaging — the EA explicitly warns at init that it expects a hedging account.

The safety stack is the standard 9-gate family pattern, applied via IsSafeToTrade_EX09021(). The gates, in order, are: cap-amount reached (InpCapAmount > 0 and equity >= cap), cap-floor breach (equity < InpCapFloor, default 50), 95% of initial-balance floor, 3% daily realized-loss cap, 3-consecutive-losses cooldown (default 30 minutes), 50 trades per day, market-open check (no trading Friday after 21:00 GMT, all Saturday, Sunday before 22:00 GMT), active-session check (London 07:00–16:00 GMT and New York 12:00–21:00 GMT union, with the Asia window 00:00–07:00 GMT excluded by default), and an optional ±15-minute news filter around the London and NY session open hours. The OnTradeTransaction() handler updates g_realizedToday, g_tradesToday, and g_consecLosses from the actual deal stream, not the EA's own bookkeeping — so the daily counters survive restarts within the same session and match the broker's history. The DetectGMTOffset_EX09021() function walks back through H1 bars looking for a 3+ hour weekend gap, then subtracts 22 to infer the offset, falling back to InpServerGMTOffset if you set it manually.

The entry/exit path also has a race-condition guard. IsUncertainStateEnv() walks the order pool looking for an order with the right magic and symbol but no position ID — that's the gap between a fill being accepted and the position being registered. If the EA finds that state, it sleeps 1000 ms and retries up to 3 times (ENV_ATTEMPTS=3, ENV_WAIT_ATTEMPT=1000) before refusing to act. The same pattern guards OpenPosition() directly. TryClose_EX09021() retries a position close up to 3 times at 200 ms on REQUOTE, TIMEOUT, PRICE_OFF, and PRICE_CHANGED — anything else (PRICE_INVALID, REJECT, etc.) is treated as a hard fail. Filling mode is auto-detected from SYMBOL_FILLING_MODE and falls back to RETURNIOCFOK depending on what the broker advertises, which keeps the EA compatible with ECN, exchange, and instant-execution setups.

The OnTester() formula is the family-standard n * p / (1 + d) — net profit times profit factor divided by relative equity drawdown plus one — with a 30-trade minimum and a guard that returns 0 if profit factor is non-positive or drawdown is zero. That's the fitness function the MT5 optimizer maximizes, so the backtest results in the Strategy Tester are ranking candidates on risk-adjusted return, not raw PnL.

For practical use, EX09021 is a M5-and-up mean-reversion system tuned for the long-period family (WPR32, BB58, ATR64). It expects a hedging account and works on both metals (XAUUSD is the default symbol in the deployable version) and FX majors. The pyramid-on-better-prices rule means it does not grid in a martingale sense — the EA only adds when the market has continued in the expected direction. That makes drawdowns materially different from a classic grid bot: instead of stacking into a losing position, the EA stacks into a winning one and tightens the average entry.

Strategy Deep Dive

EX09021 runs two independent signal generators per tick and trades only when they agree. WPR(32) flags momentum exhaustion by looking for a bar-1 WPR crossing out of the -80 / -20 zones; BB(58, 2.0) flags price in the outer half of its envelope by comparing bar-0 open against the midpoints of the lower-half and upper-half of the band. OnTick() AND-s the two and dispatches to TradeProcess(), which checks IsPresentPosOnCurrentBar() to prevent same-bar re-entries and then either opens a new position or pyramid-adds at a strictly better price. The OpenPosition() function computes dynamic SL/TP from half-BB-width and ATR(64) using the multipliers, and the CTrade wrapper uses GetTypeFilling() to pick RETURN / IOC / FOK based on what the broker advertises. Before any of that, IsSafeToTrade_EX09021() runs the 9-gate safety stack — cap, floor, 95% equity, daily loss, consec-loss cooldown, max-trades, market open, session, news — and OnTradeTransaction() updates the daily counters from the deal stream. The race-condition guard IsUncertainStateEnv() waits up to 3×1000 ms for an order to settle into a position before letting OpenPosition() submit, which keeps a fast market from causing duplicate entries. OnTester() ranks candidates on n*p/(1+d) with a 30-trade minimum.

Entry Signal

Entries require both WPR(32) and BB(58) to agree. WPR fires long when bar-1 WPR crosses up from ≤-80 (oversold exit) and short when bar-1 WPR crosses down from ≥-20 (overbought exit). BB fires when bar-0 open is in the outer half of the band (below the (lower+middle)/2 midpoint for long, above the (upper+middle)/2 midpoint for short). Both signals must match in OnTick() for the EA to trade.

Exit Signal

Exits are price-driven by SL and TP — there is no time-based or reverse-signal close. Positions are managed entirely by the dynamic or fixed SL/TP set at entry; no break-even move, no trailing stop, no partial close, and no opposite-signal exit is implemented. Pyramid adds continue in the same direction as long as the new entry is at a better price.

Stop Loss

SL is half the BB envelope width × InpSLMltp (default 2.6) when InpStopLoss = -1, a fixed-point distance when InpStopLoss > 0, or disabled when InpStopLoss = 0. On netting accounts both SL and TP are zeroed in OpenPosition() because the EA explicitly expects a hedging account. There is no in-trade trailing or break-even adjustment.

Take Profit

TP is ATR(64) × InpTPMltp (default 1.3, in points) when InpTakeProfit = -1, a fixed-point distance when InpTakeProfit > 0, or disabled when InpTakeProfit = 0. At defaults the implied R:R is roughly 1.5:1 to 2.5:1 on M5 metals. TP is not adjusted after entry.

Best For

Minimum balance: $100 (the InpCapFloor default is 50, the 95% initial-equity floor is the binding constraint for small accounts). Best on M5 and H1 on XAUUSD; portable to FX majors. Run during London 07:00–16:00 GMT and New York 12:00–21:00 GMT — the InpAvoidAsia default excludes the Asian session. Hedging account is required (the EA prints a warning and zeros SL/TP on netting). Use a low-spread ECN broker because the WPR+BB agreement gate already thins the trade stream and wide spreads will filter the rest out. The InpMaxTradesPerDay = 50 cap, the 3% daily loss limit, and the 3-consec-losses 30-minute cooldown make it usable on accounts down to micro-lot size.

Strategy Logic

Pipsgrowth EX09021 MeanReversion — Strategy Logic Analysis (from .mq5 source)

Family: MeanReversion Magic: 22209021 Version: 2.00

BRIEF: WPR + Bollinger Bands mean-reversion EA that buys when WPR exits oversold below the lower BB band and sells when WPR exits overbought above the upper BB band. Uses ATR-based dynamic SL/TP with configurable multipliers and pyramiding on better prices. Supports hedging and netting accounts. 12 layers: REGIME, SIGNAL, ENTRY, CONFIRM, NO-TRADE, CAPITAL CAP, RISK, SIZING, MANAGE, EXIT, SCALING, OnTester

INDICATOR STACK:

  • Standard MT5 indicators

KEY FUNCTIONS:

  • CopyPricesData()
  • CopyWPRData()
  • CopyBBData()
  • CopyATRData()
  • CopyIndicatorsData()
  • PriceOpen()
  • PriceHigh()
  • PriceLow()
  • PriceClose()
  • Time()
  • WPR()
  • BBUpper()
  • ...and 34 more

INTERNAL CONSTANTS (4 total):

  • DATA_COUNT = 3 // Количество получаемых данных от индикаторов (3 и более)
  • ENV_ATTEMPTS = 3 // Количество попыток ожидания получения окружения
  • ENV_WAIT_ATTEMPT = 1000 // Количество миллисекунд ожидания обновления окружения
  • SPREAD_MLTP = 3 // Множитель спреда для дистанции стоп-приказов

INPUT PARAMETERS (3 total across 3 groups):

  • [=== Identity ===] InpTradeComment = "Psgrowth.com Expert_09021" // Trade comment
  • [=== Bollinger Bands ===] InpPriceBB = 1 // Applied price (1=close,2=open,3=high,4=low,5=median,6=typical,7=weighted) /* BB applied price */ // Цена расчёта BB
  • [=== Capital Allocation Cap ===] InpCapFloor = 50.0 // +------------------------------------------------------------------+
Pseudocode
// Pipsgrowth EX09021 MeanReversion — Execution Flow (from source analysis)
// Family: MeanReversion
// WPR + Bollinger Bands mean-reversion EA that buys when WPR exits oversold below the lower BB band and sells when WPR exits overbought above the upper BB band. Uses ATR-based dynamic SL/TP with configurable multipliers and pyramiding on better prices. Supports hedging and netting accounts. 12 layers: REGIME, SIGNAL, ENTRY, CONFIRM, NO-TRADE, CAPITAL CAP, RISK, SIZING, MANAGE, EXIT, SCALING, OnTester

ON_INIT:
    Create indicator handles: standard set
    Initialize state variables
    Detect broker GMT offset

ON_TICK:
    1. Refresh indicator buffers (closed-bar shift=1)
    2. Manage existing positions:
       - Break-even check
       - ATR trailing stop
       - Profit lock ratchet
       - Time-based exit
       - Opposite-signal exit
    3. If new bar:
       a. ClassifyRegime() — ADX/ATR/BB regime detection
       b. NoTradeGate() checks:
          - Market open + session filter
          - Spread limit
          - Cooldown after loss
          - Consecutive loss limit
          - Kill switch
          - Max drawdown
          - Max concurrent positions
          - Daily/weekly loss limits
       c. GenerateSignal() — strategy-specific entry logic
       d. CheckConfirm() — HTF alignment + R:R + ADX minimum
       e. Calculate position size from risk %
       f. Execute with retry logic
       g. Mark bar to prevent duplicates

ON_TESTER:
    Custom fitness = weighted(RecoveryFactor, ROI, ProfitFactor, TradeCount, Sharpe, Drawdown)

Optimization Profile

Optimized Brokers:
ExnessIC Markets
Optimized Symbols:
XAUUSD
Optimized Timeframes:
M5H1

How to Install This EA on MT5

  1. 1Download the .mq5 file using the button above
  2. 2Open MetaTrader 5 on your computer
  3. 3Click File → Open Data Folder in the top menu
  4. 4Navigate to MQL5 → Experts and paste the .mq5 file there
  5. 5In MT5, right-click Expert Advisors in the Navigator panel → Refresh
  6. 6Drag the EA onto an H1 or H4 chart
  7. 7Set Bollinger Band period, deviation, RSI levels, and lot size
  8. 8Enable Allow Algo Trading and click OK

EA Parameters

ParameterDefaultDescription
InpTradeComment"Psgrowth.com Expert_09021"Trade comment
InpPriceBB1Applied price (1=close,2=open,3=high,4=low,5=median,6=typical,7=weighted) /* BB applied price */ // Цена расчёта BB
InpCapFloor50.0+------------------------------------------------------------------+
Source Code (.mq5)Open Source
Pipsgrowth_com_EX09021.mq5
#property copyright "Pipsgrowth.com"
#property link      "https://pipsgrowth.com"
#property version   "2.00"
#property strict
#property description "Pipsgrowth.com EX09021 ExpWPRBB — WPR + Bollinger Bands mean-reversion with ATR SL/TP, full 12-layer stack."

#include <Trade\Trade.mqh>
#include <Arrays\ArrayLong.mqh>

//+------------------------------------------------------------------+
//| Перечисления                                                     |
//+------------------------------------------------------------------+
//--- Типы сигналов
enum ENUM_SIGNAL_TYPE
  {
   SIGNAL_TYPE_NONE,                                                 // Нет сигнала
   SIGNAL_TYPE_LONG,                                                 // Сигнал на покупку
   SIGNAL_TYPE_SHORT,                                                // Сигнал на покупку
  };

//--- Структура позиций
struct SData
  {
   CArrayLong  list_tickets;                                         // Список тикетов открытых позиций
   double      total_volume;                                         // Общий объём открытых позиций
  };

//--- Структура данных позиций по типам
struct SDataPositions
  {
   SData       Buy;                                                  // Данные позиций Buy
   SData       Sell;                                                 // Данные позиций Sell
  }
Data;
//+------------------------------------------------------------------+
  
  
//+------------------------------------------------------------------+
//| Макроподстановки                                                 |
//+------------------------------------------------------------------+
#define  DATA_COUNT        3                                         // Количество получаемых данных от индикаторов (3 и более)
#define  ENV_ATTEMPTS      3                                         // Количество попыток ожидания получения окружения
#define  ENV_WAIT_ATTEMPT  1000                                      // Количество миллисекунд ожидания обновления окружения
#define  SPREAD_MLTP       3                                         // Множитель спреда для дистанции стоп-приказов

//+------------------------------------------------------------------+
//| Входные параметры                                                |
//+------------------------------------------------------------------+
ENUM_APPLIED_PRICE MapAppliedPriceInt(int ap)
{
   switch(ap)
   {
      case 1: return PRICE_CLOSE;
      case 2: return PRICE_OPEN;
      case 3: return PRICE_HIGH;
      case 4: return PRICE_LOW;
      case 5: return PRICE_MEDIAN;
      case 6: return PRICE_TYPICAL;
      case 7: return PRICE_WEIGHTED;
      default: return PRICE_CLOSE;

Full source code available on download

Educational purposes only. Do NOT use with real money. Test on demo accounts only.

Tags:ex09021meanreversionpipsgrowthfreemt5xauusd

Clear Warning: Educational Purposes Only

Clear Warning: This Expert Advisor is for educational and testing purposes only. Do NOT use it with real money. Test only on demo accounts. Trading with real money involves substantial risk of capital loss. This does not constitute investment advice.

Recommended Brokers for This EA

These EAs run on MT5 — use a regulated broker with fast execution and tight spreads

Community

Sign in to contributeSign In

Educational purposes only. Do NOT use with real money. Test on demo accounts only.

File NamePipsgrowth_com_EX09021.mq5
File Size55.4 KB
Versionv2.00
PlatformMetaTrader 5
File Type.mq5 Source
StrategyMean Reversion
Risk LevelMedium Risk
Timeframes
M5H1
Currency Pairs
XAUUSD
Min. Deposit$100