CCI Indicator: Formula, ±100 Signals, and What Tests Reveal

Twenty-period and two-period CCI values on the same price history, showing how the calculation window changes the scale.

Key takeaways

  • CCI divides a price's distance from its rolling average by mean absolute deviation and a 0.015 scale constant; its value is not a percentage price change.
  • For the standard same-window calculation, absolute CCI cannot exceed N divided by 0.03. A two-period CCI stays near ±66.67 when its prices differ, and a three-period CCI cannot strictly exceed ±100.
  • At a 20-period lookback, about 60–62% of checked values lay between −100 and +100 in the historical samples. The scaling constant does not guarantee a fixed containment rate.

The Commodity Channel Index (CCI) measures how far a price sits from its recent average, relative to the spread of the same prices. Traders often watch +100 and −100 for strength or extreme conditions.

Our 144,936 configuration evaluations explore lookbacks, thresholds, and three entry rules. The calculation explains an important boundary: with only two periods, CCI cannot reach +100 at all. At twenty periods, the same threshold has a very different meaning.

What does the CCI indicator measure?

A positive CCI puts the latest source price above its rolling average. A negative CCI puts it below. Larger magnitudes mean a greater distance relative to the window’s mean absolute deviation.

Despite its name, CCI can be calculated for markets beyond commodities. A twenty-period example often uses typical price, the average of a candle’s high, low, and close. Platforms can offer other sources.

TradingView’s CCI guide explains the conventional calculation and the use of extreme readings for either trend strength or potential reversal. Those interpretations need separate trading rules.

How to calculate CCI

For a window of N source prices:

Typical price = (high + low + close) / 3
Mean          = average of the N typical prices
Mean deviation = average absolute distance from that mean

CCI = (latest typical price − mean)
      ÷ (0.015 × mean deviation)

The deviation uses each price’s distance from the same current window mean. It is not the average of historical one-bar changes or a standard deviation.

For two typical prices of 100 and 110, the mean is 105 and the mean absolute deviation is 5. CCI is 5 ÷ (0.015 × 5), or about 66.67.

Use 100 and 100.10 instead: the mean and deviation both shrink, leaving CCI at the same 66.67. The oscillator normalizes the move; 66.67 does not mean a 66.67% price increase.

Why two-period CCI cannot reach +100

With two unequal source prices, the latest value is always one mean-deviation unit above or below the mean. Standard CCI is therefore approximately +66.67 or −66.67. If the prices are equal, mean deviation is zero and the ratio needs a defined missing-value convention.

There is a more general limit when the latest observation belongs to the same calculation window:

Maximum absolute CCI = N / 0.03

The mean-centered deviations sum to zero. Their positive and negative totals must balance, so the total absolute deviation is at least twice the absolute newest deviation. Dividing by N and applying the 0.015 scale gives that bound.

Constructed teaching example The same latest price can reach different CCI limits

The latest price is110 in every window. Its maximum normalized deviation grows with the number of observations.

The value table below is available without JavaScript.

Chart data
Data and calculation details
Source: Constructed mean-deviation calculations. For each N, use N−1 typical prices of100 and a newest typical price110. All points are separate windows, not market observations. Mean deviation uses the same window including newest price. Constructed values illustrate the calculation; they are not market history or backtest results.
Accessible value table (19 observations)
ObservationCCI of the same newest price · CCI
266.667
3100.000
4133.333
5166.667
6200.000
7233.333
8266.667
9300.000
10333.333
11366.667
12400.000
13433.333
14466.667
15500.000
16533.333
17566.667
18600.000
19633.333
20666.667

Every point above uses older prices of 100 and a newest price of 110, changing only the window length. The construction reaches the bound. At two observations it is 66.67; at three it is exactly 100. A rule requiring CCI strictly greater than 100 cannot qualify with three or fewer observations.

CCI is commonly called an unbounded oscillator because it has no fixed 0–100 range like RSI. That description does not remove the lookback-dependent limit of this particular same-window formula.

How the window changes a historical reading

The boundary is useful beyond a constructed example. A shorter CCI is not simply a quicker version with an otherwise identical scale.

Historical indicator values One price history, different normalization windows

