Skip to content
SMARTFINANCEDATA
Home Markets Insights Blog Tools Contact
Sign In Get Access
Home Markets Insights Tools Blog Contact Pricing
Sign In Get Access
Scalping Strategy Tutorial

5-Minute Range Filter Trading Strategy

Master a powerful intraday strategy that filters market noise and identifies high-probability trading opportunities using range-based price action.

5-Minute Timeframe

Fast-paced scalping opportunities

Noise Filtration

Eliminate false breakouts

High Win Rate

Proven price action signals

Strategy Components

Range Filter
Price Action
Volume Confirmation
Start Learning
20 min read
Intermediate Level
8,750+ learners

Understanding the 5-Minute Range Filter Strategy

The 5-Minute Range Filter Trading Strategy is a powerful scalping approach designed for intraday traders who want to capitalize on short-term price movements while avoiding the noise and false signals common in lower timeframes. This strategy combines a dynamic range filter with price action confirmation to identify high-probability trades during active market sessions.

What Is a Range Filter?

A range filter is a technical indicator that smooths price data by calculating a moving average that only updates when price moves beyond a specified range threshold. Unlike traditional moving averages that respond to every price tick, the range filter ignores minor fluctuations, making it ideal for filtering out market noise in choppy conditions.

Range Filter Calculation:

1. Calculate the Range Size:

Range = ATR(Period) × Multiplier

2. Update the Filter Line:

  • If price moves above (Filter + Range), update Filter upward
  • If price moves below (Filter - Range), update Filter downward
  • Otherwise, maintain the current Filter value

Strategy Components

1. Timeframe: 5-Minute Charts

The 5-minute timeframe strikes an optimal balance between trade frequency and signal reliability. It's fast enough for intraday scalping but slow enough to filter out the excessive noise found in 1-minute charts. This timeframe is ideal during high-liquidity sessions (London and New York overlaps).

2. Range Filter Indicator

The core indicator uses ATR (Average True Range) with a 14-period setting and a 2.0 multiplier. When price closes above the filter line, it signals upward momentum; when price closes below, it signals downward momentum. The filter line acts as dynamic support and resistance.

Settings: ATR Period = 14, Range Multiplier = 2.0 (can be adjusted between 1.5-3.0 based on volatility preference)

3. Price Action Confirmation

Beyond the range filter signal, confirm entries with candlestick patterns. Look for bullish engulfing patterns or hammer candles for long entries, and bearish engulfing or shooting star patterns for short entries. This adds an extra layer of confirmation to filter trades.

4. Volume Analysis (Optional)

Incorporate volume indicators to validate breakouts. Higher-than-average volume on filter crossovers suggests genuine momentum, while low-volume signals may indicate false breakouts. Use a volume moving average to identify significant volume spikes.

Trading Rules

Long (Buy) Entry Criteria

  1. Price closes above the range filter line
  2. Filter line changes from red to green (uptrend confirmation)
  3. Bullish candlestick pattern forms (engulfing, hammer, or piercing)
  4. Optional: Volume exceeds 20-period moving average
  5. Enter at the open of the next candle

Stop Loss: Place below the recent swing low or 1.5× ATR below entry

Take Profit: Target 2:1 or 3:1 risk-reward ratio, or exit when price closes back below the filter line

Short (Sell) Entry Criteria

  1. Price closes below the range filter line
  2. Filter line changes from green to red (downtrend confirmation)
  3. Bearish candlestick pattern forms (engulfing, shooting star, or dark cloud)
  4. Optional: Volume exceeds 20-period moving average
  5. Enter at the open of the next candle

Stop Loss: Place above the recent swing high or 1.5× ATR above entry

Take Profit: Target 2:1 or 3:1 risk-reward ratio, or exit when price closes back above the filter line

MQL5 Implementation

Here's a complete MQL5 Expert Advisor implementing the 5-Minute Range Filter Strategy:

