Edgoro
Momentum indicator

CCI indicator: formula, ±100 levels and Pine Script v6 code

How the Commodity Channel Index measures distance from an average in mean-deviation units, how traders read ±100, settings, and a free CCI script.

What it measures

The Commodity Channel Index measures how far the typical price is from its moving average, scaled by how far it usually strays. A reading of +100 means price is unusually far above its average; −100, unusually far below. There's no fixed upper or lower limit.

Donald Lambert introduced it in 1980 for cyclical commodity markets, and it is now used on every asset class. Despite the name, it's a momentum oscillator, not a channel drawn on the chart.

The formula in words

  1. Typical price = (high + low + close) ÷ 3.
  2. Take a 20-period simple moving average of the typical price.
  3. Mean deviation: the average of the absolute distances between each of the last 20 typical prices and that average.
  4. CCI = (typical price − its average) ÷ (0.015 × mean deviation).

Lambert chose the 0.015 constant so that most readings, roughly 70 to 80 percent, would fall between −100 and +100. That makes ±100 a statistical boundary rather than overbought or oversold in the RSI sense. Pine Script's ta.cci(source, length) follows this formula.

How traders read it

  • Breaks beyond ±100. Lambert's original use was trend-following: a move above +100 marks unusual strength and a possible new trend, and the trade ends when CCI falls back below +100.
  • Returns inside ±100. Range traders do the opposite: CCI dropping below −100 and then crossing back above it is read as a stretched move snapping back. The script lets you mark either event.
  • The zero line. CCI above zero means the typical price is above its average. Some traders use zero crosses as a slower trend filter.
  • Extremes. Readings beyond ±200 are rare on most symbols and are read as exhaustion or as a very strong trend, depending on context.
  • Divergence. As with other oscillators, a new price high with a lower CCI high describes slowing momentum and needs a separate trigger.

Common settings

SettingTypical valueNotes
Length20Lambert's default; 14 is also common.
SourceTypical price (hlc3)Close-only versions exist and read slightly differently.
Levels±100±200 for extremes.

Shorter lengths push CCI past ±100 more often. If you change the length, look at how often the new version crosses the levels on your symbol before keeping them.

Pine Script v6 code

The complete, self-contained script is below. Copy it into a new indicator in TradingView's Pine Editor, or download the .pine file.

Pine Script v6
//@version=6
indicator("Commodity Channel Index (CCI)", shorttitle = "CCI", format = format.price, precision = 2)

src     = input.source(hlc3, "Source", group = "Calculation")
len     = input.int(20, "Length", minval = 2, group = "Calculation")
upper   = input.int(100, "Upper level", minval = 0, group = "Levels")
lower   = input.int(-100, "Lower level", maxval = 0, group = "Levels")
extreme = input.int(200, "Extreme level (+/-)", minval = 0, group = "Levels")
markMode = input.string("Returns inside the levels", "Mark", options = ["Returns inside the levels", "Breaks beyond the levels"], group = "Signals")

cci = ta.cci(src, len)

breakUp    = ta.crossover(cci, upper)
breakDown  = ta.crossunder(cci, lower)
backBelow  = ta.crossunder(cci, upper)
backAbove  = ta.crossover(cci, lower)
markReturn = markMode == "Returns inside the levels"

cciColor = cci > upper ? color.new(color.teal, 0) : cci < lower ? color.new(color.red, 0) : color.new(color.blue, 0)
plot(cci, "CCI", color = cciColor, linewidth = 2)
upLine = hline(upper, "Upper", color = color.gray, linestyle = hline.style_dashed)
hline(0, "Zero", color = color.new(color.gray, 60), linestyle = hline.style_dotted)
loLine = hline(lower, "Lower", color = color.gray, linestyle = hline.style_dashed)
hline(extreme, "Upper extreme", color = color.new(color.gray, 70), linestyle = hline.style_dotted)
hline(-extreme, "Lower extreme", color = color.new(color.gray, 70), linestyle = hline.style_dotted)
fill(upLine, loLine, color = color.new(color.blue, 93), title = "Range")

plotshape(markReturn ? backAbove : breakUp, "Bullish mark", shape.triangleup, location.bottom, color.new(color.teal, 0), size = size.tiny)
plotshape(markReturn ? backBelow : breakDown, "Bearish mark", shape.triangledown, location.top, color.new(color.red, 0), size = size.tiny)

alertcondition(breakUp, "CCI above upper level", "CCI crossed above the upper level on {{ticker}} ({{interval}})")
alertcondition(breakDown, "CCI below lower level", "CCI crossed below the lower level on {{ticker}} ({{interval}})")
alertcondition(backAbove, "CCI back above lower level", "CCI crossed back above the lower level on {{ticker}} ({{interval}})")
alertcondition(backBelow, "CCI back below upper level", "CCI crossed back below the upper level on {{ticker}} ({{interval}})")

CCI is plotted in its own pane, green above the upper level and red below the lower one, with dotted lines at ±200. A setting chooses which events get triangles: returns inside the levels (mean reversion) or breaks beyond the levels (Lambert's trend-following reading).

All four events, both breaks and both returns, are available as alert conditions whichever you choose to mark. Set them to Once per bar close.

Add it to your chart

  1. Open any chart on TradingView and open the Pine Editor.
  2. Create a new indicator, delete the template code and paste the script.
  3. Click Save, then Add to chart. Change lengths and levels from the indicator's settings.

Stuck on an error? See how to add a Pine Script indicator to TradingView.

Pitfalls

  • Treating ±100 as overbought and oversold. CCI has no ceiling, and in trends it can stay beyond +100 for a long time. Decide whether you read the levels as breakouts or as stretched moves.
  • Mixing both readings. Buying breaks above +100 and selling returns below +100 on the same symbol is one event read two ways. Pick one approach and test it.
  • Comparing values across lengths. A 14-period CCI swings far more than a 50-period one; the same level means different things.
  • Live-bar crosses. The typical price changes until the bar closes.

The script is an educational example: test it on your own markets before relying on it. Indicators describe the past; they don't predict the future. Trading involves substantial risk of loss and is not suitable for every investor. Edgoro is a software tool, not a broker or financial adviser: nothing it produces is investment advice, and past or backtested performance does not guarantee future results.

Make it yours with Edgoro

Describe the change in plain English and Edgoro writes the Pine Script v6 for you, ready to paste. For example:

“Plot CCI(20) with ±100 levels and alert when CCI crosses back above -100 while the close is above the 200 EMA, once per bar close.”

Build your CCI indicator