Complete thin Dx-composition wrapper indicators with full test coverage: - PlusDi/MinusDi: Directional Indicator wrappers (DiPlus/DiMinus from Dx) - PlusDm/MinusDm: Directional Movement wrappers (DmPlus/DmMinus from Dx) - Individual validation tests per indicator directory (TALib, Skender, bounds) - Combined unit tests (DiDm.Tests.cs) and validation tests (DiDm.Validation.Tests.cs) - Quantower wrappers + tests for all 4 indicators - PineScript v6 implementations with compensated RMA - Normalized .md documentation for all indicators and categories - 182 tests passing, 0 failures
6.9 KiB
BBANDS: Bollinger Bands
Standard deviation channels adapt to the market's own volatility rhythm, expanding and contracting like breathing.
| Property | Value |
|---|---|
| Category | Channel |
| Inputs | Source (close) |
| Parameters | period (default DefaultPeriod), multiplier (default DefaultMultiplier) |
| Outputs | Multiple series (Middle, Upper, Lower, Width, PercentB) |
| Output range | Tracks input |
| Warmup | period bars |
| PineScript | bbands.pine |
- Bollinger Bands construct a volatility-adaptive envelope around a Simple Moving Average using population standard deviation as the width measure.
- Parameterized by
period(default defaultperiod),multiplier(default defaultmultiplier). - Output range: Tracks input.
- Requires
periodbars of warmup before first valid output (IsHot = true). - Validated against TA-Lib, Skender, and Tulip reference implementations where available.
Bollinger Bands construct a volatility-adaptive envelope around a Simple Moving Average using population standard deviation as the width measure. The bands expand during high-volatility periods and contract during consolidation, dynamically adapting to changing market conditions. Under Gaussian assumptions, \pm 2\sigma contains approximately 95.4% of price action, but financial returns exhibit fat tails and volatility clustering, so the bands function more as a volatility-normalized reference frame than a strict probability envelope. The derived metrics %B (price position as a fraction of band width) and BandWidth (normalized band spread) extend the raw bands into a complete analytical toolkit.
Historical Context
John Bollinger developed Bollinger Bands in the early 1980s while working as a market technician. He registered the name as a trademark in 1996 and published Bollinger on Bollinger Bands (McGraw-Hill, 2001). The indicator emerged from Bollinger's observation that fixed-percentage envelopes fail to account for changing volatility: a 5% envelope that works during quiet markets becomes useless during volatile phases, and vice versa.
Bollinger drew on statistical probability theory. Under the normal distribution, approximately 68% of observations fall within \pm 1\sigma, 95% within \pm 2\sigma, and 99.7% within \pm 3\sigma. By defaulting the multiplier to 2.0, he created bands targeting the 95% containment level. Chebyshev's inequality guarantees at least 75% containment at \pm 2\sigma regardless of distribution shape. In practice, with fat-tailed market returns (typical kurtosis 4-6), expect 92-95% containment rather than 95.4%.
The "Squeeze" pattern (BandWidth at multi-period lows) became one of the most recognized technical analysis signals, predating and influencing the TTM Squeeze indicator. Walking the bands (price hugging the upper or lower band during trends) is a momentum signal, not a reversal signal. Bollinger Bands became one of the most widely adopted technical analysis tools, available in virtually every charting platform.
Architecture & Physics
1. Middle Band (SMA)
\text{Middle}_t = \frac{1}{n} \sum_{i=0}^{n-1} x_{t-i}
2. Population Standard Deviation
Using the computational formula (running sums of x and x^2):
\sigma_t = \sqrt{\frac{\sum x_i^2}{n} - \left(\frac{\sum x_i}{n}\right)^2}
Note: this is population standard deviation (divide by n), not sample standard deviation (divide by n-1). Bollinger specified population \sigma, and most reference implementations (TA-Lib, TradingView) use this convention.
3. Band Construction
\text{Upper}_t = \text{Middle}_t + k \cdot \sigma_t
\text{Lower}_t = \text{Middle}_t - k \cdot \sigma_t
4. Derived Metrics
BandWidth (normalized volatility measure):
\text{BandWidth}_t = \frac{\text{Upper}_t - \text{Lower}_t}{\text{Middle}_t}
%B (price position oscillator, 0-1 range when inside bands):
\%B_t = \frac{x_t - \text{Lower}_t}{\text{Upper}_t - \text{Lower}_t}
5. Complexity
The circular buffer maintains running sums of x and x^2, enabling O(1) computation of both mean and variance per bar. The square root for \sigma is the most expensive operation.
Mathematical Foundation
Parameters
| Parameter | Description | Default | Constraint |
|---|---|---|---|
period |
Lookback for SMA and standard deviation (n) |
20 | > 0 |
multiplier |
Number of standard deviations (k) |
2.0 | > 0 |
source |
Input price series | close |
Containment Guarantees
Multiplier (k) |
Normal Distribution | Chebyshev (any dist.) |
|---|---|---|
| 1.0 | 68.3% | 0% (trivial bound) |
| 2.0 | 95.4% | 75.0% |
| 3.0 | 99.7% | 88.9% |
Output Interpretation
| Output | Range | Meaning |
|---|---|---|
middle |
price-scale | SMA center line |
upper |
price-scale | Middle + k\sigma |
lower |
price-scale | Middle - k\sigma |
bandwidth |
[0, \infty) |
Normalized volatility; low values signal "squeeze" |
percentB |
typically [0, 1] |
> 1: above upper band; < 0: below lower band |
Performance Profile
Operation Count (Streaming Mode)
BBANDS maintains running sums of x and x^2 via a circular buffer for O(1) mean and variance:
| Operation | Count | Cost (cycles) | Subtotal |
|---|---|---|---|
| MUL (source² for sumSq) | 1 | 3 | 3 |
| SUB (oldest from sum, sumSq) | 2 | 1 | 2 |
| ADD (new to sum, sumSq) | 2 | 1 | 2 |
| DIV (sum / count for mean) | 1 | 15 | 15 |
| MUL (mean² for variance) | 1 | 3 | 3 |
| DIV (sumSq / count) | 1 | 15 | 15 |
| SUB (sumSq/n - mean²) | 1 | 1 | 1 |
| SQRT (σ from variance) | 1 | 20 | 20 |
| MUL (k × σ) | 1 | 3 | 3 |
| ADD/SUB (middle ± dev) | 2 | 1 | 2 |
| Total (hot) | 13 | — | ~66 cycles |
The SQRT dominates. Derived metrics (%B, BandWidth) add 2 DIV + 2 SUB (~34 cycles) when requested.
Batch Mode (SIMD Analysis)
The running-sum maintenance is sequential. The variance and SQRT are per-bar and parallelizable in a batch post-pass:
| Optimization | Benefit |
|---|---|
| Running sum/sumSq | Sequential (sliding window dependency) |
| Variance → SQRT → bands | Vectorizable with Vector.SquareRoot across output |
| %B and BandWidth derivations | Vectorizable (element-wise arithmetic) |
Resources
- Bollinger, J. Bollinger on Bollinger Bands. McGraw-Hill, 2001. (Definitive reference)
- Bollinger, J. "Using Bollinger Bands." Technical Analysis of Stocks & Commodities, 1992.
- Chebyshev, P.L. "Des valeurs moyennes." Journal de Mathématiques Pures et Appliquées, 1867. (Distribution-free containment bound)
- TA-Lib
TA_BBANDSfunction. (Population standard deviation reference implementation)