MQL5 Expert Advisor: RangeFilterScalper.mq5
//+------------------------------------------------------------------+
//|                                          RangeFilterScalper.mq5  |
//|                        5-Minute Range Filter Trading Strategy    |
//+------------------------------------------------------------------+
#property copyright "SmartFinanceData"
#property version   "1.00"
#property strict

// Input Parameters
input int      ATR_Period = 14;              // ATR Period for Range Filter
input double   Range_Multiplier = 2.0;       // Range Multiplier
input double   RiskPercent = 1.0;            // Risk per trade (%)
input double   RR_Ratio = 2.0;               // Risk-Reward Ratio
input int      Volume_MA_Period = 20;        // Volume MA Period
input bool     Use_Volume_Filter = true;     // Use Volume Confirmation

// Global Variables
int atrHandle;
int volumeHandle;
double filterLine[];
double rangeSize[];
bool isUpTrend = false;
datetime lastBarTime = 0;

//+------------------------------------------------------------------+
//| Expert initialization function                                     |
//+------------------------------------------------------------------+
int OnInit()
{
   // Initialize ATR indicator
   atrHandle = iATR(_Symbol, PERIOD_M5, ATR_Period);
   if(atrHandle == INVALID_HANDLE)
   {
      Print("Failed to create ATR indicator");
      return(INIT_FAILED);
   }
   
   // Initialize arrays
   ArraySetAsSeries(filterLine, true);
   ArraySetAsSeries(rangeSize, true);
   
   Print("Range Filter Scalper EA initialized successfully");
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                   |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   IndicatorRelease(atrHandle);
}

//+------------------------------------------------------------------+
//| Expert tick function                                               |
//+------------------------------------------------------------------+
void OnTick()
{
   // Check for new bar
   if(lastBarTime == iTime(_Symbol, PERIOD_M5, 0))
      return;
   
   lastBarTime = iTime(_Symbol, PERIOD_M5, 0);
   
   // Calculate Range Filter
   CalculateRangeFilter();
   
   // Check for existing positions
   if(PositionsTotal() > 0)
   {
      ManageOpenPositions();
      return;
   }
   
   // Look for entry signals
   CheckForEntrySignals();
}

//+------------------------------------------------------------------+
//| Calculate Range Filter                                             |
//+------------------------------------------------------------------+
void CalculateRangeFilter()
{
   double atr[];
   ArraySetAsSeries(atr, true);
   
   if(CopyBuffer(atrHandle, 0, 0, 3, atr) <= 0)
      return;
   
   double range = atr[1] * Range_Multiplier;
   double close1 = iClose(_Symbol, PERIOD_M5, 1);
   double close2 = iClose(_Symbol, PERIOD_M5, 2);
   
   // Initialize filter on first run
   static double prevFilter = 0;
   if(prevFilter == 0)
      prevFilter = close2;
   
   double newFilter = prevFilter;
   
   // Update filter based on price movement
   if(close1 > prevFilter + range)
   {
      newFilter = prevFilter + range;
      isUpTrend = true;
   }
   else if(close1 < prevFilter - range)
   {
      newFilter = prevFilter - range;
      isUpTrend = false;
   }
   
   ArrayResize(filterLine, ArraySize(filterLine) + 1);
   ArrayResize(rangeSize, ArraySize(rangeSize) + 1);
   filterLine[0] = newFilter;
   rangeSize[0] = range;
   
   prevFilter = newFilter;
}

