MQL5 ATR Volatility Filter: How to Improve EA Entry Quality

目次

1. What Is an MQL5 ATR Volatility Filter?

Conclusion: An ATR volatility filter is control logic that allows trades only when price movement is large enough. It is used to reduce unnecessary entries and make expected performance more stable.

1.1 Definition of ATR (Average True Range)

Conclusion: ATR is an indicator that measures price volatility. It does not show trend direction; it only measures the size of price movement.

Definition:
ATR (Average True Range) is an indicator that averages the price range over a set period, including the high-low range and gaps.

In practical terms, ATR has these characteristics.

  • Higher value: the market is moving more strongly (high volatility)
  • Lower value: the market is moving less (low volatility)
  • It does not show whether the market is rising or falling; a separate indicator is needed for direction

A common beginner mistake is assuming that “ATR is rising” means “the market is in an uptrend.” That is incorrect. ATR only shows the size of price movement.

ATR is also important in situations such as these.

  • Identifying low-volatility conditions where spread costs can easily consume profit
  • Detecting high-volatility conditions where slippage is more likely
  • Indirectly judging execution conditions, such as how easily orders may be filled

In short, ATR is used as a standard for deciding whether the market is suitable for trading.


1.2 What Is a Volatility Filter?

Conclusion: A volatility filter is a mechanism that uses indicators such as ATR to select only the market conditions where an entry should be allowed.

The basic idea behind a volatility filter is very simple.

  • ATR is at or above a set level: trade because there is enough movement
  • ATR is below a set level: do not trade because movement is too small

By switching trading permission based on market conditions, the filter reduces unnecessary orders.

Examples:

  • Scalping
    Avoid low-volatility conditions because spread costs can easily exceed the available profit margin.
  • Breakout strategies
    Include ATR as a condition because breakouts tend to work better in high-volatility environments.
  • Trend following
    Use ATR as a filter because trends are more likely to extend when volatility is present.

A common failure is entering trades all the time without using a filter. This can create the following problems.

  • More false signals in ranging markets
  • More unnecessary entries, which increases commissions and spread costs
  • Lower PF (profit factor)

For this reason, an ATR filter should be treated as a prerequisite for improving trade quality.


1.3 Why It Matters in MQL5

Conclusion: In MQL5, an ATR filter is an important component that can strongly affect the stability and reproducibility of an EA.

Automated trading systems, or EAs, always face these issues.

  • Market conditions constantly change
  • Execution conditions, fills, and slippage are not constant
  • Spreads vary by time of day and currency pair

An ATR filter works as a way to judge market conditions quantitatively.

Practical benefits:

  • Fewer unnecessary entries, which optimizes trade frequency
  • Lower drawdown (DD)
  • Better strategy reproducibility across different market environments

The most important point is its effect on expectancy.

Without an ATR filter:

  • The win rate may rise, but profits may not extend
  • The system may get worn down by many small gains and losses

With an ATR filter:

  • The number of trades decreases
  • Profit per trade tends to become larger

As a result, PF and risk-reward can improve over the long term.

One important caution is that an ATR filter alone does not create a complete strategy.

  • Trend judgment, such as MA or RSI
  • Cost control, such as a spread filter
  • Time control, such as a session filter

An EA reaches a practical operating level only when these elements are combined.

2. How to Implement an ATR Volatility Filter

Conclusion: In MQL5, an ATR filter can be implemented in three steps: get the indicator handle with iATR, get the value with CopyBuffer, and control entries with conditional logic.


2.1 Basic Syntax of the iATR Function

Conclusion: iATR is a function that gets the handle, or identifier, of the ATR indicator. The actual ATR value is retrieved later.

In MQL5, indicators are designed to be accessed through handles instead of returning values directly.

Basic syntax:

int iATR(
   string           symbol,     // currency pair
   ENUM_TIMEFRAMES  timeframe,  // timeframe
   int              period      // period
);

Example:

int atrHandle;

int OnInit()
{
   atrHandle = iATR(_Symbol, PERIOD_CURRENT, 14);

   if(atrHandle == INVALID_HANDLE)
   {
      Print("Failed to get ATR handle");
      return(INIT_FAILED);
   }

   return(INIT_SUCCEEDED);
}

