Diese Strategie verwendet den Commodity Channel Index (CCI), um Umkehrungen zu erkennen, nachdem der Indikator extreme Zonen verlässt.
Überblick
Der Indikator wird auf 8-Stunden-Kerzen mit einer konfigurierbaren Periode berechnet. Zwei Schwellenwerte definieren überkaufte und überverkaufte Bereiche. Wenn der CCI nach Erreichen eines Extremwerts wieder in diese Grenzen zurückkehrt, eröffnet die Strategie eine Position in entgegengesetzter Richtung und erwartet eine Mean Reversion.
Handelsregeln
Long-Einstieg: Vor zwei Bars lag der CCI über dem hohen Niveau und der vorherige Bar fiel darunter.
Short-Einstieg: Vor zwei Bars lag der CCI unter dem niedrigen Niveau und der vorherige Bar stieg darüber.
Long schließen: Der CCI des vorherigen Bars lag unter dem mittleren Niveau.
Short schließen: Der CCI des vorherigen Bars lag über dem mittleren Niveau.
Parameter
CciPeriod – Rückblickperiode für den CCI.
HighLevel – oberer CCI-Schwellenwert, der als überkauft gilt.
MiddleLevel – mittlerer Schwellenwert zum Schließen von Positionen.
LowLevel – unterer CCI-Schwellenwert, der als überverkauft gilt.
CandleType – Kerzenserie für die Berechnungen (Standard 8 Stunden).
Hinweise
Die Strategie öffnet maximal eine Position gleichzeitig und verwendet Marktaufträge. Das Standard-Risikomanagement wird über StartProtection aktiviert.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// CCI Normalized Reversal Strategy.
/// Enters positions after the indicator leaves extreme zones.
/// </summary>
public class CciNormalizedReversalStrategy : Strategy
{
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<int> _highLevel;
private readonly StrategyParam<int> _middleLevel;
private readonly StrategyParam<int> _lowLevel;
private readonly StrategyParam<DataType> _candleType;
private int _prevColor = 2;
private int _prevPrevColor = 2;
/// <summary>
/// CCI calculation period.
/// </summary>
public int CciPeriod
{
get => _cciPeriod.Value;
set => _cciPeriod.Value = value;
}
/// <summary>
/// Upper CCI threshold.
/// </summary>
public int HighLevel
{
get => _highLevel.Value;
set => _highLevel.Value = value;
}
/// <summary>
/// Middle CCI threshold.
/// </summary>
public int MiddleLevel
{
get => _middleLevel.Value;
set => _middleLevel.Value = value;
}
/// <summary>
/// Lower CCI threshold.
/// </summary>
public int LowLevel
{
get => _lowLevel.Value;
set => _lowLevel.Value = value;
}
/// <summary>
/// Candle type to use.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="CciNormalizedReversalStrategy"/>.
/// </summary>
public CciNormalizedReversalStrategy()
{
_cciPeriod = Param(nameof(CciPeriod), 10)
.SetDisplay("CCI Period", "Lookback period for CCI", "General")
.SetRange(5, 50)
;
_highLevel = Param(nameof(HighLevel), 100)
.SetDisplay("High Level", "Upper CCI threshold", "General")
.SetRange(50, 200)
;
_middleLevel = Param(nameof(MiddleLevel), 0)
.SetDisplay("Middle Level", "Middle CCI threshold", "General")
.SetRange(-50, 50)
;
_lowLevel = Param(nameof(LowLevel), -100)
.SetDisplay("Low Level", "Lower CCI threshold", "General")
.SetRange(-200, -50)
;
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevColor = 2;
_prevPrevColor = 2;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevColor = 2;
_prevPrevColor = 2;
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(cci, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal cciValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var color = GetColorIndex(cciValue);
// Close short when CCI rises above middle level
if (_prevColor < 2 && Position < 0)
BuyMarket();
// Close long when CCI falls below middle level
if (_prevColor > 2 && Position > 0)
SellMarket();
// Open long after leaving high zone
if (_prevPrevColor == 0 && _prevColor > 0 && Position <= 0)
BuyMarket();
// Open short after leaving low zone
if (_prevPrevColor == 4 && _prevColor < 4 && Position >= 0)
SellMarket();
_prevPrevColor = _prevColor;
_prevColor = color;
}
private int GetColorIndex(decimal cci)
{
if (cci > MiddleLevel)
return cci > HighLevel ? 0 : 1;
if (cci < MiddleLevel)
return cci < LowLevel ? 4 : 3;
return 2;
}
}
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_normalized_reversal_strategy(Strategy):
def __init__(self):
super(cci_normalized_reversal_strategy, self).__init__()
self._cci_period = self.Param("CciPeriod", 10) \
.SetDisplay("CCI Period", "Lookback period for CCI", "General")
self._high_level = self.Param("HighLevel", 100) \
.SetDisplay("High Level", "Upper CCI threshold", "General")
self._middle_level = self.Param("MiddleLevel", 0) \
.SetDisplay("Middle Level", "Middle CCI threshold", "General")
self._low_level = self.Param("LowLevel", -100) \
.SetDisplay("Low Level", "Lower CCI threshold", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_color = 2
self._prev_prev_color = 2
@property
def cci_period(self):
return self._cci_period.Value
@property
def high_level(self):
return self._high_level.Value
@property
def middle_level(self):
return self._middle_level.Value
@property
def low_level(self):
return self._low_level.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(cci_normalized_reversal_strategy, self).OnReseted()
self._prev_color = 2
self._prev_prev_color = 2
def OnStarted2(self, time):
super(cci_normalized_reversal_strategy, self).OnStarted2(time)
self._prev_color = 2
self._prev_prev_color = 2
cci = CommodityChannelIndex()
cci.Length = self.cci_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(cci, self.process_candle).Start()
def process_candle(self, candle, cci_value):
if candle.State != CandleStates.Finished:
return
cci_val = float(cci_value)
color = self._get_color_index(cci_val)
# Close short when CCI rises above middle level
if self._prev_color < 2 and self.Position < 0:
self.BuyMarket()
# Close long when CCI falls below middle level
if self._prev_color > 2 and self.Position > 0:
self.SellMarket()
# Open long after leaving high zone
if self._prev_prev_color == 0 and self._prev_color > 0 and self.Position <= 0:
self.BuyMarket()
# Open short after leaving low zone
if self._prev_prev_color == 4 and self._prev_color < 4 and self.Position >= 0:
self.SellMarket()
self._prev_prev_color = self._prev_color
self._prev_color = color
def _get_color_index(self, cci):
mid = float(self.middle_level)
high = float(self.high_level)
low = float(self.low_level)
if cci > mid:
return 0 if cci > high else 1
if cci < mid:
return 4 if cci < low else 3
return 2
def CreateClone(self):
return cci_normalized_reversal_strategy()