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
- Typical price = (high + low + close) ÷ 3.
- Take a 20-period simple moving average of the typical price.
- Mean deviation: the average of the absolute distances between each of the last 20 typical prices and that average.
- 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
| Setting | Typical value | Notes |
|---|---|---|
| Length | 20 | Lambert's default; 14 is also common. |
| Source | Typical 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.
//@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
- Open any chart on TradingView and open the Pine Editor.
- Create a new indicator, delete the template code and paste the script.
- 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.
Related reading
- Pine Script alerts: alertcondition() vs alert(), messages, webhooks and frequency
- 8 backtesting mistakes that make a strategy look better than it is
- Risk/Reward Calculator (free tool)
- Expectancy & Win-Rate Calculator (free tool)
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.