-
Notifications
You must be signed in to change notification settings - Fork 0
Indicator Cci
Commodity Channel Index — measures how far the current typical price deviates from its rolling mean, in units of mean absolute deviation scaled by Lambert's constant.
| Field | Value |
|---|---|
| Family | Momentum Oscillators |
| Input type | Candle |
| Output type | f64 |
| Output range | unbounded (typically [−200, +200] thanks to the 0.015 factor) |
| Default parameters |
period = 20 (Python) |
| Warmup period |
period (20 for period = 20) |
| Interpretation |
> +100 overbought, < −100 oversold (Lambert) |
For each candle, compute the typical price TP = (high + low + close) / 3,
then over the rolling period-bar window:
SMA_TP_t = (TP_{t-period+1} + … + TP_t) / period
MAD_t = (1 / period) · Σ |TP_i − SMA_TP_t| for i = t-period+1 … t
CCI_t = (TP_t − SMA_TP_t) / (factor · MAD_t)
The default factor is Lambert's 0.015, chosen empirically so that
roughly 70–80 % of values fall inside [−100, +100]. The implementation
exposes the factor through Cci::with_factor(period, factor) if you want
to retune it for an asset with very different volatility characteristics.
When MAD == 0 (a perfectly flat window), the implementation returns 0
rather than dividing by zero.
| Name | Type | Default (Python) | Valid range | Description |
|---|---|---|---|---|
period |
usize |
20 |
>= 1 |
Rolling window length for both the SMA of typical price and the MAD. |
factor |
f64 |
0.015 (Cci::new) |
> 0, finite |
Lambert's scaling constant; configurable via Cci::with_factor. |
Cci::new(0) returns Error::PeriodZero. Cci::with_factor(_, factor)
returns Error::NonPositiveMultiplier when factor <= 0 or non-finite.
From impl Indicator for Cci:
type Input = Candle;
type Output = f64;
fn update(&mut self, candle: Candle) -> Option<f64>;Python's CCI.batch(high, low, close) returns a 1-D float64 np.ndarray
with NaN during warmup. Node's CCI.batch(high, low, close) returns a
flat number[] (also NaN during warmup); the Node binding does not
expose a streaming update() (bindings/node/index.d.ts lists only
constructor and batch).
warmup_period() returns exactly period. CCI does not consume diffs —
it only needs period typical-price samples to populate its rolling
window before it can compute an SMA and MAD. In streaming terms, calls
1..period return None; the period-th call returns the first value.
-
Flat input. Every
TPis the SMA, soMAD == 0and the implementation returns0.0(testflat_candles_yield_zero). This avoids the divide-by-zero that would otherwise produceNaN/±∞. -
Custom factor.
Cci::with_factor(period, factor)lets you replace Lambert's0.015. Picking a smaller factor widens the typical range of CCI values; picking a larger one compresses them. -
Reset.
reset()clears the rolling window and the running sum, returning the indicator to the freshly-constructed state.
use wickra::{BatchExt, Candle, Cci, Indicator};
let candles: Vec<Candle> = (0..25)
.map(|i| {
let m = 50.0 + i as f64;
Candle::new(m, m + 1.0, m - 1.0, m, 1.0, 0).unwrap()
})
.collect();
let mut cci = Cci::new(20)?;
let out = cci.batch(&candles);
println!("row 19 = {}", out[19].unwrap());
println!("row 24 = {}", out[24].unwrap());
# Ok::<(), wickra::Error>(())Verified output:
row 19 = 126.66666666666667
row 24 = 126.66666666666667
import numpy as np
import wickra as ta
i = np.arange(25, dtype=float)
m = 50.0 + i
high = m + 1.0
low = m - 1.0
close = m
cci = ta.CCI(20)
out = cci.batch(high, low, close)
print('row 19:', out[19])
print('row 24:', out[24])Verified output:
row 19: 126.66666666666667
row 24: 126.66666666666667
const wickra = require('wickra');
const n = 25;
const high = [], low = [], close = [];
for (let i = 0; i < n; i++) {
const m = 50 + i;
high.push(m + 1);
low.push(m - 1);
close.push(m);
}
const cci = new wickra.CCI(20);
const out = cci.batch(high, low, close);
console.log('row 19:', out[19]);
console.log('row 24:', out[24]);Verified output:
row 19: 126.66666666666667
row 24: 126.66666666666667
-
±100 threshold. Lambert's published convention is to treat values
above
+100as overbought and below−100as oversold. The choice of0.015for the divisor is what makes the threshold meaningful; changing the factor changes the threshold. -
Zero-line cross.
CCIcrossing zero says the typical price has moved through itsperiod-bar mean — sometimes used as a trend-direction filter. - Divergence. As with RSI/Stochastic, a price making a new high while CCI makes a lower high is a classic bearish divergence.
-
CCI is unbounded. Unlike RSI or Stochastic, CCI can spike well
outside
±100in volatile markets. Threshold-based rules should be paired with a maximum-absolute-value guard, or you will mis-classify legitimate breakouts as "extreme overbought". -
The 0.015 factor is empirical, not derived. It was chosen by
Lambert in 1980 for commodity futures markets. Modern equities and
crypto have wider distributions; if your
|CCI|distribution sits almost entirely outside±100, retune viaCci::with_factorrather than rewriting downstream thresholds.
- Donald Lambert, "Commodity Channel Index: Tools for Trading Cyclical
Trends", Commodities Magazine, October 1980 — the original
publication, including the empirical choice of
0.015.
- Indicator: Rsi — bounded sibling for comparison.
- Indicator: WilliamsR — another candle-input oscillator, range-based rather than deviation-based.
- Indicator: Mfi — volume-weighted RSI; useful as a confirmation alongside CCI.
-
Warmup Periods —
period(no off-by-one).
Wickra on GitHub · crates.io · PyPI · npm · License: PolyForm-Noncommercial-1.0.0
- Alligator
- Alma
- Dema
- Ema
- Evwma
- Frama
- Hma
- Jma
- Kama
- McGinleyDynamic
- Sma
- Smma
- T3
- Tema
- Trima
- Vidya
- Vwma
- Wma
- Zlema
- AwesomeOscillator
- Cci
- Cmo
- ConnorsRSI
- Inertia
- Kst
- LaguerreRSI
- Mfi
- Mom
- Pgo
- Pmo
- Roc
- Rsi
- Rvi
- Smi
- Stochastic
- StochRsi
- Tsi
- UltimateOscillator
- WilliamsR
- Adx
- Adxr
- Aroon
- AroonOscillator
- ChoppinessIndex
- MacdIndicator
- MassIndex
- Rwi
- Tii
- Trix
- VerticalHorizontalFilter
- Vortex
- WaveTrend
- Atr
- BollingerBands
- BollingerBandwidth
- ChaikinVolatility
- Donchian
- GarmanKlassVolatility
- HistoricalVolatility
- Keltner
- Natr
- ParkinsonVolatility
- PercentB
- RogersSatchellVolatility
- RviVolatility
- StdDev
- TrueRange
- UlcerIndex
- YangZhangVolatility