Pipsgrowth EX09007 MeanReversion
MT5 Expert Advisor (Open Source) · XAUUSD · M5, H1
Pipsgrowth.com EX09007 HangingManHammer MFI — candlestick reversal + MFI confirm, full 12-layer stack.
Overview
EX09007 looks for a very specific candle shape: a body in the upper third of the bar with a lower wick at least twice as long as the body, and a lower wick longer than the upper wick. That geometric definition is what most retail traders call a Hammer (bullish reversal) or a Hanging Man (bearish reversal) — but here it is computed in the SignalPattern() function on the just-closed M5 bar (shift=1), with a precise threshold: the body must sit in the upper third of the bar's range (bodyBot > high - range/3.0) and lowerWick >= 2.0 * bodySize. That last clause is what disqualifies a lot of "looks like a hammer" candles — the lower wick has to be at least double the body, not merely noticeable.
Pattern alone is not enough. The EA also reads a 5-period SMA on the same timeframe for trend context: a Hammer must close below the SMA(5) — meaning the bar printed in an existing micro-downtrend — and a Hanging Man must close above the SMA(5). That SMA gate ensures the EA is fading short-term momentum rather than buying strength. After the trend gate comes the third filter: the Money Flow Index with period 37. A Hammer must print with MFI below 40 (sell-pressure exhaustion), and a Hanging Man must print with MFI above 60 (buy-pressure exhaustion). The two inputs InpMFIBuyMax=40.0 and InpMFISellMin=60.0 are the literal thresholds; the confidence output of SignalPattern() is computed as 50 + |offset|*1.2 capped at 100, but it is logged only and not gating — only the pattern match plus the threshold comparisons actually matter for the entry decision.
A high-confidence pattern is not by itself enough to fire. The EA runs a full 7-state regime classifier via ClassifyRegime() using ADX(14), a 100-bar ATR(14) percentile, and a Bollinger-Band width z-score (period 20, deviation 2.0). The seven states are StrongTrend, WeakTrend, Range, Breakout, Compress, Expand, and Choppy. RegimeAllowsEntry() permits entries only in three of them: Range, Compress, and WeakTrend. StrongTrend, Breakout, Expand, and Choppy are blocked. The intent is straightforward — mean reversion only works when the market is not trending hard and not in a volatility expansion. A Hammer forming inside a StrongTrend regime is a continuation signal, not a reversal, and is ignored.
Before the order is even sized, three more confirmations must pass in ComputeConfirm(). The HTF EMA filter pulls a 50-period EMA on H1 (HTF_TIMEFRAME = PERIOD_H1): a Hammer is only confirmed if the M5 close is below the H1 EMA — a pullback context — and a Hanging Man only if the close is above it. That single cross-timeframe gate is what stops the EA from fading a clean H1 trend on a 5-minute "fake" Hammer. The spread gate allows a 35-point absolute cap (MAX_SPREAD_POINTS=35) or 3× the rolling 20-bar average spread, whichever is tighter, when InpMaxSpreadOverAvg=3. The R:R gate enforces tpDist / slDist >= 1.2 (the constant MIN_RR_RATIO) — a thin trade is never taken.
Risk math is straightforward. CalcLotByRisk() reads the SL distance in price, divides effective capital by tick_value / tick_size to get the per-lot risk, and sizes the order so that 0.5% * effective_capital is at risk per trade (InpRiskPercent=0.5). The lot is then clamped to the symbol's volume step and to InpMaxLots=5.0. The capital base is the minimum of equity and InpCapitalCapAmount (when the cap is non-zero), which is the EA's way of letting you cap exposure at a fixed dollar figure on a larger account — setting the cap to 0 disables it.
Five exit paths run on every tick through ManageOpenPosition(). First, a one-shot break-even at 1.0R (BE_TRIGGER_R=1.0): once profit equals the initial risk, the stop is moved to entry + 2 points. Second, a partial close at 1.0R (PARTIAL_TP_R=1.0): 50% of the position is closed (PARTIAL_FRACTION=0.5), with the heuristic that the lot must be at least twice the symbol's volume minimum — otherwise the partial is skipped to avoid a too-small residual. Third, an ATR(14) trailing stop at 2.5×ATR (TRAIL_ATR_MULT=2.5) with a 10-point step (TRAIL_STEP_POINTS=10), forward-only, that only ratchets in the profitable direction. Fourth, an opposite-pattern exit: if a Hammer prints against an existing long, the position is closed immediately, and vice versa. Fifth, a regime-change exit: if the classifier flips into StrongTrend, Breakout, or Expand — the states that block entries — the position is force-closed, because the mean-reversion thesis is no longer valid. A 60-bar time stop (MAX_BARS_IN_TRADE=60) layers on top of that stack, which is roughly 5 hours on the M5 default.
The no-trade system around all of this is one of the more comprehensive in the corpus. The NoTradeReason() function returns a string tag for the first failure and short-circuits: kill switch on, broker not allowing trades, terminal disconnected, equity below the 50-dollar floor (InpCapitalCapFloor=50.0), outside the 07:00-20:00 server-time session (SESSION_START_HOUR=7, SESSION_END_HOUR=20), weekend (Saturday or Sunday), current spread above 35 points, a ±30-minute window around each hour boundary treated as a generic news guard (NEWS_WINDOW_MIN=30), regime blocked, 5 trades already taken today (MAX_DAILY_TRADES=5), the 5-bar cooldown after a loss (COOLDOWN_BARS_AFTER_LOSS=5), or 1 position already open (InpMaxConcurrent=1). The session window is in broker server time, not auto-detected GMT — a user on a GMT+2 broker sees the live window at 05:00-18:00 UTC. The news guard is a primitive time-based proxy, not an MQL5 economic-calendar feed.
Risk management outside the trade is enforced after entries: a daily 3% loss of effective capital (InpDailyLossLimitPct=3.0) and a weekly 6% loss (InpWeeklyLossLimitPct=6.0) trigger a force-close of any open position via the RealizedPnLToday() and RealizedPnLThisWeek() history walkers. These walk the deal history from start-of-day and start-of-Monday to now, filtering by InpMagic and symbol, summing profit + swap + commission. The OnTester custom criterion multiplies net profit by profit factor and divides by 1 + drawdown_percent, with a 30-trade minimum to prevent over-fit curves from scoring well. Trade-execution transient errors are absorbed by a 1-retry loop with a 150ms sleep on REQUOTE, PRICE_OFF, PRICE_CHANGED, CONNECTION, and TIMEOUT retcodes; close operations are wrapped in a 3-retry 200ms loop that also covers PRICE_OFF and PRICE_CHANGED, but TryModify_EX09007 only retries on REQUOTE and TIMEOUT — a small gap where a price-change reject on a stop modification will not retry.
Two defaults deserve a callout. InpDryRun=true ships enabled — every order attempt is logged with the [DRYRUN] prefix and no live order is sent. That is a deliberate safe default for forward testing but it means the EA does nothing in live until the user flips the input. InpKillSwitch=false is the other binary that needs to be off for trading; turning it on hard-blocks all new entries regardless of conditions. The portfolio-heat cap of 6% (PORTFOLIO_HEAT_CAP=0.06) is estimated from CountOurPositions() * InpRiskPercent / 100.0, a crude but effective size-based proxy.
For backtests, expect this EA to fire on Gold in the 07:00-20:00 server window most often on bars that print the geometric pattern with MFI exhaustion — typically 1 to 3 times per London-NY overlap on a 5-minute chart, more on volatile days. The 60-bar time stop is a hard ceiling: a trade that hasn't paid by 5 hours closes regardless of MFI. The two combination gates that most often kill an otherwise valid pattern are the H1 EMA pullback requirement (which filters out "buy the breakout" patterns) and the regime classifier (which filters out the strongest trend days, where the Hammers print as continuation candles). A user wanting more trades should look at lowering MIN_RR_RATIO or widening the regime allowlist in RegimeAllowsEntry() — both reduce selectivity in measurable ways. The pyramid constants PYRAMID_MAX_LEVELS=5 and PYRAMID_ATR_SPACING=1.5 are defined but unused at runtime, because InpMaxConcurrent=1 forces a single open position; they are leftover scaffolding from a strategy variant.
Strategy Deep Dive
SignalPattern() runs on the closed M5 bar and returns +1 for a Hammer or -1 for a Hanging Man based on the geometric rule bodyBot > high - range/3 and lowerWick >= 2*bodySize && lowerWick > upperWick, then gates the call with the SMA(5) trend direction and the MFI(37) exhaustion threshold. The full OnTick() flow is: refresh symbol data, classify regime via ADX(14) + Bollinger-width z-score + ATR(14) percentile, walk all the no-trade checks (kill switch, capital floor, session, weekend, spread, news window, regime, daily-trade limit, cooldown, concurrent cap), pull the signal, compute the H1 EMA(50) pullback confirmation, size the lot via CalcLotByRisk() against 0.5% of effective capital, and submit through the 1-retry transient-error wrapper in SendOrder(). ManageOpenPosition() runs on every tick on top of the same flow, walking the BE → partial → ATR trail → opposite-signal → regime-change → time-stop stack. The full input surface is 18 user-tunable values across 7 input groups; the only binary that ships in a non-default state is InpDryRun=true, which logs orders as [DRYRUN] and sends nothing live until the user flips it.
The EA enters long when a closed M5 bar matches the geometric Hammer pattern — body in the upper third of the bar's range with lower wick at least 2× the body size and a longer lower than upper wick — and the bar's close sits below the SMA(5), with MFI(37) below 40. The mirror short entry fires on a Hanging Man (same geometry) closing above the SMA(5) with MFI(37) above 60. The 7-state regime classifier must allow the entry (Range, Compress, or WeakTrend only), the H1 EMA(50) pullback gate must agree, and the live spread must clear the 35-point cap or 3× the rolling average.
A 5-path exit stack runs every tick: one-shot break-even at 1.0R moves the stop to entry + 2 points, a 50% partial close at 1.0R is attempted (only if the residual would still be at least 2× the symbol's volume minimum), and an ATR(14)×2.5 trailing stop with a 10-point forward step ratchets behind price. The position is force-closed if the regime classifier flips into StrongTrend, Breakout, or Expand, if a candle of the opposite pattern prints, or after 60 M5 bars (roughly 5 hours). A 3% daily or 6% weekly loss of effective capital also force-closes via the deal-history walkers.
Stop loss is ATR(14) × 1.8 on the closed bar at signal time, snapped outward to honor the symbol's stops level. With MIN_RR_RATIO=1.2 enforced on top via the confirm gate, the minimum distance is the ATR multiple — the EA will never size a tighter stop than that.
Take profit is ATR(14) × 3.0 from entry, giving a 1.67:1 R:R at signal time. The TP price is also snapped outward to respect the broker's stops level minimum, and a 50% partial close at 1.0R is attempted before the full TP can be hit.
Best on XAUUSD M5 during the broker-server 07:00-20:00 window, which on a GMT+2 broker is the 05:00-18:00 UTC London-NY overlap where MFI exhaustion patterns print most often. Minimum recommended balance is $100 with the default 0.5% risk, and InpMaxLots=5.0 caps the per-trade lot to keep the EA compatible with micro-lot accounts — raise InpMaxLots and lower InpRiskPercent proportionally for larger books. The EA needs a low-spread ECN or RAW account because the 35-point spread cap and 3× rolling-average filter will block entries during wide-spread events, and the user must remember to flip InpDryRun to false before live trading.
Strategy Logic
Pipsgrowth EX09007 MeanReversion — Strategy Logic Analysis (from .mq5 source)
Family: MeanReversion
Magic: 22209007
Version: 2.00
BRIEF:
Hanging Man (bearish) / Hammer (bullish) candlestick on last CLOSED bar + MFI confirmation (MFI<40 Buy / MFI>60 Sell). 12 layers: REGIME, SIGNAL, ENTRY, CONFIRM, NO-TRADE, CAPITAL CAP, RISK, SIZING, MANAGE, EXIT, SCALING, OnTester
INDICATOR STACK:
- Standard
MT5indicators
KEY FUNCTIONS:
Norm()ClampVolume()PointsToPrice()StopsLevelPrice()CopyBuf()MFIVal()MAVal()ATRVal()ADXVal()HTFEMAVal()GetBBWidthZ()GetATRPctile()- ...and 28 more
INTERNAL CONSTANTS (36 total):
ATR_REG_PERIOD= 14 //ATRperiod for regimeATR_PCTILE_LOOKBACK= 100 //ATRpercentile windowBB_REG_PERIOD= 20 // Bollinger Band period (regime)BB_REG_DEV=2.0// Bollinger Band deviationADX_REG_PERIOD= 14 //ADXperiod (regime)HTF_TREND_PERIOD= 50 //HTFEMAperiodHTF_TIMEFRAME=PERIOD_H1//HTFtimeframe for trend agreementAVG_BODY_PERIOD= 12 // candle avg body period (pattern)MA_TREND_PERIOD= 5 // shortSMAfor pattern trend contextMFI_PERIOD_DEFAULT= 37 //MFIoscillator periodMFI_VOL_TYPE=VOLUME_TICK//MFIapplied volume typeREG_STRONG_ADX= 28 //ADX>= this =>StrongTrendREG_RANGE_ADX= 20 //ADX<= this => range-ishREG_COMP_BBZ=0.8//BB-width zscore <= => CompressREG_EXP_BBZ=1.5//BB-width zscore >= => Expand- ...and 21 more
INPUT PARAMETERS (21 total across 7 groups):
- [=== Identity ===]
InpMagic=22209007// Magic number (2220000+ 554) - [=== Identity ===]
InpTradeComment= "Psgrowth.com Expert_09007" // Trade comment - [=== Risk & Sizing ===]
InpRiskPercent=0.5// Risk per trade, % of effective capital - [=== Risk & Sizing ===]
InpDailyLossLimitPct=3.0// Daily loss limit, % of effective capital - [=== Risk & Sizing ===]
InpWeeklyLossLimitPct=6.0// Weekly loss limit, % of effective capital - [=== Risk & Sizing ===]
InpMaxLots=5.0// Hard cap on lot size per trade - [=== Risk & Sizing ===]
InpMaxConcurrent= 1 // Max concurrent positions (this symbol/magic) - [=== Risk & Sizing ===]
InpSlippagePoints= 20 // Max slippage in points - [=== Capital Allocation Cap ===]
InpCapitalCapAmount=0.0// Cap amount inREALequity $ - [=== Capital Allocation Cap ===]
InpCapitalCapFloor=50.0// Floor below which entries are blocked - [===
Signal(Pattern +MFI) ===]InpMFIPeriod= 37 //MFIoscillator period - [===
Signal(Pattern +MFI) ===]InpMFIBuyMax=40.0//MFIupper bound to confirmHammer(Buy) - [===
Signal(Pattern +MFI) ===]InpMFISellMin=60.0//MFIlower bound to confirmHangMan(Sell) - [=== Regime / Confirm ===]
InpHTFBarAgree= 1 // 1=requireHTF-EMAside agreement, 0=skip - [=== Regime / Confirm ===]
InpMaxSpreadOverAvg= 3 // Max spread multiple over rolling avg (x), 0=off - [=== Exit / Manage ===]
InpUseBreakEven=true// Enable break-even atBE_TRIGGER_R - [=== Exit / Manage ===]
InpUsePartialTP=true// Enable partial TP atPARTIAL_TP_R - [=== Exit / Manage ===]
InpUseATRTrail=true// EnableATRtrailing stop - [=== Exit / Manage ===]
InpExitOnOppSignal=true// Exit on opposite candlestick pattern - [=== Dry-Run / Kill Switch ===]
InpDryRun=true// Dry-run mode (no live orders) - [=== Dry-Run / Kill Switch ===]
InpKillSwitch=false// Emergency kill switch (block all trading)
// Pipsgrowth EX09007 MeanReversion — Execution Flow (from source analysis)
// Family: MeanReversion
// Hanging Man (bearish) / Hammer (bullish) candlestick on last CLOSED bar + MFI confirmation (MFI<40 Buy / MFI>60 Sell). 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
How to Install This EA on MT5
- 1Download the .mq5 file using the button above
- 2Open MetaTrader 5 on your computer
- 3Click File → Open Data Folder in the top menu
- 4Navigate to MQL5 → Experts and paste the .mq5 file there
- 5In MT5, right-click Expert Advisors in the Navigator panel → Refresh
- 6Drag the EA onto an H1 or H4 chart
- 7Set Bollinger Band period, deviation, RSI levels, and lot size
- 8Enable Allow Algo Trading and click OK
EA Parameters
| Parameter | Default | Description |
|---|---|---|
| InpMagic | 22209007 | Magic number (2220000 + 554) |
| InpTradeComment | "Psgrowth.com Expert_09007" | Trade comment |
| InpRiskPercent | 0.5 | Risk per trade, % of effective capital |
| InpDailyLossLimitPct | 3.0 | Daily loss limit, % of effective capital |
| InpWeeklyLossLimitPct | 6.0 | Weekly loss limit, % of effective capital |
| InpMaxLots | 5.0 | Hard cap on lot size per trade |
| InpMaxConcurrent | 1 | Max concurrent positions (this symbol/magic) |
| InpSlippagePoints | 20 | Max slippage in points |
| InpCapitalCapAmount | 0.0 | Cap amount in REAL equity $ |
| InpCapitalCapFloor | 50.0 | Floor below which entries are blocked |
| InpMFIPeriod | 37 | MFI oscillator period |
| InpMFIBuyMax | 40.0 | MFI upper bound to confirm Hammer (Buy) |
| InpMFISellMin | 60.0 | MFI lower bound to confirm HangMan (Sell) |
| InpHTFBarAgree | 1 | 1=require HTF-EMA side agreement, 0=skip |
| InpMaxSpreadOverAvg | 3 | Max spread multiple over rolling avg (x), 0=off |
| InpUseBreakEven | true | Enable break-even at BE_TRIGGER_R |
| InpUsePartialTP | true | Enable partial TP at PARTIAL_TP_R |
| InpUseATRTrail | true | Enable ATR trailing stop |
| InpExitOnOppSignal | true | Exit on opposite candlestick pattern |
| InpDryRun | true | Dry-run mode (no live orders) |
| InpKillSwitch | false | Emergency kill switch (block all trading) |
#property copyright "Pipsgrowth.com"
#property link "https://pipsgrowth.com"
#property version "2.00"
#property strict
#property description "Pipsgrowth.com EX09007 HangingManHammer MFI — candlestick reversal + MFI confirm, full 12-layer stack."
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\AccountInfo.mqh>
#include <Trade\OrderInfo.mqh>
#include <Trade\DealInfo.mqh>
//================== TUNABLE CONSTANTS (NOT inputs) =================
#define ATR_REG_PERIOD 14 // ATR period for regime
#define ATR_PCTILE_LOOKBACK 100 // ATR percentile window
#define BB_REG_PERIOD 20 // Bollinger Band period (regime)
#define BB_REG_DEV 2.0 // Bollinger Band deviation
#define ADX_REG_PERIOD 14 // ADX period (regime)
#define HTF_TREND_PERIOD 50 // HTF EMA period
#define HTF_TIMEFRAME PERIOD_H1 // HTF timeframe for trend agreement
#define AVG_BODY_PERIOD 12 // candle avg body period (pattern)
#define MA_TREND_PERIOD 5 // short SMA for pattern trend context
#define MFI_PERIOD_DEFAULT 37 // MFI oscillator period
#define MFI_VOL_TYPE VOLUME_TICK // MFI applied volume type
#define REG_STRONG_ADX 28 // ADX >= this => StrongTrend
#define REG_RANGE_ADX 20 // ADX <= this => range-ish
#define REG_COMP_BBZ 0.8 // BB-width zscore <= => Compress
#define REG_EXP_BBZ 1.5 // BB-width zscore >= => Expand
#define ATR_PCTILE_STRONG 80 // ATR percentile >= => high vol
#define ATR_PCTILE_LOW 20 // ATR percentile <= => low vol
#define SL_ATR_MULT 1.8 // SL = ATR(closed bar) * mult
#define TP_ATR_MULT 3.0 // TP = ATR(closed bar) * mult
#define TRAIL_ATR_MULT 2.5 // ATR trailing distance
#define TRAIL_STEP_POINTS 10 // trail step (points)
#define BE_TRIGGER_R 1.0 // break-even trigger at 1.0R
#define PARTIAL_TP_R 1.0 // partial TP at 1.0R
#define PARTIAL_FRACTION 0.5 // partial close 50%
#define MAX_BARS_IN_TRADE 60 // time-based exit (bars)
#define MAX_SPREAD_POINTS 35 // spread cap (points)
#define MAX_DAILY_TRADES 5 // max entries per day
#define COOLDOWN_BARS_AFTER_LOSS 5 // cooldown after loss
#define MIN_RR_RATIO 1.2 // min reward:risk
#define SESSION_START_HOUR 7 // server-time session start
#define SESSION_END_HOUR 20 // server-time session end
#define NEWS_WINDOW_MIN 30 // manual news window (min around HH:00)
#define PYRAMID_MAX_LEVELS 5 // pyramid hard cap
#define PYRAMID_ATR_SPACING 1.5 // pyramid ATR spacing
#define PORTFOLIO_HEAT_CAP 0.06 // max portfolio heat 6%
#define MAX_TRADE_RETRIES 1 // trade-send retry on transient
#define INP_VERSION_TAG "v2.00 MeanRev HangHam/MFI" // version tag (log only)
//================== INPUTS (18 total) ==============================
input group "=== Identity ==="
input long InpMagic = 22209007; // Magic number (2220000 + 554)
input string InpTradeComment = "Psgrowth.com Expert_09007"; // Trade comment
input group "=== Risk & Sizing ==="
input double InpRiskPercent = 0.5; // Risk per trade, % of effective capital
input double InpDailyLossLimitPct = 3.0; // Daily loss limit, % of effective capitalFull source code available on download
Educational purposes only. Do NOT use with real money. Test on demo accounts only.
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
Markets.com
Exness
IC Markets
Similar Expert Advisors
View All Expert AdvisorsMore Mean Reversion strategy EAs from our library
Pipsgrowth EX09013 MeanReversion
Pipsgrowth.com EX09013 Bollinger_Bands_EA — BB mean reversion with trend filter, full 12-layer stack.
Pipsgrowth EX09009 MeanReversion
Pipsgrowth.com EX09009 HangingManHammer Stoch — candlestick reversal + Stochastic confirm, full 12-layer stack.
Pipsgrowth EX09023 MeanReversion
Pipsgrowth.com EX09023 BollingerMeanReversion — BB outer band fade, full 12-layer stack.
Community
Educational purposes only. Do NOT use with real money. Test on demo accounts only.