Key points:

  • _Symbol: the current currency pair
  • PERIOD_CURRENT: the current timeframe
  • 14: a common default period

Common mistakes:

  • Not checking whether handle creation failed
  • Creating the handle on every tick in OnTick instead of once in OnInit, which is inefficient and wastes memory

2.2 How to Get Values with CopyBuffer

Conclusion: The actual ATR value is obtained with the CopyBuffer function and handled as an array.

In MQL5, indicator values are retrieved as buffers, which are arrays.

Basic syntax:

int CopyBuffer(
   int       indicator_handle,
   int       buffer_num,
   int       start_pos,
   int       count,
   double    buffer[]
);

Implementation example:

double atrBuffer[];

void GetATRValue()
{
   ArraySetAsSeries(atrBuffer, true);

   if(CopyBuffer(atrHandle, 0, 0, 1, atrBuffer) <= 0)
   {
      Print("Failed to get ATR");
      return;
   }
}

Important points:

  • buffer_num = 0: ATR has only one buffer
  • start_pos = 0: the latest bar
  • count = 1: get only one bar
  • ArraySetAsSeries(true): reverse the time series so the latest value is [0]

Common mistakes:

  • Not setting ArraySetAsSeries, which reverses the intended index order
  • Not checking the return value of CopyBuffer, which can lead to invalid data being used

2.3 Example Filter Conditions

Conclusion: You can build a simple filter by comparing the ATR value with a threshold.

Common patterns:

High-volatility entries only

double threshold = 0.0010;

if(atrBuffer[0] > threshold)
{
   // Allow entry
}

Avoid low volatility

if(atrBuffer[0] < threshold)
{
   // Prohibit entry
}

Practical considerations:

  • Values differ by currency pair, such as USDJPY and EURUSD
  • ATR values change significantly by timeframe

Examples:

  • M1: smaller values
  • H1: larger values

Common mistakes:

  • Reusing one fixed threshold everywhere
  • Not optimizing by currency pair
  • Misreading the number of decimal places

2.4 Practical Code Example (Simple)

Conclusion: An ATR filter is usually added inside OnTick in the flow: check the condition, then decide before OrderSend.

Minimum structure:

int atrHandle;
double atrBuffer[];

int OnInit()
{
   atrHandle = iATR(_Symbol, PERIOD_CURRENT, 14);
   return(INIT_SUCCEEDED);
}

void OnTick()
{
   ArraySetAsSeries(atrBuffer, true);

   if(CopyBuffer(atrHandle, 0, 0, 1, atrBuffer) <= 0)
      return;

   double atr = atrBuffer[0];
   double threshold = 0.0010;

   // Filter condition
   if(atr < threshold)
      return; // Low volatility, so do not enter

   // --- Entry logic starts here ---
   // Logic such as OrderSend
}

Practical notes:

  • It is safer to place the filter immediately before OrderSend
  • It is common to use it together with a spread filter
  • Execution conditions, such as VPS latency, also matter

Common mistakes:

  • Placing the filter too early before the signal
  • Making the filter so strict that no trades occur
  • Judging only by backtesting without forward validation

3. Why an ATR Filter Works

Conclusion: An ATR filter improves trade expectancy by excluding unfavorable market conditions in advance and reducing unnecessary losses.


3.1 Problems in Low-Volatility Markets

Conclusion: In low-volatility markets, price movement is small, profit potential is often too limited relative to spreads and commissions, and expectancy can fall.

Characteristics of low volatility, where ATR is small:

  • Narrow price movement, often in a range
  • More noise and false signals
  • Clear trends are less likely to appear

Trading in this environment can create these problems.

  • Price does not extend after entry
  • Spread costs consume the trade edge
  • Stops are hit easily by small up-and-down movements

This is especially damaging for scalping and short-term EAs.

Example:

  • Profit target: 5 pips
  • Spread: 2 pips

The effective profit margin is very small.

Common mistakes:

  • Entering all the time without using ATR
  • Repeating trades endlessly in a ranging market
  • Evaluating logic only by win rate

