Extreme Reclaim
Prior N-bar high or low is pierced and the close finishes back inside, with penetration at least k times Wilder ATR.
Visual Example
Eight bars with high 11, low 10, close 10.5, then a bar with low 9 and close 10.2. That bar pierces the prior low and closes back above it. With window 5, ATR length 5, and size_k 0.5, the penetration of 1 still passes after that bar's true range lifts ATR to 1.2. A close that stays below the prior low is a pierce, not a reclaim.
Description
Prior N-bar high or low is pierced and the close finishes back inside, with penetration at least k times Wilder ATR.
bullish is the full three-part test. bull_pierce and bull_reclaim are the parts, so a caller can drop the size filter. A close that stays beyond the extreme is a break, not a reclaim.
Price-action tooling with streaming and Polars batch parity. Rich outputs feed backtest signals, regime filters, and ML feature pipelines.
Not Ehlers. Pierce-and-reclaim from Build Alpha CustomIndicators.xml (Bergstrom): window 20, ATR 20, k = 0.5, penetration compared with >=.
Typical applications:
- Size stops and position risk from band width or ATR expansion
- Detect squeeze conditions (narrow bands) before breakout systems
- Warm-up: first
20bars build rolling volatility state - Combine with trend direction (SuperTrend, MACD) for breakout bias
QuantWave implements this via the universal Next<T> trait — bit-identical across Rust streaming, Python streaming, and Polars .ta() batch plugins.
Formula / Specification
Implementation (market_structure):
Parameters
| Parameter | Default | Description |
|---|---|---|
window |
20 | Bars in the prior extreme. The current bar is excluded. |
atr_period |
20 | Wilder ATR length for the penetration test. |
size_k |
0.5 | Minimum penetration as a multiple of ATR. |
Usage Examples
Streaming (Rust)
use quantwave_core::indicators::ExtremeReclaim;
use quantwave_core::traits::Next;
let mut ind = ExtremeReclaim::new(20);
for price in &prices {
let value = ind.next(price);
}
Streaming (Python)
from quantwave import ExtremeReclaim
ind = ExtremeReclaim(20)
for price in prices:
value = ind.next(price)
Polars Batch (Python)
import polars as pl
import quantwave as qw
def apply_extreme_reclaim(series: pl.Series) -> pl.Series:
ind = qw.ExtremeReclaim(20)
return pl.Series([ind.next(float(v)) for v in series.to_list()])
df = (
pl.read_csv('ohlcv.csv')
.lazy()
.with_columns(
pl.col("close").map_batches(apply_extreme_reclaim, return_dtype=pl.Float64).alias("extreme_reclaim")
)
.collect()
)
All surfaces are bit-identical via the single Next<T> implementation and proptests.
Edge Cases & Limitations
- Warm-up: first
20bars may return NaN or partial state per implementation. - Parameter sensitivity: smaller periods increase noise; larger periods increase lag.
- Sudden gaps or bad ticks can distort rolling windows — consider pre-filtering.
- Single-series indicators ignore volume unless otherwise documented.
- Validated via proptests against gold-standard vectors where available.
- No look-ahead bias; streaming and Polars batch paths are bit-identical.
Boundary Behavior
| Condition | Behavior |
|---|---|
| Warm-up | Early bars return empty event lists or default structs (no scalar NaN). |
| period > len | Insufficient history yields no events rather than NaN scalars. |
| NaN inputs | NaN OHLC typically suppresses event detection for that bar. |
| Invalid params | Invalid swing_strength or tolerance raises ValueError. |
| Empty data | Empty input returns empty event collections. |
Related Indicators & See Also
Sources & References
Primary Source: David Bergstrom, Build Alpha, https://www.buildalpha.com/backtest-ict-and-smc/ CustomIndicators.xml (window 20, ATR length 20, k = 0.5).
Implementation: quantwave-core/src/indicators/market_structure (ExtremeReclaim / _METADATA).
Provenance: Standards bulk upgrade 2026-10-02 IST — see docs/DOCUMENTATION_STANDARDS.md.