Files

211 lines
7.4 KiB
Markdown
Raw Permalink Normal View History

2026-02-02 13:42:47 -08:00
# NATR: Normalized Average True Range
> *The same volatility reads different on different price scales. NATR speaks the universal language of percentages.*
2026-02-27 07:48:12 -08:00
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Volatility |
| **Inputs** | OHLCV bar (TBar) |
| **Parameters** | `period` (default 14) |
| **Outputs** | Single series (Natr) |
| **Output range** | $\geq 0$ |
| **Warmup** | 1 bar |
| **PineScript** | [natr.pine](natr.pine) |
2026-02-27 07:48:12 -08:00
- NATR normalizes the Average True Range (ATR) as a percentage of the closing price.
- **Similar:** [ATR](../atr/atr.md), [ATRN](../atrn/atrn.md) | **Complementary:** Cross-asset comparison | **Trading note:** Normalized ATR as percentage of close.
2026-02-27 07:48:12 -08:00
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
2026-02-02 13:42:47 -08:00
NATR normalizes the Average True Range (ATR) as a percentage of the closing price. This is mathematically identical to ATRP (Average True Range Percent)—both compute `(ATR / Close) × 100`. The difference is purely nomenclature: NATR is the term used in TA-Lib and many charting platforms.
## Historical Context
NATR derives from J. Welles Wilder Jr.'s ATR, introduced in his 1978 *New Concepts in Technical Trading Systems*. While Wilder's original ATR provided absolute volatility in price units, traders and quantitative analysts quickly recognized the need for percentage-based normalization.
The "Normalized" moniker became standard in the TA-Lib open-source library, which formalized the calculation as `NATR = (ATR / Close) × 100`. This naming convention spread through the algorithmic trading community, creating the parallel terminology alongside "ATRP" (Average True Range Percent) used in other contexts.
Both names describe the same mathematical transformation: making volatility comparable across instruments with different price levels.
## Architecture & Physics
NATR consists of three cascaded components:
### 1. True Range (TR)
Captures the actual price movement including gaps:
$$
TR_t = \max(H_t - L_t, |H_t - C_{t-1}|, |L_t - C_{t-1}|)
$$
Where:
- $H_t$: Current high
- $L_t$: Current low
- $C_{t-1}$: Previous close
First bar uses simple range: $TR_0 = H_0 - L_0$
### 2. RMA Smoothing (Wilder's Method)
ATR smooths TR using Wilder's RMA with $\alpha = 1/N$:
$$
ATR_t = \alpha \cdot TR_t + (1 - \alpha) \cdot ATR_{t-1}
$$
With warmup compensation to eliminate initialization bias:
$$
e_t = e_{t-1} \cdot (1 - \alpha), \quad e_0 = 1
$$
$$
ATR_{compensated} = \frac{ATR_{raw}}{1 - e_t} \quad \text{when } e_t > \epsilon
$$
### 3. Percentage Normalization
$$
NATR_t = \frac{ATR_t}{C_t} \times 100
$$
This transforms absolute volatility into relative volatility, enabling cross-asset comparison.
## Mathematical Foundation
### Complete Formula Chain
Given period $N$:
1. **Parameters**: $\alpha = \frac{1}{N}$, $\text{decay} = 1 - \alpha$
2. **True Range**:
$$
TR_t = \begin{cases}
H_t - L_t & \text{if } t = 0 \\
\max(H_t - L_t, |H_t - C_{t-1}|, |L_t - C_{t-1}|) & \text{otherwise}
\end{cases}
$$
3. **RMA with FMA optimization**:
$$
ATR_{raw,t} = \text{FMA}(ATR_{raw,t-1}, \text{decay}, \alpha \cdot TR_t)
$$
4. **Warmup compensation**:
$$
ATR_t = \frac{ATR_{raw,t}}{1 - e_t}
$$
5. **Normalization**:
$$
NATR_t = \frac{ATR_t}{C_t} \times 100
$$
### Warmup Period
Convergence threshold: $e < 0.05$ (5% remaining bias)
$$
\text{WarmupPeriod} = \left\lceil \frac{\ln(0.05)}{\ln(1 - \alpha)} \right\rceil
$$
For $N = 14$: $\text{WarmupPeriod} \approx 42$ bars.
## Performance Profile
| Metric | Score | Notes |
| :--- | :---: | :--- |
| **Throughput** | 10/10 | O(1) calculation via RMA + single division |
| **Allocations** | 0 | Zero-allocation streaming; state in record struct |
| **Complexity** | O(1) | Constant time regardless of period |
| **Accuracy** | 10/10 | Exact mathematical computation |
| **Timeliness** | 4/10 | Inherits ATR's lag from RMA smoothing |
| **Overshoot** | 0/10 | Mathematically bounded |
| **Smoothness** | 8/10 | Smooth RMA decay; minor noise from close price variation |
### Operation Count (Streaming Mode)
| Operation | Count | Notes |
| :--- | :---: | :--- |
| SUB | 3 | H-L, H-PrevC, L-PrevC |
| ABS | 2 | Gap calculations |
| MAX | 2 | True Range selection |
| FMA | 1 | RMA update |
| MUL | 1 | Decay for warmup |
| DIV | 2 | Warmup compensation + percentage |
| MUL | 1 | × 100 |
| **Total** | ~12 ops | Dominated by FMA and divisions |
## Validation
NATR is validated by computing ATR from external libraries and applying the same percentage formula.
| Library | Status | Notes |
| :--- | :---: | :--- |
| **QuanTAlib** | ✅ | Native implementation |
| **TA-Lib** | ✅ | Via `(ATR / Close) × 100`; tolerance 0.10 for warmup divergence |
| **Skender** | ✅ | Via `(GetAtr / Close) × 100` |
| **Tulip** | ✅ | Via `(atr / Close) × 100` |
| **Ooples** | ✅ | Via `(CalculateAverageTrueRange / Close) × 100` |
Note: QuanTAlib's warmup-compensated RMA may diverge 4-7% from classic Wilder implementations over long histories. Both approaches are mathematically valid; QuanTAlib prioritizes accurate early-series values.
## Use Cases
### Cross-Asset Volatility Comparison
Compare volatility across different price scales:
| Asset | Price | ATR | NATR |
| :--- | :---: | :---: | :---: |
| Penny Stock | $2.50 | 0.25 | 10.0% |
| Mid-Cap | $150 | 4.50 | 3.0% |
| Blue Chip | $500 | 5.00 | 1.0% |
ATR suggests Blue Chip is most volatile. NATR reveals Penny Stock has 10× the relative volatility.
### Volatility-Adjusted Position Sizing
```
Position Size = (Account Risk %) / NATR
```
Ensures equal percentage risk per position regardless of asset price.
### Regime Detection
| NATR Range | Interpretation | Strategy Implication |
| :--- | :--- | :--- |
| < 1% | Low volatility | Mean reversion, tight stops |
| 1-3% | Normal | Standard trend-following |
| 3-5% | Elevated | Wider stops, reduced size |
| > 5% | High volatility | Crisis mode, capital preservation |
## Common Pitfalls
1. **Lag Inheritance**: NATR inherits ATR's smoothing lag. It measures recent volatility, not current or future volatility.
2. **Close Price Spikes**: A sharp close creates transient NATR spikes since it affects both TR (numerator) and the denominator simultaneously.
3. **Near-Zero Prices**: Assets approaching zero produce extreme NATR values. Implement minimum price thresholds.
4. **Gap Sensitivity**: Large overnight gaps inflate TR significantly. Consider using gap-adjusted data for equity analysis.
5. **Warmup Period**: The first 40+ bars (for period=14) contain warmup bias. Use `IsHot` to filter unreliable values.
6. **OHLC Requirement**: NATR requires bar data (Open, High, Low, Close). It cannot be computed from close prices alone. Use `Update(TBar)` not `Update(TValue)`.
## Related Indicators
- **ATR**: Absolute volatility measure NATR normalizes
2026-02-23 17:27:35 -08:00
- **ATRN**: ATR normalized to [0,1] based on historical min/max (different algorithm)
2026-02-02 13:42:47 -08:00
- **CV**: Coefficient of Variation—alternative percentage volatility measure
- **HV**: Historical Volatility—annualized standard deviation approach
## References
- Wilder, J.W. (1978). *New Concepts in Technical Trading Systems*. Trend Research.
- TA-Lib documentation: NATR function specification
- TradingView PineScript: `ta.natr()` implementation