The key point is that the decision not to trade is also part of the strategy.


3.2 Characteristics of High-Volatility Markets

Conclusion: In high-volatility markets, price movement is larger, profit distance is easier to secure, and risk-reward can improve.

Characteristics of high volatility, where ATR is large:

  • Trends are more likely to form
  • Breakouts are more likely to work
  • Profits are more likely to extend

This environment has these benefits.

  • Profit can be earned with fewer trades
  • Some slippage may be absorbed by larger movement
  • Price movement is larger than execution costs

However, there are also risks.

  • Reversal risk from sudden price movement
  • Increased slippage
  • Execution delays and fill problems

Common misconception:

  • “High volatility means safe” is incorrect.
    The correct view is that profit potential is higher, but risk is also higher.

Therefore, the important question is not whether to use an ATR filter, but at what level to use it.


3.3 Effect on Expectancy

Conclusion: An ATR filter improves profit factor (PF) and expectancy by reducing losing trades.

Basic expectancy structure:

  • Expectancy = win rate × average profit – loss rate × average loss

Role of the ATR filter:

  • Reduce unnecessary trades in low volatility, which can lower the loss rate
  • Enter only in high volatility, which can increase average profit

As a result:

  • PF, or profit divided by loss, can improve
  • DD, or drawdown, can be reduced
  • The equity curve can become more stable

Specific changes:

MetricWithout FilterWith Filter
Number of tradesHighLow
Win rateMay be highSlightly lower
Profit distanceSmallLarge
PFLowHigh

Important points:

  • Profit distance matters more than win rate
  • Reducing trade count is not automatically bad

Common mistakes:

  • Discarding the logic only because the win rate dropped
  • Treating fewer trades as a negative by default
  • Judging without checking PF or expectancy

3.4 Role in EA Design

Conclusion: In an EA, an ATR filter works as a quality check before entry and supports strategy stability.

Typical position in EA design:

  • Signal generation, such as an MA cross
  • Filters, such as ATR, spread, and time
  • Entry execution, such as OrderSend

ATR belongs to the filter layer.

Its roles are:

  • Quantitative evaluation of market conditions
  • Exclusion of unfavorable environments
  • Improvement of logic reproducibility

Practical use:

  • Use ATR as part of a combined filter, not by itself
  • Examples:
    • ATR + spread filter
    • ATR + trend judgment, such as MA or RSI
    • ATR + session filter

Why combination is needed:

  • ATR only measures movement size
  • Direction, cost, and time are separate dimensions

Common mistakes:

  • Building a strategy with ATR alone
  • Adding too many filters and over-optimizing
  • Evaluating only with backtesting

Practical conclusion:

  • ATR is weak alone, but strong when combined correctly
  • It is a foundation component that raises EA quality

4. Comparison with Other Filter Methods

Conclusion: An ATR filter judges the size of market movement, while other filters such as spread, trend, and time control different risks. ATR alone is not enough; combining filters improves practical accuracy.


4.1 ATR Filter vs. Spread Filter

Conclusion: ATR controls market condition selection, while a spread filter controls trading cost. Their roles are fundamentally different.

Role of a spread filter:

  • Control entry cost
  • Avoid abnormal spread expansion

Implementation image:

double spread = (SymbolInfoDouble(_Symbol, SYMBOL_ASK) - SymbolInfoDouble(_Symbol, SYMBOL_BID)) / _Point;

if(spread > maxSpread)
   return;

Comparison:

ItemATR FilterSpread Filter
TargetMarket movementTrading cost
PurposeSelect favorable marketsAvoid unfavorable costs
NatureIndirectDirect

Important points:

  • Even if ATR is high, a wide spread can make the trade unfavorable
  • The basic approach is to check both at the same time

Common mistakes:

  • Judging by ATR alone
  • Entering while ignoring spread, which can lead to execution losses

4.2 ATR Filter vs. Trend Filter

Conclusion: ATR judges strength, while trend filters such as MA and RSI judge direction. Their roles complement each other.

Examples of trend filters:

  • Moving average (MA)
  • RSI
  • MACD

