Auf GitHub ansehen

CCI Normalisierte Umkehr-Strategie

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;
	}
}