CCI-Divergenzen (Commodity Channel Index) können Trendumkehrungen ankündigen, wenn sich der Preis in die entgegengesetzte Richtung des Indikators bewegt. Diese Strategie vergleicht Swing-Hochs und -Tiefs im Preis mit denen des CCI, um verstärkte Stärke oder Schwäche zu identifizieren.
Tests zeigen eine durchschnittliche jährliche Rendite von etwa 91%. Sie funktioniert am besten auf dem Aktienmarkt.
Bei jeder Kerze aktualisiert das System die jüngsten Preis- und CCI-Werte und markiert eine bullische Divergenz, wenn der Preis ein neues Tief macht, während der CCI ein höheres Tief bildet. Bärische Divergenz ist das Gegenteil. Wenn eine Divergenz mit überverkauften oder überkauften Niveaus übereinstimmt, wird ein Trade mit einem Volatilitätsstopp eröffnet.
Ausstiege erfolgen, wenn der CCI wieder durch die Nulllinie kreuzt, was signalisiert, dass der Impuls abgespielt hat. Da Divergenzen andauern können, werden die Regeln auch nach einer festen Anzahl von Balken zurückgesetzt, um veraltete Signale zu vermeiden.
Details
Einstiegskriterien: Preis/CCI-Divergenz mit CCI unter -100 für Longs oder über +100 für Shorts.
Long/Short: Beide.
Ausstiegskriterien: CCI kreuzt Null oder Stop-Loss.
Stops: Ja, prozentbasiert.
Standardwerte:
CciPeriod = 20
DivergencePeriod = 5
OverboughtLevel = 100
OversoldLevel = -100
CandleType = 15 minute
StopLossPercent = 2
Filter:
Kategorie: Divergenz
Richtung: Beide
Indikatoren: CCI
Stops: Ja
Komplexität: Fortgeschritten
Zeitrahmen: Intraday
Saisonalität: Nein
Neuronale Netze: Nein
Divergenz: Ja
Risikolevel: Mittel
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// CCI Divergence strategy.
/// Detects divergences between price and CCI for reversal signals.
/// Bullish: price falling but CCI rising.
/// Bearish: price rising but CCI falling.
/// </summary>
public class CciDivergenceStrategy : Strategy
{
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private decimal _prevPrice;
private decimal _prevCci;
private int _cooldown;
/// <summary>
/// CCI Period.
/// </summary>
public int CciPeriod
{
get => _cciPeriod.Value;
set => _cciPeriod.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Cooldown bars.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public CciDivergenceStrategy()
{
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetRange(5, 30)
.SetDisplay("CCI Period", "Period for CCI", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_cooldownBars = Param(nameof(CooldownBars), 500)
.SetRange(1, 1000)
.SetDisplay("Cooldown Bars", "Bars to wait between trades", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevPrice = default;
_prevCci = default;
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevPrice = 0;
_prevCci = 0;
_cooldown = 0;
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(cci, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, cci);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal cciValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_prevPrice == 0)
{
_prevPrice = candle.ClosePrice;
_prevCci = cciValue;
return;
}
if (_cooldown > 0)
{
_cooldown--;
_prevPrice = candle.ClosePrice;
_prevCci = cciValue;
return;
}
var bullishDiv = candle.ClosePrice < _prevPrice && cciValue > _prevCci;
var bearishDiv = candle.ClosePrice > _prevPrice && cciValue < _prevCci;
if (Position == 0 && bullishDiv && cciValue > -100)
{
BuyMarket();
_cooldown = CooldownBars;
}
else if (Position == 0 && bearishDiv && cciValue < 100)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position > 0 && cciValue > 100)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position < 0 && cciValue < -100)
{
BuyMarket();
_cooldown = CooldownBars;
}
_prevPrice = candle.ClosePrice;
_prevCci = cciValue;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class cci_divergence_strategy(Strategy):
"""
CCI Divergence strategy.
Detects divergences between price and CCI for reversal signals.
Bullish: price falling but CCI rising.
Bearish: price rising but CCI falling.
"""
def __init__(self):
super(cci_divergence_strategy, self).__init__()
self._cci_period = self.Param("CciPeriod", 14).SetDisplay("CCI Period", "Period for CCI", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._cooldown_bars = self.Param("CooldownBars", 500).SetDisplay("Cooldown Bars", "Bars to wait between trades", "General")
self._prev_price = 0.0
self._prev_cci = 0.0
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(cci_divergence_strategy, self).OnReseted()
self._prev_price = 0.0
self._prev_cci = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(cci_divergence_strategy, self).OnStarted2(time)
self._prev_price = 0.0
self._prev_cci = 0.0
self._cooldown = 0
cci = CommodityChannelIndex()
cci.Length = self._cci_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(cci, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, cci)
self.DrawOwnTrades(area)
def _process_candle(self, candle, cci_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
cv = float(cci_val)
if self._prev_price == 0:
self._prev_price = close
self._prev_cci = cv
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_price = close
self._prev_cci = cv
return
cd = self._cooldown_bars.Value
bullish_div = close < self._prev_price and cv > self._prev_cci
bearish_div = close > self._prev_price and cv < self._prev_cci
if self.Position == 0 and bullish_div and cv > -100:
self.BuyMarket()
self._cooldown = cd
elif self.Position == 0 and bearish_div and cv < 100:
self.SellMarket()
self._cooldown = cd
elif self.Position > 0 and cv > 100:
self.SellMarket()
self._cooldown = cd
elif self.Position < 0 and cv < -100:
self.BuyMarket()
self._cooldown = cd
self._prev_price = close
self._prev_cci = cv
def CreateClone(self):
return cci_divergence_strategy()