Characteristics:

  • Can judge upward or downward direction
  • Helps decide entry direction

Difference from ATR:

ItemATRTrend Filter
What it judgesRange of movementDirection
RoleWhether to enterWhich direction to enter
Standalone usefulnessLowMedium

Combination example:

if(atr > threshold && price > ma)
{
   // Uptrend and high volatility, so enter
}

Common mistakes:

  • Using ATR alone to decide buy or sell direction
  • Entering without trend judgment

Conclusion:

  • ATR answers “Is it moving?”
  • Trend answers “Which way is it moving?”

4.3 ATR Filter vs. Time Filter

Conclusion: ATR provides dynamic control based on market conditions, while a time filter provides static control based on fixed rules.

Examples of time filters:

  • Trade only during London hours
  • Avoid New York hours
  • Exclude periods before and after economic news releases

Implementation image:

int hour = TimeHour(TimeCurrent());

if(hour < 8 || hour > 20)
   return;

Comparison:

ItemATR FilterTime Filter
NatureDynamicStatic
FlexibilityHighLow
ReproducibilityMediumHigh

Important points:

  • Volatility changes even during the same time period
  • ATR adapts more directly to the market

However:

  • Time filters are highly reproducible and stable
  • ATR is more affected by historical optimization

Common mistakes:

  • Judging only by time
  • Using ATR while ignoring the trading session

4.4 Comparison Summary for Practical Decisions

Conclusion: The most effective approach is combining ATR with other filters. Using ATR alone is not recommended.

Overall comparison:

FilterAccuracyReproducibilityImplementation DifficultyBest Use
ATRMediumMediumLowVolatility judgment
SpreadHighHighLowCost control
TrendMediumMediumMediumDirection judgment
TimeLowHighLowStable operation

Best practical structure:

  • ATR for market condition
  • Spread for cost
  • Trend for direction
  • Time for stability

Example:

if(atr > atrThreshold &&
   spread < maxSpread &&
   price > ma &&
   hour >= 8 && hour <= 20)
{
   // High-quality entry condition
}

Important points:

  • Filters should be separated by role, not reduced blindly
  • Adding too many filters can eliminate trading opportunities

Common mistakes:

  • Adding too many filters and over-optimizing
  • Depending on one filter
  • Judging only by backtesting

Practical conclusion:

  • ATR is support, not the core of the strategy
  • Combined design is the assumption

5. Common Mistakes and Cautions

Conclusion: ATR filters are useful, but mistakes in threshold settings, period settings, and over-optimization can reduce trading opportunities or worsen performance. In this area, design mistakes are often more serious than implementation mistakes.


5.1 Threshold Setting Mistakes

Conclusion: The best threshold differs by currency pair and timeframe, so reusing one fixed value can make the filter fail.

Common problems:

  • Applying an EURUSD value directly to USDJPY
  • Using the same threshold on M1 and H1
  • Misreading decimal places by not considering _Point

Countermeasures:

  • Optimize separately by currency pair
  • Use separate parameters by timeframe
  • Convert ATR into points before comparing it

Example, point conversion:

double atrPoints = atrBuffer[0] / _Point;
if(atrPoints < minAtrPoints) return;

Why this matters:

  • ATR is an absolute value, so scale differences can be large
  • Volatility characteristics differ by instrument

5.2 Incorrect ATR Period Settings

Conclusion: If the period is too short, ATR reacts to noise. If it is too long, it cannot follow market changes quickly enough.

Typical behavior:

  • Short-term, such as 5 to 10
    • Fast response but more noise
  • Standard, such as 14
    • Good balance
  • Long-term, such as 50 or more
    • Stable but delayed

Selection guidelines:

  • Scalping: shorter side
  • Day trading: standard
  • Swing trading: longer side

Common mistakes:

  • Fixing the period without testing it
  • Optimizing only in backtests

5.3 Excessive Filtering

Conclusion: If filters are too strict, trade count can drop sharply and expectancy can become worse.

Typical example:

if(atr < threshold) return;
if(spread > maxSpread) return;
if(price < ma) return;
if(hour < 8 || hour > 20) return;