A selected high-CCI episode. A two-period calculation stays at approximately ±66.67 when its two source prices differ.

The value table below is available without JavaScript.

Chart data
Data and calculation details
Source: Exact TrainBard-returned historical candles. Selected later-window two-hour sample; indicator values calculated locally from the exact returned OHLCV. Values are aligned to candle-open UTC timestamps and known at candle close. No execution markers or inferred fills.
Accessible value table (61 observations)
ObservationClosing price · CloseCCI on the same typical prices · 20 periodsCCI on the same typical prices · 2 periods
2025-02-28T04:00:00Z79,973.790-239.962-66.667
2025-02-28T06:00:00Z79,204.590-213.971-66.667
2025-02-28T08:00:00Z80,343.110-162.94666.667
2025-02-28T10:00:00Z80,513.380-118.46766.667
2025-02-28T12:00:00Z81,512.420-78.95066.667
2025-02-28T14:00:00Z84,005.050-11.86166.667
2025-02-28T16:00:00Z83,605.12015.58966.667
2025-02-28T18:00:00Z84,449.99025.79266.667
2025-02-28T20:00:00Z84,258.37027.360-66.667
2025-02-28T22:00:00Z84,349.94033.50766.667
2025-03-01T00:00:00Z84,656.93044.69466.667
2025-03-01T02:00:00Z85,330.84074.05966.667
2025-03-01T04:00:00Z85,588.190101.67666.667
2025-03-01T06:00:00Z84,740.15074.214-66.667
2025-03-01T08:00:00Z85,380.00079.23366.667
2025-03-01T10:00:00Z84,632.79062.552-66.667
2025-03-01T12:00:00Z84,532.24052.317-66.667
2025-03-01T14:00:00Z84,800.00055.83366.667
2025-03-01T16:00:00Z85,214.70064.23066.667
2025-03-01T18:00:00Z85,485.41070.63066.667
2025-03-01T20:00:00Z86,076.86087.23166.667
2025-03-01T22:00:00Z86,064.53098.51566.667
2025-03-02T00:00:00Z86,354.930112.38466.667
2025-03-02T02:00:00Z85,873.070101.271-66.667
2025-03-02T04:00:00Z85,957.51086.366-66.667
2025-03-02T06:00:00Z86,232.420119.12066.667
2025-03-02T08:00:00Z85,901.30076.017-66.667
2025-03-02T10:00:00Z86,105.89079.38766.667
2025-03-02T12:00:00Z85,710.81042.208-66.667
2025-03-02T14:00:00Z87,427.990178.61166.667
2025-03-02T16:00:00Z94,093.750512.42966.667
2025-03-02T18:00:00Z93,522.000348.37866.667
2025-03-02T20:00:00Z94,298.000248.64166.667
2025-03-02T22:00:00Z94,270.000188.77466.667
2025-03-03T00:00:00Z93,084.640131.417-66.667
2025-03-03T02:00:00Z92,709.980100.582-66.667
2025-03-03T04:00:00Z93,344.00090.73866.667
2025-03-03T06:00:00Z92,363.58066.044-66.667
2025-03-03T08:00:00Z91,847.76050.115-66.667
2025-03-03T10:00:00Z92,739.99055.49366.667
2025-03-03T12:00:00Z93,586.83066.54666.667
2025-03-03T14:00:00Z90,035.37016.612-66.667
2025-03-03T16:00:00Z90,300.010-0.742-66.667
2025-03-03T18:00:00Z85,606.000-74.086-66.667
2025-03-03T20:00:00Z85,374.330-108.368-66.667
2025-03-03T22:00:00Z86,220.610-96.76266.667
2025-03-04T00:00:00Z83,380.550-134.094-66.667
2025-03-04T02:00:00Z83,983.720-138.403-66.667
2025-03-04T04:00:00Z84,273.990-123.45066.667
2025-03-04T06:00:00Z83,186.400-121.288-66.667
2025-03-04T08:00:00Z83,748.000-103.19266.667
2025-03-04T10:00:00Z83,937.940-86.93566.667
2025-03-04T12:00:00Z82,804.000-91.783-66.667
2025-03-04T14:00:00Z82,985.060-81.93866.667
2025-03-04T16:00:00Z85,443.890-56.73866.667
2025-03-04T18:00:00Z88,206.1901.38866.667
2025-03-04T20:00:00Z87,517.49016.20866.667
2025-03-04T22:00:00Z87,281.98017.751-66.667
2025-03-05T00:00:00Z87,643.11020.449-66.667
2025-03-05T02:00:00Z86,843.40028.128-66.667
2025-03-05T04:00:00Z87,145.98040.438-66.667

