Trading Strategy

CCI Strategy

A momentum oscillator strategy using the Commodity Channel Index to identify cyclical trends and mean reversion opportunities.

Cyclical Momentum Indicator

The Commodity Channel Index (CCI) is a versatile indicator that measures how price deviates from the statistical mean. Originally designed for commodity markets, it works equally well on any financial instrument. CCI identifies cyclical trends, overbought/oversold conditions, and potential trend reversals. Combined with a 200 EMA trend filter, this strategy provides reliable entry signals.

Momentum Type
4h Chart Timeframe
Intermediate Complexity
CCI + EMA + ATR Indicators

Signal Logic

Long (Buy)

CCI crosses above oversold level (-100), price is above 200 EMA.

Short (Sell)

CCI crosses below overbought level (+100), price is below 200 EMA.

Implementation

//@version=6
strategy("CCI Strategy", overlay=true, initial_capital=1000000, default_qty_type=strategy.percent_of_equity, default_qty_value=100)

// ==========================================
// 🔹 INPUTS
// ==========================================
// Group: CCI Settings
grp_cci = "CCI Settings"
cci_len = input.int(20, "CCI Period", minval=1, group=grp_cci)
cci_oversold = input.int(-100, "Oversold Level", group=grp_cci)
cci_overbought = input.int(100, "Overbought Level", group=grp_cci)

// Group: Trend Filter
grp_trend = "Trend Filter"
use_trend = input.bool(true, "Use Trend Filter (EMA 200)", group=grp_trend)
ema_len = input.int(200, "Trend EMA Length", minval=1, group=grp_trend)

// Group: Risk Management
grp_risk = "Risk Management"
atr_len = input.int(14, "ATR Length", minval=1, group=grp_risk)
sl_mult = input.float(2.0, "Stop Loss (ATR Multiplier)", step=0.1, group=grp_risk)
tp_ratio = input.float(2.0, "Risk:Reward Ratio", step=0.1, group=grp_risk)

// ==========================================
// 🔹 CALCULATIONS
// ==========================================
// CCI Indicator
cci_val = ta.cci(close, high, low, cci_len)

// Trend EMA
ema_val = ta.ema(close, ema_len)

// ATR for risk management
atr_val = ta.atr(atr_len)

// Trend conditions
trend_up = use_trend ? close > ema_val : true
trend_down = use_trend ? close < ema_val : true

// ==========================================
// 🔹 STRATEGY LOGIC
// ==========================================
// Long Entry: CCI crosses above oversold level (bullish reversal)
long_signal = ta.crossover(cci_val, cci_oversold) and trend_up

// Short Entry: CCI crosses below overbought level (bearish reversal)
short_signal = ta.crossunder(cci_val, cci_overbought) and trend_down

// ==========================================
// 🔹 EXECUTION & RISK MANAGEMENT
// ==========================================

if long_signal
    strategy.entry("Long", strategy.long, comment="L | CCI Bull")

if short_signal
    strategy.entry("Short", strategy.short, comment="S | CCI Bear")

// Risk management with ATR
if strategy.position_size > 0
    stop_level = strategy.position_avg_price - (atr_val * sl_mult)
    profit_level = strategy.position_avg_price + (atr_val * sl_mult * tp_ratio)
    strategy.exit("Exit Long", "Long", stop=stop_level, limit=profit_level, comment_loss="SL", comment_profit="TP")

if strategy.position_size < 0
    stop_level = strategy.position_avg_price + (atr_val * sl_mult)
    profit_level = strategy.position_avg_price - (atr_val * sl_mult * tp_ratio)
    strategy.exit("Exit Short", "Short", stop=stop_level, limit=profit_level, comment_loss="SL", comment_profit="TP")

// ==========================================
// 🔹 VISUALS
// ==========================================
// Plot Trend EMA
plot(use_trend ? ema_val : na, "Trend EMA", color=color.new(color.orange, 0), linewidth=2)

// Plot CCI Reference Levels
plot(cci_overbought, "Overbought", color=color.new(color.red, 70), linestyle=plot.linestyle_dashed)
plot(cci_oversold, "Oversold", color=color.new(color.green, 70), linestyle=plot.linestyle_dashed)
plot(0, "Zero Line", color=color.new(color.gray, 80), linestyle=plot.linestyle_dashed)

// Plot Signals on price chart
plotshape(long_signal, title="Long Signal", location=location.belowbar, color=color.green, style=shape.labelup, text="BUY", textcolor=color.white)
plotshape(short_signal, title="Short Signal", location=location.abovebar, color=color.red, style=shape.labeldown, text="SELL", textcolor=color.white)

// Background color for overbought/oversold zones
overbought_zone = cci_val > cci_overbought
oversold_zone = cci_val < cci_oversold
bgcolor(overbought_zone ? color.new(color.red, 95) : oversold_zone ? color.new(color.green, 95) : na)