Problems:

  • Too many conditions prevent entries from occurring
  • Backtests may look good, but live performance can fail

Countermeasures:

  • Clarify the role of each filter
  • Separate filters that reduce bad trades from filters that improve trade quality

Decision standards:

  • If trade count drops too much, the filter is excessive
  • If only PF is high, be cautious because overfitting may be present

5.4 Ignoring Spread and Slippage

Conclusion: ATR alone cannot control cost, so spread and slippage must be managed separately.

Problems:

  • High volatility often comes with spread expansion
  • Slippage can increase around economic releases

Countermeasure:

double spread = (Ask - Bid) / _Point;
if(spread > maxSpread) return;

Important points:

  • ATR only sees market condition
  • Costs and execution conditions must be controlled separately

Common mistakes:

  • Assuming high ATR means the trade is safe
  • Getting good backtests while ignoring costs

5.5 The Backtest Optimization Trap (Over-Optimization)

Conclusion: If ATR thresholds and periods are optimized too closely to past data, future reproducibility can be lost.

Typical pattern:

  • Choosing parameters that work extremely well only in one specific period
  • Performance collapses in forward testing

Causes:

  • ATR depends heavily on market conditions and changes a lot
  • Past volatility structure does not necessarily match the future

Countermeasures:

  • Forward testing is required
  • Validate across multiple periods, such as walk-forward testing
  • Keep parameters simple

Decision standard:

  • Prioritize stability even if performance is slightly lower
  • Choose robust settings rather than the most optimized settings

5.6 Practical Checklist

Conclusion: If the following items are satisfied, an ATR filter is more likely to withstand live operation.

Checklist:

  • The threshold is adjusted by currency pair
  • The ATR period matches the strategy
  • A spread filter is used together with ATR
  • A trend filter has a separate role
  • Forward validation has been performed

6. Practical Use Cases by Strategy

Conclusion: An ATR filter works best when its use is changed by strategy. Instead of using one universal rule, design the condition around the strategy’s characteristics.


6.1 Use in Trend-Following Strategies

Conclusion: In trend following, allowing entries only when ATR is above a set level helps target markets that are more likely to extend.

Characteristics of trend following:

  • Profit is extended by riding a trend
  • Losses are more likely in sideways markets

Role of the ATR filter:

  • Extract conditions where trends are more likely to appear
  • Avoid ranging markets

Implementation image:

if(atr > atrThreshold && price > ma)
{
   // Uptrend and high volatility, so buy
}

Key points:

  • Use it together with a trend filter such as MA
  • ATR alone does not show direction

Common mistakes:

  • Entering with ATR alone
  • Skipping trend judgment

6.2 Use in Breakout Strategies

Conclusion: In breakout strategies, using the timing of rising ATR can reduce false breakouts.

Challenges in breakout trading:

  • Many false breakouts occur inside ranges
  • Breakouts are more likely to fail when volatility is low

How to use the ATR filter:

  • Enter only when ATR is rising
  • Volatility expansion can indicate a higher chance of real movement

Implementation example:

if(atr > atrThreshold && atr > prevAtr)
{
   // Use breakout only while volatility is expanding
}

Key points:

  • Look not only at the absolute ATR value but also at whether it is increasing
  • Use CopyBuffer to get multiple bars and compare them

Common mistakes:

  • Not checking ATR change
  • Judging only with a static threshold

6.3 Use in Scalping

Conclusion: In scalping, avoiding low ATR conditions is the most important point, and the decision not to trade directly affects profitability.

Characteristics of scalping:

  • Profit distance is small
  • Spread has a large impact

Problems:

  • Low volatility makes it easy to lose to spread costs
  • Execution delays can create a disadvantage

Role of the ATR filter:

  • Exclude low-volatility environments
  • Require a minimum level of price movement

Implementation example:

if(atr < minAtrThreshold)
   return; // Prohibit entry

Important points:

  • Avoiding low volatility is more important than attacking high volatility
  • Use with a spread filter is required

Common mistakes:

  • Trading all the time
  • Trying to win by trade count without using ATR

6.4 Combined Filter Design for Live Operation

Conclusion: In live operation, ATR alone is not enough. A combination of multiple filters should be assumed.