The two-period curve stays near ±66.67 when its source values differ, while the twenty-period calculation can move beyond ±100. These are locally calculated indicator values, not backtest execution markers.

A high reading can persist as price keeps trending. A falling CCI can also result from the window average and deviation changing. It does not automatically mean the price itself fell.

Does the 0.015 constant keep 70–80% of values inside ±100?

That is a familiar description of the scaling convention, including in Fidelity’s CCI guide. It is not a distribution-free guarantee.

At a twenty-period lookback, about 60–62% of the checked historical values fell between −100 and +100 across our samples. Those observations include trending and ranging periods. The measured share belongs to those data and that formula.

Changing the 0.015 constant just rescales CCI. If a constant is multiplied by two, the same values are halved; halving the numerical threshold preserves the original inequality. Treating those paired changes as separate evidence would count the same decision twice.

Strength, fade, and recovery are different rules

The tests use a shared zero-line exit and three entries:

  • Strength: buy while CCI is strictly above the positive threshold; exit below zero.
  • Fade: buy while CCI is strictly below the negative threshold; exit at or above zero.
  • Recovery: first require a strict below-threshold observation, then buy on recovery above it while still below zero; exit at or above zero.
Recorded backtest metrics A fixed ±100 threshold behaves differently as lookback changes

One fixed rule and historical sample, changing only the displayed setting and line comparison. Each buy/sell is one execution.

The value table below is available without JavaScript.

Chart data
Data and calculation details
Source: Completed TrainBard fixed small-notional controls. Recorded historical execution counts; omitted-zero counts appear only after full UI reconciliation. Each entry requests100 quote units at signal close via qty=100/close; next-open notional can differ. Main99%-equity sweeps are separate. Exact source/frame/row mapping is in the evidence.
Accessible value table (99 observations)
ObservationExecutions by lookback (bars) · StrengthExecutions by lookback (bars) · FadeExecutions by lookback (bars) · Strict recovery
20.0000.0000.000
30.0000.0000.000
42,388.0002,467.0002,066.000
51,988.0002,067.0001,746.000
61,746.0001,792.0001,526.000
71,564.0001,604.0001,364.000
81,433.0001,422.0001,244.000
91,305.0001,294.0001,146.000
101,209.0001,192.0001,084.000
111,099.0001,108.0001,024.000
121,027.0001,054.000972.000
13949.000996.000912.000
14883.000938.000866.000
15861.000886.000812.000
16812.000810.000748.000
17772.000760.000704.000
18728.000730.000686.000
19698.000710.000664.000
20674.000674.000624.000
21652.000648.000596.000
22630.000620.000570.000
23612.000596.000556.000
24596.000574.000532.000
25576.000562.000522.000
26566.000546.000512.000
27540.000520.000486.000
28520.000492.000458.000
29506.000474.000446.000
30496.000468.000440.000
31474.000452.000428.000
32458.000446.000420.000
33448.000439.000415.000
34434.000423.000399.000
35418.000415.000395.000
36402.000411.000391.000
37382.000399.000379.000
38374.000389.000373.000
39374.000383.000367.000
40362.000381.000365.000
41356.000379.000363.000
42342.000373.000355.000
43334.000367.000351.000
44328.000361.000345.000
45322.000351.000335.000
46320.000349.000335.000
47314.000343.000331.000
48312.000335.000319.000
49310.000325.000313.000
50302.000317.000307.000
51292.000315.000309.000
52290.000319.000313.000
53282.000309.000305.000
54280.000307.000303.000
55272.000301.000295.000
56266.000299.000293.000
57260.000297.000291.000
58262.000293.000287.000
59258.000291.000283.000
60252.000291.000283.000
61240.000285.000277.000
62238.000289.000283.000
63232.000283.000279.000
64236.000277.000273.000
65232.000271.000267.000
66230.000269.000265.000
67228.000267.000263.000
68228.000263.000259.000
69224.000257.000253.000
70218.000255.000251.000
71218.000249.000245.000
72218.000241.000237.000
73220.000241.000237.000
74216.000243.000239.000
75214.000243.000239.000
76216.000241.000237.000
77214.000233.000229.000
78208.000231.000227.000
79208.000225.000223.000
80204.000217.000217.000
81200.000213.000213.000
82190.000207.000207.000
83190.000205.000205.000
84184.000205.000205.000
85182.000209.000209.000
86178.000205.000205.000
87176.000205.000205.000
88172.000203.000203.000
89170.000203.000203.000
90162.000201.000201.000
91160.000199.000199.000
92158.000199.000199.000
93158.000197.000197.000
94158.000197.000197.000
95154.000193.000193.000
96152.000187.000187.000
97154.000183.000183.000
98148.000179.000179.000
99150.000177.000177.000
100152.000177.000177.000

