ATR-based position sizing

A fixed-point stop distance (chapter 71's entry_price - stop_price) doesn't adapt to how volatile the instrument currently is. ATR (Average True Range) sizes the stop — and therefore the position — to current volatility, so a calm stock and a wild one carry comparable *risk* per trade despite different price behavior.

Computing ATR

import pandas as pd

def compute_atr(df: pd.DataFrame, period: int = 14) -> pd.Series:
    high, low, close = df["high"], df["low"], df["close"]
    prev_close = close.shift(1)
    tr = pd.concat([
        high - low,
        (high - prev_close).abs(),
        (low - prev_close).abs(),
    ], axis=1).max(axis=1)
    return tr.rolling(period).mean()

Sizing off a volatility-scaled stop

def atr_based_qty(account_equity: float, risk_pct: float, entry_price: float, atr: float, atr_multiplier: float = 2.0, lot_size: int = 1) -> int:
    risk_amount = account_equity * (risk_pct / 100)
    stop_distance = atr * atr_multiplier
    if stop_distance == 0:
        return 0
    raw_qty = int(risk_amount / stop_distance)
    return (raw_qty // lot_size) * lot_size

def atr_based_stop_price(entry_price: float, atr: float, atr_multiplier: float, side: str) -> float:
    distance = atr * atr_multiplier
    return entry_price - distance if side == "BUY" else entry_price + distance
df["atr14"] = compute_atr(df, 14)
latest_atr = df["atr14"].iloc[-1]

qty = atr_based_qty(account_equity=100000, risk_pct=1.0, entry_price=1470, atr=latest_atr, atr_multiplier=2.0)
stop = atr_based_stop_price(entry_price=1470, atr=latest_atr, atr_multiplier=2.0, side="BUY")

Why atr_multiplier matters as much as the risk percentage

A multiplier too small (e.g. 0.5x ATR) places the stop inside normal price noise — you get stopped out repeatedly by ordinary volatility, not by the thesis actually being wrong (this shows up as low win rate purely from noise, unrelated to signal quality). A multiplier too large (e.g. 5x ATR) makes stops so wide that position sizes shrink to near-zero under the fixed-risk formula, or risk becomes too large if position size isn't correctly capped. 1.5x-3x ATR is a common starting range — validate it empirically per instrument/timeframe via backtesting (chapter 82), don't assume a single multiplier works everywhere.

Recompute ATR fresh for every new trade, not once per strategy

Volatility regimes shift — an ATR computed at strategy start and reused for months will misjudge risk as the instrument's behavior changes. Recompute from the latest available candles each time you size a new entry.

Next: 073 — Risk per trade and daily loss limit