Using ATR for Dynamic Stop-Loss Placement
Learn how to use Average True Range (ATR) to set volatility-adjusted stop losses that adapt to market conditions, with full code examples.
The Problem with Fixed Stop Losses
A 50-pip stop loss on EURUSD might work perfectly in a quiet Asian session but get triggered by normal noise during a London/New York overlap. Fixed stops ignore the current volatility regime, leading to either premature exits or unnecessarily wide risk exposure.
ATR solves this by measuring the average range of price movement over a period. When volatility expands, your stop widens. When it contracts, your stop tightens. The result is a stop loss that breathes with the market.
Adjusts to current volatility
Premature stop-outs
Risk-reward ratios
How ATR Works
True Range is the greatest of: (1) current high minus current low, (2) absolute value of current high minus previous close, or (3) absolute value of current low minus previous close. ATR is simply the moving average of True Range over N periods (typically 14).
True Range = max(
High - Low,
abs(High - Previous Close),
abs(Low - Previous Close)
)
ATR(14) = SMA(True Range, 14)
Fetching ATR from the API
curl -H "X-API-Key: YOUR_API_KEY" \
"https://tickatlas.com/v1/indicator?symbol=EURUSD&indicator=ATR_14&timeframe=H4"
Response:
{
"success": true,
"data": {
"symbol": "EURUSD",
"timeframe": "H4",
"indicator": "ATR_14",
"values": {
"atr": 0.00387
},
"ohlcv": {
"open": 1.0845,
"high": 1.0871,
"low": 1.0832,
"close": 1.0858,
"volume": 12340
},
"timestamp": "2026-03-28T12:00:00Z"
}
} An ATR of 0.00387 for EURUSD on H4 means the average bar moves about 38.7 pips. This is your building block for stop-loss calculation.
Python: ATR-Based Stop-Loss Calculator
import requests
from dataclasses import dataclass
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://tickatlas.com/v1"
@dataclass
class StopLossResult:
symbol: str
direction: str
entry_price: float
stop_loss: float
take_profit: float
atr_value: float
risk_pips: float
reward_pips: float
def calculate_atr_stop(
symbol: str,
timeframe: str,
direction: str = "long",
atr_multiplier: float = 2.0,
rr_ratio: float = 1.5,
) -> StopLossResult:
"""Calculate ATR-based stop loss and take profit."""
resp = requests.get(
f"{BASE_URL}/indicator",
headers={"X-API-Key": API_KEY},
params={
"symbol": symbol,
"indicator": "ATR_14",
"timeframe": timeframe,
},
)
resp.raise_for_status()
data = resp.json()["data"]
atr = data["values"]["atr"]
close = data["ohlcv"]["close"]
stop_distance = atr * atr_multiplier
if direction == "long":
stop_loss = close - stop_distance
take_profit = close + (stop_distance * rr_ratio)
else:
stop_loss = close + stop_distance
take_profit = close - (stop_distance * rr_ratio)
# Convert to pips (works for most forex pairs)
pip_factor = 10000 if "JPY" not in symbol else 100
risk_pips = stop_distance * pip_factor
reward_pips = stop_distance * rr_ratio * pip_factor
return StopLossResult(
symbol=symbol,
direction=direction,
entry_price=close,
stop_loss=round(stop_loss, 5),
take_profit=round(take_profit, 5),
atr_value=atr,
risk_pips=round(risk_pips, 1),
reward_pips=round(reward_pips, 1),
)
# Example usage
result = calculate_atr_stop("EURUSD", "H4", "long", 2.0, 1.5)
print(f"Entry: {result.entry_price}")
print(f"Stop Loss: {result.stop_loss} ({result.risk_pips} pips)")
print(f"Take Profit: {result.take_profit} ({result.reward_pips} pips)") Choosing the ATR Multiplier
The multiplier you choose depends on your trading style and the market conditions:
1.0x ATR -- Tight stops (scalping)
More stop-outs, but smaller losses per trade. Best for high-probability setups on lower timeframes.
1.5x -- 2.0x ATR -- Standard (day/swing trading)
The most common range. Gives enough room for normal price fluctuation while limiting risk.
2.5x -- 3.0x ATR -- Wide stops (position trading)
Allows trades to survive significant pullbacks. Requires smaller position sizes to manage risk.
Position Sizing with ATR
ATR-based stops naturally lead to ATR-based position sizing. If your stop is wider because volatility is high, you trade a smaller position to keep dollar risk constant:
def position_size(
account_balance: float,
risk_percent: float,
atr_value: float,
atr_multiplier: float,
pip_value: float = 10.0, # per standard lot
) -> float:
"""Calculate position size in lots."""
risk_amount = account_balance * (risk_percent / 100)
stop_pips = atr_value * atr_multiplier * 10000 # for non-JPY pairs
lots = risk_amount / (stop_pips * pip_value)
return round(lots, 2)
# Risk 1% of a $10,000 account
lots = position_size(10000, 1.0, 0.00387, 2.0)
print(f"Position size: {lots} lots") # ~0.13 lots Trailing Stop with ATR
You can also use ATR as a trailing stop. As the trade moves in your favor, trail the stop at a fixed ATR distance from the most favorable price:
class ATRTrailingStop:
def __init__(self, atr_multiplier: float = 2.0):
self.multiplier = atr_multiplier
self.highest_price = None
self.trailing_stop = None
def update(self, current_price: float, atr: float) -> float:
"""Update trailing stop for a long position."""
if self.highest_price is None:
self.highest_price = current_price
self.highest_price = max(self.highest_price, current_price)
new_stop = self.highest_price - (atr * self.multiplier)
if self.trailing_stop is None:
self.trailing_stop = new_stop
else:
# Stop can only move up, never down
self.trailing_stop = max(self.trailing_stop, new_stop)
return self.trailing_stop
Related Reading
Try this with live data
Every account gets $2.50 in free PAYG credits. No card required — paste your API key and run the code above against live broker data.
Keep reading
All articles- Tutorial 11 min read
24/7 Crypto Monitoring: Building Always-On Analysis Systems
Build a monitoring system that watches crypto markets around the clock, detects significant moves, and sends alerts when conditions match your criteria.
March 28, 2026
- Tutorial 12 min read
How to Build an AI Market Analyst That Runs 24/7
Build a production-ready AI market analyst that monitors forex and crypto markets around the clock, generates daily briefings, and alerts you to opportunities via Telegram.
March 28, 2026
- Tutorial 11 min read
How to Backtest a Trading Strategy with Historical API Data
Learn how to backtest your trading strategy using historical OHLC and indicator data from the TickAtlas API. Includes a complete Python backtesting framework.
March 28, 2026