In the displayed comparison, the strength rule recorded 2,388 executions at four periods, 674 at twenty, and 152 at one hundred. Neighboring lengths also produced occasional small increases in activity. Length changes the mean and mean deviation together, so it is more than a speed adjustment.

The threshold stays fixed in these additional tests using small positions. The three rules respond to different events, so their execution counts can separate even on the same indicator values. A recovery that jumps directly above zero is rejected because its exit already has priority.

The script also disables entries at thresholds at or beyond the exact bound. Those settings are valid cash outcomes by construction. Their lack of trades is not fresh empirical proof of the mathematics.

The full evidence preserves return and drawdown summaries as well as activity. The chart teaches what each rule selects; it does not identify a universally profitable CCI setting.

CCI versus RSI and useful settings

RSI summarizes smoothed upward and downward price changes on a fixed 0–100 scale. CCI compares a price level with a rolling mean and mean absolute deviation. A reading of 70 on one is not equivalent to 70 on the other.

Choose lookback and threshold together. Shortening the window can alter the available scale, the rate of extreme readings, and how often a recovery can happen. A conventional twenty-period setting is a starting point for a defined comparison, not a reason to assume ±100 has the same behavior everywhere.

Reproduce the comparison

The script defaults to twenty-period typical-price CCI and a +100 strength entry. Switch the rule to fade or strict recovery while keeping the same indicator and threshold.

Pine Script v6
Open editor

//@version=6
strategy("CCI Lab: thresholds, continuation and recovery", overlay=false, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=99, process_orders_on_close=false)

cci_length = input.int(20, "CCI lookback", minval=2, maxval=100)
threshold = input.int(100, "Absolute entry threshold", minval=25, maxval=325)
rule_mode = input.int(0, "Rule: 0 strength, 1 fade, 2 recovery", minval=0, maxval=2)

cci_value = ta.cci(hlc3, cci_length)
recovery = ta.crossover(cci_value, -threshold) and cci_value[1] < -threshold
// The newest observation belongs to the same mean-deviation window.
// A strict excursion cannot exceed the bound N / 0.03.
feasible = threshold < cci_length / 0.03 - 0.000001
ready = bar_index >= 500 and not na(cci_value) and feasible
enter_long = ready and (rule_mode == 0 ? cci_value > threshold : rule_mode == 1 ? cci_value < -threshold : recovery)
exit_long = ready and (rule_mode == 0 ? cci_value < 0 : cci_value >= 0)

plot(cci_value, "CCI", color=color.blue)
plot(threshold, "Upper threshold", color=color.orange)
plot(-threshold, "Lower threshold", color=color.green)
plot(0, "Mean", color=color.gray)
if exit_long and strategy.position_size > 0
    strategy.close("Long")
if enter_long and not exit_long and strategy.position_size == 0
    strategy.entry("Long", strategy.long)

Markets, settings, accounting, and reproducibility

The historical frame covers Binance Spot BTCUSDT and ETHUSDT, two-hour and four-hour candles, and 2021-01-01–2023-12-31 and 2024-01-01–2025-12-31. All eight frames use the same frozen settings; later results are retrospective replication, not a blind holdout.

