- 1 1. What Is an MQL5 ATR Volatility Filter?
- 2 2. How to Implement an ATR Volatility Filter
- 3 3. Why an ATR Filter Works
- 4 4. Comparison with Other Filter Methods
- 5 5. Common Mistakes and Cautions
- 6 6. Practical Use Cases by Strategy
- 7 7. Reusable Implementation Template
- 8 8. Frequently Asked Questions
- 8.1 8.1 What is an ATR volatility filter?
- 8.2 8.2 What ATR period should I use?
- 8.3 8.3 Should I avoid entries when ATR is low?
- 8.4 8.4 Can an ATR filter alone create a profitable EA?
- 8.5 8.5 Can the ATR threshold be fixed?
- 8.6 8.6 Which is more important, an ATR filter or a spread filter?
- 8.7 8.7 Is it okay to optimize the ATR threshold in backtesting?
- 8.8 8.8 Which strategies work well with an ATR filter?
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 pairPERIOD_CURRENT: the current timeframe14: a common default period
Common mistakes:
- Not checking whether handle creation failed
- Creating the handle on every tick in
OnTickinstead of once inOnInit, 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 bufferstart_pos = 0: the latest barcount = 1: get only one barArraySetAsSeries(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:
| Metric | Without Filter | With Filter |
|---|---|---|
| Number of trades | High | Low |
| Win rate | May be high | Slightly lower |
| Profit distance | Small | Large |
| PF | Low | High |
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:
| Item | ATR Filter | Spread Filter |
|---|---|---|
| Target | Market movement | Trading cost |
| Purpose | Select favorable markets | Avoid unfavorable costs |
| Nature | Indirect | Direct |
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:
| Item | ATR | Trend Filter |
|---|---|---|
| What it judges | Range of movement | Direction |
| Role | Whether to enter | Which direction to enter |
| Standalone usefulness | Low | Medium |
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:
| Item | ATR Filter | Time Filter |
|---|---|---|
| Nature | Dynamic | Static |
| Flexibility | High | Low |
| Reproducibility | Medium | High |
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:
| Filter | Accuracy | Reproducibility | Implementation Difficulty | Best Use |
|---|---|---|---|---|
| ATR | Medium | Medium | Low | Volatility judgment |
| Spread | High | High | Low | Cost control |
| Trend | Medium | Medium | Medium | Direction judgment |
| Time | Low | High | Low | Stable 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
CopyBufferto 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 pairPERIOD_CURRENT: the current timeframe14: a common initial value that can be adjusted
Common mistakes:
- Calling
iATRevery time inOnTick, 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
CopyBufferfails
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.