//+------------------------------------------------------------------+
//| Check for entry signals                                            |
//+------------------------------------------------------------------+
void CheckForEntrySignals()
{
   if(ArraySize(filterLine) < 3)
      return;
   
   double close1 = iClose(_Symbol, PERIOD_M5, 1);
   double close2 = iClose(_Symbol, PERIOD_M5, 2);
   double open1 = iOpen(_Symbol, PERIOD_M5, 1);
   double high1 = iHigh(_Symbol, PERIOD_M5, 1);
   double low1 = iLow(_Symbol, PERIOD_M5, 1);
   
   // Volume filter (optional)
   bool volumeConfirm = true;
   if(Use_Volume_Filter)
   {
      long volume1 = iVolume(_Symbol, PERIOD_M5, 1);
      double avgVolume = 0;
      for(int i = 1; i <= Volume_MA_Period; i++)
         avgVolume += iVolume(_Symbol, PERIOD_M5, i);
      avgVolume /= Volume_MA_Period;
      
      volumeConfirm = (volume1 > avgVolume);
   }
   
   // Long Entry Signal
   if(close1 > filterLine[1] && close2 <= filterLine[2] && volumeConfirm)
   {
      // Bullish candlestick patterns
      bool bullishEngulfing = (close1 > open1 && open1 < close2 && close1 > open1);
      bool hammer = ((high1 - close1) < (close1 - open1) * 0.3 && 
                     (close1 - low1) > (high1 - low1) * 0.6);
      
      if(bullishEngulfing || hammer)
      {
         double sl = low1;
         double entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
         double tp = entryPrice + (entryPrice - sl) * RR_Ratio;
         
         OpenPosition(ORDER_TYPE_BUY, entryPrice, sl, tp);
      }
   }
   
   // Short Entry Signal
   if(close1 < filterLine[1] && close2 >= filterLine[2] && volumeConfirm)
   {
      // Bearish candlestick patterns
      bool bearishEngulfing = (close1 < open1 && open1 > close2 && close1 < open1);
      bool shootingStar = ((close1 - low1) < (open1 - close1) * 0.3 && 
                          (high1 - close1) > (high1 - low1) * 0.6);
      
      if(bearishEngulfing || shootingStar)
      {
         double sl = high1;
         double entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
         double tp = entryPrice - (sl - entryPrice) * RR_Ratio;
         
         OpenPosition(ORDER_TYPE_SELL, entryPrice, sl, tp);
      }
   }
}

//+------------------------------------------------------------------+
//| Open a position                                                    |
//+------------------------------------------------------------------+
void OpenPosition(ENUM_ORDER_TYPE orderType, double entry, double sl, double tp)
{
   double lotSize = CalculateLotSize(entry, sl);
   
   MqlTradeRequest request = {};
   MqlTradeResult result = {};
   
   request.action = TRADE_ACTION_DEAL;
   request.symbol = _Symbol;
   request.volume = lotSize;
   request.type = orderType;
   request.price = entry;
   request.sl = sl;
   request.tp = tp;
   request.deviation = 10;
   request.magic = 123456;
   request.comment = "Range Filter";
   
   if(!OrderSend(request, result))
      Print("OrderSend failed: ", GetLastError());
   else
      Print("Position opened: ", (orderType == ORDER_TYPE_BUY ? "BUY" : "SELL"), 
            " at ", entry, " SL: ", sl, " TP: ", tp);
}

//+------------------------------------------------------------------+
//| Calculate lot size based on risk                                   |
//+------------------------------------------------------------------+
double CalculateLotSize(double entry, double sl)
{
   double risk = AccountInfoDouble(ACCOUNT_BALANCE) * RiskPercent / 100.0;
   double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   double slDistance = MathAbs(entry - sl);
   
   double lots = risk / (slDistance / tickSize * tickValue);
   
   // Normalize lot size
   double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   
   lots = MathFloor(lots / lotStep) * lotStep;
   lots = MathMax(minLot, MathMin(maxLot, lots));
   
   return lots;
}

//+------------------------------------------------------------------+
//| Manage open positions                                              |
//+------------------------------------------------------------------+
void ManageOpenPositions()
{
   if(ArraySize(filterLine) < 1)
      return;
   
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL) != _Symbol)
            continue;
         
         double close1 = iClose(_Symbol, PERIOD_M5, 1);
         ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
         
         // Exit if price crosses back through filter line
         if(posType == POSITION_TYPE_BUY && close1 < filterLine[0])
            ClosePosition(ticket);
         else if(posType == POSITION_TYPE_SELL && close1 > filterLine[0])
            ClosePosition(ticket);
      }
   }
}