The two BTCUSDT two-hour main frames were run through TrainBard’s MCP endpoint. Remaining main frames and the activity controls were run through its web interface with the same frozen scripts. Completed UI totals, exact parameter membership, settings snapshots, and original exports are reconciled before inclusion. Guarded cash configurations stay in the accepted denominator. Omitted zero-trade tuples provide execution counts of zero; absent return, drawdown, fee, and win-rate cells are not fabricated. Interface bridge checks are counted separately. The main study contains 140,701 observed metric rows and 4,235 valid UI-omitted zero tuples. Return and drawdown summaries use the observed rows only; cash-row coverage differs by interface.

Each frame has 18,117 configurations: every integer lookback from 2 through 100 (99), thresholds 25 through 325 in steps of 5 (61), and three entry rules. The main total is 144,936 accepted evaluations. Separate preparatory diagnostics are excluded. 2,376 additional fixed small-notional evaluations repeat the complete activity curves across the same eight frames. In those controls, each entry requests qty = 100 / signal close; actual next-open fill notional can differ. Their smaller requested size separates the displayed activity comparison from the broad sweeps’ equity-funding behavior. The exact activity-control script is retained separately; these confirmations are excluded from the main count. The control total contains 2,328 observed metric rows and 48 reconciled UI-omitted zero tuples. A local full-precision signal-state check matched 2,374 of the 2,376 control counts. Two four-period fade/recovery cases differed by one entry/exit pair; rounding the OHLC inputs to float32 reproduced their recorded counts. That is consistent with input precision affecting a strict comparison, without proving the platform’s internal cause. Published activity uses the recorded exports throughout.

The calculation is ta.cci(hlc3, length). All modes require the threshold to be strictly below length / 0.03, with a 0.000001 numerical margin. This prevents floating-point boundary comparisons from creating strict excursions outside the mathematical bound. It deliberately excludes boundary-only recovery rules: the final recovery requires the preceding value to be strictly below minus the threshold as well as a current crossover. Standard crossover definitions can accept equality at the preceding value; those are a different rule. The 696 guarded settings per frame, or 5,568 across the study, remain valid cash configurations in the main denominator. The accepted main results contain 5,646 zero-execution settings in total.

Every test starts at 10,000 USDT, stays in cash for 500 startup bars, requests 99% equity sizing, and uses 0.1% combined fee/slippage per execution. Entries require a flat position and exits require an open position, with exit priority. Signals use completed candles and request next-open market fills. No leverage or cash yield is used; remaining positions are valued at the end. The same 500-bar startup spans different elapsed time on the two candle sizes.

The sizing request does not guarantee a persistent 1% reserve under the platform’s returned fees and fills. Buy and sell orders each count as executions; totalTrades is not the number of closed positions. The endpoint includes the 00:00 UTC candle opening on the named end date. The execution and source audit retains detailed controls and fee/sizing checks.

Direct containment measurements use exact TrainBard-returned candles and exclude each frame’s first 500 bars. The 20-period share inside ±100 is 60.59–62.11% across frames. An official-archive crosscheck found small earlier-window differences preserved in the source audit; later-window teaching values matched that archive comparison.

The historical price/CCI chart selects the maximum post-startup twenty-period CCI above 200 in the BTCUSDT two-hour later frame. Its locally calculated values illustrate normalization and are not fills. The activity chart uses the fixed small-notional controls on the BTCUSDT two-hour early frame at threshold 100, showing the three rule families over the full lookback grid. Downloadable data retains canonical timestamps and exact settings.

The study evidence contains accepted counts, run identifiers, grids, zero-trade accounting, checksums, per-frame summaries, direct containment measurements, and selection provenance. The tested script accompanies it. Original requests, exports, and earlier diagnostic variants remain in the research archive.

Related settings and overlapping market histories are not independent statistical trials. Algebra establishes the bound; the historical tests describe how the specific entry rules behaved under the stated calculation and execution conventions.

Original TrainBard completion for the CCI lookback, threshold and rule comparison.

This original UI completion covers 36,234 settings on the later ETHUSDT two- and four-hour frames. It includes the deliberately guarded cash outcomes described above. The best displayed row is completion evidence, not a recommended setting.

Compare the fixed scale of RSI or the standard-deviation normalization of Bollinger Bands.