Commodity Channel Index (CCI)
period = 14 (2–200) Overview
The Commodity Channel Index (CCI) normalizes the distance between the current typical price (high + low + close / 3) and its moving average by the mean absolute deviation. This produces an oscillator where ±100 traditionally marks statistically unusual conditions, empowering traders to isolate overbought, oversold, and emerging divergence setups.
VectorTA's implementation embraces that statistical foundation with SIMD-aware kernels, candle integration, and streaming support. You can sweep parameter regimes, feed real-time typical prices, or plug into Python and WASM bindings while relying on consistent output semantics across every interface.
Implementation Examples
Compute CCI from candles or typical-price slices with minimal setup:
use vectorta::indicators::cci::{cci, CciInput, CciParams};
use vectorta::utilities::data_loader::Candles;
// Use candles with hlc3 typical price and default period = 14
let candles: Candles = load_workspace_candles()?;
let candle_input = CciInput::with_default_candles(&candles);
let candle_output = cci(&candle_input)?;
for (idx, value) in candle_output.values.iter().enumerate() {
println!("CCI[{idx}] = {value:.2}");
}
// Or feed pre-computed typical price values directly
fn compute_typical_price(candles: &Candles) -> Vec<f64> {
candles
.high
.iter()
.zip(&candles.low)
.zip(&candles.close)
.map(|((h, l), c)| (h + l + c) / 3.0)
.collect()
}
let typical_price = compute_typical_price(&candles);
let params = CciParams { period: Some(20) };
let slice_input = CciInput::from_slice(&typical_price, params);
let slice_output = cci(&slice_input)?; API Reference
Input Methods ▾
// From candles using hlc3 typical price
CciInput::from_candles(&Candles, &str, CciParams) -> CciInput
// From pre-computed typical price slice
CciInput::from_slice(&[f64], CciParams) -> CciInput
// Shortcut: candles + default params (period = 14, hlc3 source)
CciInput::with_default_candles(&Candles) -> CciInput Parameter Structure ▾
#[derive(Default, Clone)]
pub struct CciParams {
pub period: Option<usize>, // defaults to Some(14)
} Output Structure ▾
pub struct CciOutput {
pub values: Vec<f64>, // CCI per bar aligned with the source data
} Builder Utilities ▾
use vectorta::indicators::cci::CciBuilder;
use vectorta::utilities::enums::Kernel;
let builder = CciBuilder::new()
.period(25)
.kernel(Kernel::Auto);
let candle_values = builder.clone().apply(&candles)?;
let slice_values = builder.clone().apply_slice(&typical_price)?;
let mut stream = builder.into_stream()?; Streaming API ▾
use vectorta::indicators::cci::{CciParams, CciStream};
let mut stream = CciStream::try_new(CciParams::default())?;
while let Some(typical) = next_typical_price() {
if let Some(value) = stream.update(typical) {
push_indicator_value(value);
}
} Batch Operations ▾
use vectorta::indicators::cci::{CciBatchBuilder, CciParams};
let batch = CciBatchBuilder::new()
.period_range(5, 45, 5)
.apply_slice(&typical_price)?;
if let Some(row) = batch.values_for(&CciParams { period: Some(30) }) {
score_strategy(row);
} Error Handling ▾
use vectorta::indicators::cci::{cci, CciError, CciInput, CciParams};
let params = CciParams { period: Some(0) };
let input = CciInput::from_slice(&[], params);
match cci(&input) {
Ok(output) => consume(output),
Err(CciError::EmptyInputData) => log::error!("no data provided"),
Err(CciError::InvalidPeriod { period, data_len }) =>
log::warn!("period {period} exceeds data length {data_len}"),
Err(CciError::AllValuesNaN) => log::error!("all values were NaN"),
Err(CciError::NotEnoughValidData { needed, valid }) =>
log::warn!("need {needed} clean rows, only {valid} available"),
} Python Bindings
Basic Usage ▾
Operate on NumPy arrays of typical price values and optionally pin the kernel:
import numpy as np
from vectorta import cci
typical_price = np.asarray([101.4, 102.1, 100.8, 103.6, 104.2], dtype=np.float64)
values = cci(typical_price, period=20)
print("CCI", values)
# Force scalar execution when validating results against references
values_scalar = cci(typical_price, period=20, kernel="scalar") Streaming Updates ▾
Maintain a rolling CCI value by feeding live typical prices:
from vectorta import CciStream
stream = CciStream(period=20)
for candle in ohlc_generator():
typical = (candle.high + candle.low + candle.close) / 3.0
value = stream.update(typical)
if value is not None:
handle_stream_value(candle.timestamp, value) Batch Sweeps ▾
Sweep period ranges and analyze the resulting grid inside Python:
from vectorta import cci_batch
result = cci_batch(
typical_price,
period_range=(10, 40, 5),
kernel="auto",
)
values = result["values"] # reshaped to [rows, len(typical_price)]
periods = result["periods"] # vector of period lengths CUDA Acceleration ▾
CUDA-backed Python bindings for CCI are planned. The API will mirror other CUDA-enabled indicators once released.
# Coming soon: GPU-accelerated CCI sweeps
# from vectorta import cci_cuda_batch
#
# gpu_result = cci_cuda_batch(
# typical_price_matrix,
# period_range=(10, 40, 1),
# device_id=0,
# ) Return Structure ▾
# cci(...)
np.ndarray # shape: (len(typical_price),)
# cci_batch(...)
{
"values": np.ndarray, # shape: (rows, len(typical_price))
"periods": np.ndarray, # period length per row
} JavaScript / WASM Bindings
Quick Usage ▾
Run CCI inside the browser or Node using Float64Array inputs:
import { cci_js } from 'vectorta-wasm';
const typical = new Float64Array([101.4, 102.1, 100.8, 103.6, 104.2]);
const values = cci_js(typical, 20);
console.log('CCI values', Array.from(values)); Memory-Efficient Operations ▾
Reuse WASM memory to avoid repeated allocations during tight loops:
import { cci_alloc, cci_free, cci_into, memory } from 'vectorta-wasm';
const len = typical.length;
const inPtr = cci_alloc(len);
const outPtr = cci_alloc(len);
new Float64Array(memory.buffer, inPtr, len).set(typical);
cci_into(inPtr, outPtr, len, 20);
const cciValues = new Float64Array(memory.buffer, outPtr, len).slice();
cci_free(inPtr, len);
cci_free(outPtr, len); Batch & Metadata ▾
Sweep period ranges and inspect configuration metadata from JavaScript:
import { cci_batch_js, cci_batch_metadata_js, cci_batch as cci_batch_unified } from 'vectorta-wasm';
const typical = new Float64Array(loadTypicalPrices());
const metadata = cci_batch_metadata_js(10, 40, 5); // returns [10, 15, ...]
const flattened = cci_batch_js(typical, 10, 40, 5);
const block = typical.length;
const firstRow = flattened.slice(0, block);
const unified = cci_batch_unified(typical, {
period_range: [10, 40, 5],
});
console.log(unified.rows, unified.cols, unified.combos.length); Performance Analysis
Related Indicators
Acceleration Oscillator
Technical analysis indicator
Awesome Oscillator
Technical analysis indicator
Absolute Price Oscillator
Technical analysis indicator
Center of Gravity
Technical analysis indicator
Chande Momentum Oscillator
Technical analysis indicator
Chande Momentum Oscillator
Technical analysis indicator