Range & reversal
Bollinger-Band Range Mean Reversion
Original educational specification: fade a confirmed outer-band excursion only while a slow average is flat. It is a testable hypothesis, not a claim that Bollinger-band touches predict reversals.
- Category
- Range & reversal
- Timeframes
- H1
- Pairs
- EURUSD, GBPUSD, USDJPY
- Test status
- Mechanical bar tests completed; profitability unverified

How the rule works
A band excursion measures relative price, not a guaranteed turning point. The flat-SMA and ATR tests narrow the regime to a range hypothesis. Waiting for the completed candle to return inside separates a rejected excursion from a continuing outside-band move. A new trend can still walk down the lower band and stop consecutive long reversals.
Setup
- Use completed H1 bars and the broker's displayed bid chart; calculate every value using the just-closed bar and earlier bars only.
- A range is eligible when absolute SMA(50)[1]-SMA(50)[11] is no more than 0.25 ATR(14)[1], and the current ATR is below 1.5 times its 100-bar median.
- Allow one position per symbol. Do not add to a losing position.
Indicators
- Bollinger Bands: 20-period SMA, 2.0 population-standard-deviation bands, Close
- SMA(50), Close
- ATR(14)
Long entry
- At a bar close, mark a long setup if Low[1] is below LowerBand[1], Close[1] is back above LowerBand[1], and Close[1] is above Open[1].
- Submit a market buy at the next bar's first tradable ask; cancel if that quote is more than 0.10 ATR above Close[1].
Short entry
- At a bar close, mark a short setup if High[1] is above UpperBand[1], Close[1] is back below UpperBand[1], and Close[1] is below Open[1].
- Submit a market sell at the next bar's first tradable bid; cancel if that quote is more than 0.10 ATR below Close[1].
Stop loss
- Long SL = Low[1] − 1.25×ATR14[1]; short SL = High[1] + 1.25×ATR14[1]. If either violates the broker’s minimum distance, cancel the setup rather than silently changing its rule. Size from the actual executable entry.
Exit
- At entry place the target at signal-time SMA20. After each later completed H1 bar, update the target to the new SMA20 only if it remains beyond the current executable price in the profit direction; otherwise close at that next quote. Count a long target only when bid reaches it, and a short target only when ask reaches it. Skip an entry whose first target is already on the loss side.
- If the middle band has not been touched after 12 completed H1 bars, exit at the next bar open.
- For a long, if a completed H1 bar closes below LowerBand[1], send a market sell at the next executable bid; for a short, if a completed bar closes above UpperBand[1], buy to cover at the next executable ask. This is adverse-breakout invalidation, not an opposite-band target.
Risk and position size
- Risk 0.50% of equity, including a transaction-cost reserve. Lots = available risk cash / ((abs(entry − SL) / tick size) × loss tick value per one lot + estimated commission per lot). Verify account-currency conversion and round down to the broker volume step.
- Cap aggregate open risk at 1.0% and skip a trade if margin is insufficient.
Costs and execution
- Backtests must use variable bid/ask spread, commission, and at least one tick of adverse entry/exit slippage. Use New York 17:00 daily rollover; overnight positions accrue the broker's long/short swap.
When the method can fail
- Skip the 30 minutes before through 30 minutes after scheduled policy decisions, CPI, payrolls, or GDP for either currency.
- Avoid visibly directional conditions; a flat average filter can still fail when a trend begins.
Worked example
- Hypothetical: lower band 1.0980, signal low 1.0975, bullish close 1.0985 and ATR 0.0010. Entry 1.0986 gives SL 1.09625; SMA20 at 1.1010 is a 24-pip target against 23.5 pips of price risk. The example passes only if the separate flatness and volatility tests also pass.
Historical test results
No tested pair meets the complete research-screen criterion. Positive cells alone do not qualify the strategy.
18 mechanical runs across 3 pairs on H1. Decisions use completed strategy bars; fills use native ICMarketsEU-Demo M15 Bid candles with explicitly modelled costs. Full window: 1 January 2025–18 September 2026. Each row starts with an independent USD10,000 account.
| Pair | Period | Costs | Trades | Net return | Profit factor | Max drawdown | Ambiguous bars |
|---|---|---|---|---|---|---|---|
| EURUSD | combined | base | 111 | -2.02% | 0.8545 | 3.55% | 0 |
| EURUSD | combined | stress | 74 | -2.86% | 0.7286 | 4.30% | 0 |
| GBPUSD | combined | base | 138 | +0.18% | 1.0106 | 3.35% | 0 |
| GBPUSD | combined | stress | 82 | -2.82% | 0.7678 | 4.14% | 0 |
| USDJPY | combined | base | 117 | -4.56% | 0.7102 | 6.04% | 0 |
| USDJPY | combined | stress | 80 | -6.59% | 0.4933 | 7.52% | 0 |
Show 2025 and 2026 separately
| Pair | Period | Costs | Trades | Net return | Profit factor | Max drawdown | Ambiguous bars |
|---|---|---|---|---|---|---|---|
| EURUSD | 2025 | base | 72 | +0.18% | 1.0228 | 1.89% | 0 |
| EURUSD | 2025 | stress | 43 | +0.10% | 1.0196 | 1.82% | 0 |
| EURUSD | 2026 | base | 39 | -2.21% | 0.6355 | 3.53% | 0 |
| EURUSD | 2026 | stress | 31 | -2.96% | 0.4721 | 4.05% | 0 |
| GBPUSD | 2025 | base | 81 | +1.28% | 1.1371 | 3.35% | 0 |
| GBPUSD | 2025 | stress | 46 | -2.25% | 0.7025 | 3.30% | 0 |
| GBPUSD | 2026 | base | 57 | -1.00% | 0.8602 | 3.17% | 0 |
| GBPUSD | 2026 | stress | 36 | -0.62% | 0.8696 | 1.99% | 0 |
| USDJPY | 2025 | base | 65 | -3.49% | 0.6167 | 4.39% | 0 |
| USDJPY | 2025 | stress | 42 | -4.23% | 0.4306 | 4.31% | 0 |
| USDJPY | 2026 | base | 52 | -1.15% | 0.8337 | 3.08% | 0 |
| USDJPY | 2026 | stress | 38 | -2.39% | 0.5861 | 4.24% | 0 |
Costs, execution and qualification criteria
Base: Spread 1.0 pip for majors; 1.5 EURGBP/EURJPY; 2.0 GBPJPY/AUDNZD. USD7/100k round-trip commission; 0.1 pip adverse market/stop slippage per fill. Financing=max(negative current native swap,0.2pip/night), no positive credit, native triple-swap day.
Stress: Double base spread; 0.3 pip adverse slippage/fill; same commission; double max(negative current native swap,0.5pip/night).
Research candidate only if a pair has >=30 trades in EACH calendar subperiod, positive net returns and PF >=1.10 in EACH subperiod under BOTH cost scenarios, and combined maximum drawdown <=15% under BOTH scenarios. Not a statistical profitability proof. All pairs and failures are retained.
Profit factor is the sum of positive net trade results divided by the absolute sum of negative results. Drawdown includes adverse M15 intrabar marks. The end of each test window liquidates open positions, so separate subperiod returns do not add exactly to the continuous-window return.
- Bar execution, not a real-tick MT5 Strategy Tester run. Same-bar ambiguity is treated adversely and counted.
- Current swap snapshot is an explicit stress assumption, not historical funding.
- One isolated USD10,000 account per strategy/pair, leverage ceiling30, broker minimum lots and steps. Results cannot be added into one portfolio.
- 2026 is a later evaluation slice, not untouched independent out-of-sample evidence; no parameter optimization was performed.
- Retrospective scheduled MT5 calendar may contain revised release times. UTC export normalized to NY-close broker clock against BLS releases.
- General discretionary event avoidance is fixed as high-impact events for either currency +/-30min. IDs1/17 next60min; ID20 next120min. ID13 UK bank holidays excluded. Subjective trend quality, unscheduled events and all-country holiday/session quality are not fully quantifiable; these are documented mechanical variants.
- Sparse broker histories are reported with shorter effective coverage and are ineligible for a candidate label.
- Native indicator parity: ATR, SMA, RSI, MACD, bands, stochastic, WPR, CCI and Ichimoku matched native buffers on EURUSD H4 within rounding tolerance; Wilder ADX matched the MetaQuotes ADXW example. EMA200 seed residual at 1,000 bars was 0.000000715, falling below 0.0000000001 after 2,000 bars.
- Built-in iSAR differs from the published MetaQuotes example on reversal bars. ID9 therefore uses actual built-in iSAR buffers exported by MT5, joined by timestamp, not the approximate Python SAR. Native GBPUSD/USDJPY SAR history needs 300 warm-up bars from January 2025, so those rows start later and cannot pass the full-period screen.
- 37 automated checks passed: execution gaps, short ask prices, ambiguous stop/target candles, partial commissions, pending expiry, time zones, rule regression cases and monthly portfolio no-lookahead/cash costs.
Interpretation: these are mechanical bar-model tests, not verified real-tick or live performance. Price rules were held fixed; subjective market-quality exclusions remain outside the mechanical model. Strategy adaptation requires a new test.
Download all test metrics and assumptions (JSON) · Download simulated trade logs and reproducible research code · Broker commission and swap documentation
Execution conventions
- Bar [0] is forming; [1] is the most recently completed bar. Unless explicitly stated otherwise, indicators use Close with zero plot shift and signals use completed bars. EMA is exponential, SMA is arithmetic and MT5 ATR is its native true-range average. Use at least 300 completed warm-up bars; a longer rule-specific requirement takes priority.
- A close-based signal is executed at the first available quote after the close, never retrospectively at the signal close. Buy at ask, sell at bid; close longs at bid and shorts at ask. A standing stop or target can fill within a bar. A gap through a stop fills at the first executable price, which can be worse than the stop.
- R means the initial entry-to-protective-stop distance, fixed at entry. Convert that distance into account-currency loss using the symbol tick size and loss-side tick value. Lots = cash risk / loss per lot, rounded down to the broker volume step. Round prices to the trade tick and recheck risk plus minimum stop/freeze distances before submitting. Budget commission and slippage separately; skip if minimum size exceeds the risk limit.
- Use one position per symbol and no averaging down. A trailing stop only tightens after a completed bar and becomes active on the next quote. The entry bar is holding bar one; a time exit executes on the quote after the specified holding bar closes. When a hard stop and a close-based exit compete, the stop already active takes precedence. With OHLC-only data, assume stop before target if both can occur in one bar; tick data is needed to resolve the order.
- The article defines the price rule. Any discretionary news exclusion changes the tested variant and must be recorded in advance. Map broker timestamps to the named London/New York time zone using historical daylight-saving offsets; do not assume a fixed UTC offset. Include spread, commission, slippage, overnight financing and triple-swap days in a profitability test.
Adapt and test your version
- Treat these inputs as a reproducible starting specification. Choose a currency pair, session and holding period that match the time you can monitor the market, then record any changes to indicator periods, thresholds, stop distance or exits as a new version.
- Change one hypothesis at a time. Reserve a later period and additional pairs for evaluation before looking at their results. Include your account’s actual trading and financing costs, compare small parameter changes, and forward-test on demo. A selected profitable window does not validate the strategy or its modified version.
Reproduce the chart in MT5
- Open EURUSD on H1. Add the indicators listed above through Insert → Indicators; use Close and zero shift unless a different setting is specified. The Data Window displays exact values for the selected completed candle.
- Compare the signal candle with the required earlier bars before moving forward. Use the crosshair to read prices and times. For custom channels, session levels or Supertrend, reproduce the formula in this guide and check the calculation before relying on an external indicator.
- Draw entry, initial SL and target only after a candle has satisfied every condition. Label planned levels as plans; they do not demonstrate a historical fill. The featured chart is genuine historical MT5 context and is not a trade-performance report.
Sources
- A complete explanation of Bollinger Bands — Band construction, classic parameters, and relative-price interpretation.
- Bollinger Bands — MT5 indicator availability and inputs.
MT5 Expert Advisor and test status — version 1.01
Bollinger-Band Range Mean Reversion: TF_Strategy_16.ex5, H1. This single-symbol implementation uses the core entry and exit rules above with the execution conditions below. The ZIP includes the compiled EA, complete local source headers, input documentation, tester defaults and the historical calendar.
Download Strategy 16 EA v1.01 (ZIP) · Read the versioned test data
How this EA executes
Signals use completed H1 bars. Execution waits for an open MT5 trading session and uses the available bid/ask quote. The common entry spread ceiling is 3.0 pips, with any additional strategy-specific spread checks retained. A new position is blocked when another position already exists on the same symbol. The full input table and timing exceptions are included in the ZIP.
The historical calendar blocks entries outside its declared coverage. Within coverage, a missing individual event cannot be detected. Relevant high-impact events block entries 30 minutes before through 30 minutes after.
The default clock follows the New York-close broker schedule (UTC+2 in US winter, UTC+3 in US summer). Set UTC or a fixed offset for a different feed. The fallback Sunday hour is ambiguous; the source audit found no observed M1 records in that hour for the seven majors across the ten checked years. This is not a universal broker-clock guarantee.
Article constraint requiring manual account-level control: Cap aggregate open risk at 1.0% and skip a trade if margin is insufficient. This EA version does not aggregate risk or correlation across symbols. Running several copies does not enforce that limit.
The round-trip commission reserve defaults to 7.0 units of the account currency per lot. This is a sizing input, not a broker fee; the reported sizing tests used USD. Set it explicitly for the deposit currency and cost scenario.
What has actually been tested
Functional validation; long-term profitability is not established. Research case id16-eurusd-202402-release101 used EURUSD real bid/ask ticks from 2024-02-01 to 2024-03-01 (end exclusive), starting at USD 10,000. Earlier history supplied warmup only; declared warmup gaps limit the interpretation.
| Positions / partial exits / tester-end closes | 7 / 0 / 0 |
|---|---|
| Price P/L | USD -10.08 |
| Native booked swap (not verified historical funding) | USD 0.39 |
| Additional modeled commission | USD 12.25 |
| Net cash result | USD -21.94 |
The pilot was negative: price P/L plus native booked swap, less USD 3.50 per lot per side of modeled commission, produced the net result above. Observed bid/ask spread is included; no extra execution delay was added. The sample does not establish a persistent edge or prove why returns would recur. Historical swap rates, slippage and complete independent signal/indicator replay remain unvalidated. Tester-end closes, where listed, are not strategy exit signals.
The exact downloadable production EX5 also completed a separate native test (2024-02-01 to 2024-03-01, end exclusive): 7 positions, 0 partial exits and 0 tester-end closes. Its native ledger was reconciled. This run had no extra research commission, so its cash result is not the after-cost benchmark above.
Install and reproduce
- Copy the ZIP’s MQL5/Experts/TradeForex/TF_16/ directory into the terminal data folder, and TF-calendar.csv into MQL5/Files/.
- Choose this EA in Strategy Tester on H1, load the included preset through Inputs → Load, and use every tick based on real ticks with the documented symbol clock and calendar coverage.
- Review costs, session metadata and per-order risk for the intended instrument. The research cost overlay is described in TEST-STATUS.json; a normal MT5 report does not automatically reproduce it.
Account trading defaults to disabled; real accounts are rejected by this build. The validations above used Strategy Tester only. Article-level portfolio limits are not automatically enforced across symbols.
Multi-year EURUSD benchmark — EA 16 v1.01
Bollinger-Band Range Mean Reversion · H1. All 20 planned base/stress cases completed and reconciled. The research binary uses the version 1.01 strategy with the documented tester cost overlay.
EURUSD only, using genuine historical bid/ask ticks in MT5’s real-tick mode. Ten independently started segments span selected dates from 2 July 2018 to 18 September 2026 (end exclusive). Excluded broker-calendar dates and short residual windows are listed in the downloadable benchmark data. Broker time is UTC+2 in US winter and UTC+3 in US summer; source ticks are UTC. Earlier history supplies warmup only, with at least 400 observed completed bars required at the first decision; warmup gaps remain a limitation. The full ten-year data archive is not a ten-year continuous performance test.
Each segment starts flat at USD 10,000. Base uses USD 3.50 per lot per side and no added execution delay. Stress uses USD 7.00 per lot per side plus a 200 ms delay. Observed spread is included in price P/L. Stress changes both commission and delay, so its difference from base does not isolate either effect. Remaining positions are closed and charged at each segment end.
Results below sum independent segment cash outcomes; they are not a compounded account return. Drawdown is the worst observed individual segment, not a continuous full-period or intratick worst-case drawdown. It uses observed native equity after modeled fees and native booked swap. Profit factor groups complete positions, including partial exits; n/a means the loss denominator is unavailable. Native booked swap is shown separately and has not been checked against historical financing rates. Native equity can affect subsequent sizing, so subtracting swap does not recreate a separate no-financing simulation.
The rules were fixed before this campaign, but parts of the historical period had already been inspected during development. This is not an untouched out-of-sample test, and no automatic profitability badge is awarded. Ledger reconciliation is not a complete independent replay of every indicator and decision. These figures describe this exact implementation and sample; they do not establish why an apparent edge would persist. Account-level and portfolio controls described elsewhere on this page still apply.
| Measure | Base | Stress |
|---|---|---|
| Positions | 566 | 565 |
| Price P/L (USD) | -314.98 | -316.13 |
| Modeled commission (USD) | 738.29 | 1,467.76 |
| Net before financing (USD) | -1,053.27 | -1,783.89 |
| Native booked swap — unverified (USD) | -104.99 | -104.87 |
| Net including native swap (USD) | -1,158.26 | -1,888.76 |
| Position profit factor before financing | 0.843 | 0.745 |
| Positive segments before financing (out of 10) | 4 | 3 |
| Worst observed individual segment drawdown (USD) | 530.41 | 614.55 |
| Worst observed individual segment drawdown (%) | 5.29 | 6.13 |
| Forced tester-end closes | 1 | 1 |
| Reviewed server rejections retained | 0 | 1 |
Base: Summed price P/L was non-positive; modeled commission reduced the result further. The sample lost money before financing.
Stress: Summed price P/L was non-positive; modeled commission reduced the result further. The sample lost money before financing.
Execution limitation: Reviewed server rejections remain included in these results. Their native outcomes were retained; this is not evidence of error-free execution. p101-id16-eurusd-20230101-20231222-stress: An entry was rejected for invalid stops; no hypothetical fill is used. Event time(s): 2023.11.10 17:00:00.
The sizing commission reserve remains USD 7 per round-trip lot in both scenarios; the stress scenario actually charges USD 14. Its larger fee is not offset by changing that frozen sizing input.
Download the benchmark figures, exact segment dates and evidence hashes.