Typical structure:

  • ATR: market condition
  • Spread: cost control
  • Trend: direction
  • Time: stability

Implementation example:

double spread = (Ask - Bid) / _Point;
int hour = TimeHour(TimeCurrent());

if(atr > atrThreshold &&
   spread < maxSpread &&
   price > ma &&
   hour >= 8 && hour <= 20)
{
   // High-quality entry
}

Design approach:

  • Each filter should have a separate role
  • Avoid overlapping functions to prevent redundant design

Practical decision axes:

  • ATR: “Is it moving?”
  • Spread: “Can the cost be tolerated?”
  • Trend: “Is the direction aligned?”

Common mistakes:

  • Adding too many filters
  • Trying to solve everything with ATR
  • Judging only by backtesting

6.5 Best Practical Mindset

Conclusion: The real purpose of an ATR filter is not to increase entries, but to reduce them.

Important points:

  • Fewer trades can be acceptable
  • Keep only high-quality entries
  • Evaluate with PF and DD

Decision standards:

  • Trade count decreases: normal
  • PF rises: successful
  • DD decreases: practical level

Final role:

  • ATR is a central filter component
  • However, it does not stand alone

7. Reusable Implementation Template

Conclusion: An ATR filter can be reused in almost any EA when it is organized as a minimum structure: create the handle in OnInit, get the value in OnTick, and control entries with conditional logic.


7.1 Initialization in OnInit

Conclusion: The iATR handle should be created only once in OnInit, not regenerated on every tick.

int atrHandle;

int OnInit()
{
   atrHandle = iATR(_Symbol, PERIOD_CURRENT, 14);

   if(atrHandle == INVALID_HANDLE)
   {
      Print("Failed to get ATR handle");
      return(INIT_FAILED);
   }

   return(INIT_SUCCEEDED);
}

Key points:

  • _Symbol: the current currency pair
  • PERIOD_CURRENT: the current timeframe
  • 14: a common initial value that can be adjusted

Common mistakes:

  • Calling iATR every time in OnTick, which lowers performance
  • Not checking INVALID_HANDLE, which can cause abnormal behavior

7.2 Getting ATR in OnTick

Conclusion: Get the latest ATR value with CopyBuffer and always perform error checking.

double atrBuffer[];

bool GetATR(double &atr)
{
   ArraySetAsSeries(atrBuffer, true);

   if(CopyBuffer(atrHandle, 0, 0, 1, atrBuffer) <= 0)
   {
      Print("Failed to get ATR");
      return false;
   }

   atr = atrBuffer[0];
   return true;
}

Usage:

double atr;

if(!GetATR(atr))
   return;

Important points:

  • The latest value is atrBuffer[0]
  • Stop processing when CopyBuffer fails

Common mistakes:

  • Uninitialized buffer
  • Not checking the return value
  • Using an old bar value

7.3 Implementing the Filter Condition

Conclusion: Simple entry control is possible by comparing ATR with a threshold.

double atrThreshold = 0.0010;

if(atr < atrThreshold)
{
   // Low volatility, so do not enter
   return;
}

Application, point conversion:

double atrPoints = atr / _Point;

if(atrPoints < minAtrPoints)
   return;

Key points:

  • Adjustment by currency pair is required
  • Change the threshold by timeframe

Common mistakes:

  • Reusing a fixed value
  • Decimal-place mistakes, especially with JPY pairs

7.4 Entry Control Before OrderSend

Conclusion: Placing the ATR filter immediately before entry gives safer and more flexible control.

void OnTick()
{
   double atr;

   if(!GetATR(atr))
      return;

   double atrThreshold = 0.0010;

   // ATR filter
   if(atr < atrThreshold)
      return;

   // --- Entry starts here ---
   // Processing such as OrderSend
}

Recommended practical structure:

if(atr > atrThreshold &&
   spread < maxSpread &&
   price > ma)
{
   // High-quality entry condition
}

Important points:

  • Place the filter immediately before OrderSend
  • Combine it with other filters

Common mistakes:

  • Placing the filter before the signal and breaking the logic
  • Scattering conditions throughout the code and reducing readability