//+------------------------------------------------------------------+
//| Close a position                                                   |
//+------------------------------------------------------------------+
void ClosePosition(ulong ticket)
{
   MqlTradeRequest request = {};
   MqlTradeResult result = {};
   
   request.action = TRADE_ACTION_DEAL;
   request.position = ticket;
   request.symbol = _Symbol;
   request.volume = PositionGetDouble(POSITION_VOLUME);
   request.type = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? 
                  ORDER_TYPE_SELL : ORDER_TYPE_BUY;
   request.price = (request.type == ORDER_TYPE_SELL) ? 
                   SymbolInfoDouble(_Symbol, SYMBOL_BID) : 
                   SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   request.deviation = 10;
   
   if(!OrderSend(request, result))
      Print("Close position failed: ", GetLastError());
   else
      Print("Position closed: Ticket ", ticket);
}

Best Practices and Risk Management

1. Optimal Trading Sessions

Trade during high-liquidity sessions for best results. The London-New York overlap (8:00 AM - 12:00 PM EST) provides the most reliable signals. Avoid trading during low-volume Asian sessions or major news releases.

2. Risk Management Rules

Never risk more than 1-2% of account balance per trade. Use a minimum 2:1 risk-reward ratio. Limit daily drawdown to 3-5% maximum. If you hit three consecutive losses, stop trading for the day and review your executions.

3. Currency Pair Selection

This strategy works best on major pairs with tight spreads: EUR/USD, GBP/USD, USD/JPY, and AUD/USD. Avoid exotic pairs with wide spreads that can erode profits on short-term scalps.

Tip: EUR/USD typically offers the best balance of volatility and liquidity for this strategy, with average spreads under 1 pip during peak hours.

4. Parameter Optimization

Test different range multipliers (1.5-3.0) to match current market volatility. In trending markets, use lower multipliers (1.5-2.0) for more signals. In choppy markets, increase to 2.5-3.0 to reduce false signals.

5. Backtesting Requirements

Backtest on at least 6-12 months of historical data before live trading. Use 99% modeling quality tick data for accurate results. Forward test on a demo account for 2-4 weeks to validate performance in current market conditions.

Common Mistakes to Avoid

Mistake Why It Fails Solution
Trading against the trend Leads to repeated stop-outs Only trade in direction of filter line
Ignoring volume confirmation Catches false breakouts Require above-average volume on signals
Over-leveraging positions Small losses wipe out accounts Stick to 1-2% risk per trade maximum
Trading during news events Causes unpredictable volatility spikes Avoid trading 15 min before/after major news
Moving stop-loss to breakeven too early Gets stopped out by normal noise Wait for 1:1 R:R before adjusting stops

Performance Expectations

When properly implemented, the 5-Minute Range Filter Strategy typically achieves:

Win Rate

55-65%

With proper filtering and confirmation

Risk:Reward

1:2 to 1:3

Minimum 2:1 ratio recommended

Trades Per Day

3-8 signals

During active trading sessions

Average Trade Duration

15-45 min

Typical scalp holding period

Key Takeaways

  • The range filter eliminates noise by only updating when price moves beyond ATR-based thresholds
  • Combine filter signals with candlestick patterns and volume for higher-probability entries
  • Trade only during high-liquidity sessions (London-NY overlap) for best results
  • Maintain strict risk management: 1-2% per trade, minimum 2:1 R:R ratio
  • Adjust range multiplier based on market conditions (1.5-3.0) to optimize signal quality

"Success in scalping comes from filtering noise and executing only the highest-probability setups with disciplined risk management."

SmartFinanceData

Probabilistic market analytics across Forex, Indices, Commodities & Crypto — powered by 50+ datasets and millions of data points.

Product
Insights Markets Pricing Team Login
Resources
Methodology Disclaimer Terms Of Service Privacy Policy FAQ Contact

© 2026 SmartFinanceData. All data is historical and does not guarantee future performance.