7.5 Minimum Template for Copy and Paste

Conclusion: The following code is a minimum structure that can be added directly to an EA.

int atrHandle;
double atrBuffer[];

int OnInit()
{
   atrHandle = iATR(_Symbol, PERIOD_CURRENT, 14);
   return(INIT_SUCCEEDED);
}

bool GetATR(double &atr)
{
   ArraySetAsSeries(atrBuffer, true);

   if(CopyBuffer(atrHandle, 0, 0, 1, atrBuffer) <= 0)
      return false;

   atr = atrBuffer[0];
   return true;
}

void OnTick()
{
   double atr;

   if(!GetATR(atr))
      return;

   double atrThreshold = 0.0010;

   if(atr < atrThreshold)
      return;

   // --- Entry processing ---
}

7.6 Practical Extension Points

Conclusion: The template becomes valuable when it is extended according to the strategy instead of used unchanged.

Extension examples:

  • Judge whether ATR is rising or falling, indicating volatility expansion
  • Branch parameters by currency pair
  • Use timeframe-specific logic
  • Integrate with multiple indicators

Cautions:

  • Too much complexity leads to over-optimization
  • More parameters can reduce reproducibility

Practical conclusion:

  • Start simple
  • Adjust through forward validation

8. Frequently Asked Questions

8.1 What is an ATR volatility filter?

Conclusion: An ATR volatility filter is a mechanism that separates markets to trade from markets to skip based on the ATR value.

Because ATR shows the range of price movement, it can be used to avoid low-volatility markets or target only high-volatility markets. In MQL5, ATR values are obtained with iATR and CopyBuffer, then added to entry conditions.


8.2 What ATR period should I use?

Conclusion: A 14-period ATR is commonly used, but the best period depends on the strategy, currency pair, and timeframe.

Shorter ATR periods may fit short-term trading, while longer ATR periods may fit swing or longer-term strategies. However, optimizing only on past data can easily lead to over-optimization, so forward validation is also required.


8.3 Should I avoid entries when ATR is low?

Conclusion: In many EAs, avoiding entries when ATR is low is an effective design choice.

In low-volatility markets, price range is small and trading costs such as spread and slippage can easily consume the edge. This is especially important for scalping and short-term trading, where excluding conditions below a minimum ATR can reduce unnecessary trades.


8.4 Can an ATR filter alone create a profitable EA?

Conclusion: It is difficult to create a profitable EA with an ATR filter alone. Directional logic and cost control are also needed.

ATR only shows the size of price movement and does not show whether price is rising or falling. In practice, it should be combined with trend judgment such as moving averages, RSI, or MACD, as well as spread filters and time filters.


8.5 Can the ATR threshold be fixed?

Conclusion: You should avoid reusing one fixed ATR threshold across all currency pairs and timeframes.

ATR represents the price movement itself, so the value scale differs across instruments such as USDJPY, EURUSD, and XAUUSD. In practice, convert ATR by dividing it by _Point, or use separate thresholds by currency pair and timeframe.

double atrPoints = atr / _Point;

if(atrPoints < minAtrPoints)
   return;

8.6 Which is more important, an ATR filter or a spread filter?

Conclusion: Their roles are different, so the basic approach is to use both instead of choosing only one.

An ATR filter judges market volatility, while a spread filter controls trading cost. Even when ATR is high, a wide spread can create unfavorable execution, so checking both before OrderSend is safer.


8.7 Is it okay to optimize the ATR threshold in backtesting?

Conclusion: Optimization is possible, but multiple-period validation and forward testing are needed to avoid over-optimization.

Because ATR thresholds depend on market conditions, settings fitted to one specific period may not work in live operation. Do not judge by PF alone; also check DD, trade count, average profit, and average loss.


8.8 Which strategies work well with an ATR filter?

Conclusion: ATR filters work well with trend following, breakout, and scalping strategies.

In trend following, ATR can target high-volatility markets. In breakout trading, it can confirm volatility expansion. In scalping, it can help avoid low-volatility conditions. However, because ATR does not show direction, it must be combined with logic that decides buy or sell direction.