Auf GitHub ansehen

Dark Cloud Piercing CCI-Strategie

Überblick

Diese Strategie ist ein StockSharp-Port des MetaTrader Expert_ADC_PL_CCI-Advisors. Es durchsucht die Preisbewegung nach Piercing Line- und Dark Cloud Cover-Kerzenumkehrungen und verwendet den Commodity Channel Index (CCI) als Bestätigung. Sobald ein gültiges Muster zusammen mit einem extremen CCI-Wert erkannt wird, eröffnet die Strategie eine Marktposition in Richtung der Umkehr und verlässt sie später, wenn der CCI seinen extremen Bereich verlässt.

Indikatoren

  • Commodity Channel Index (CCI): bestätigt Momentum-Extreme und erstellt die Ausstiegsbedingungen.
  • Durchschnittliche Körperlänge (SMA): misst die Körpergröße der Kerze, um „lange“ Kerzen innerhalb der Musterdefinition zu validieren.
  • Durchschnittlicher Schlusskurs (SMA): fungiert als einfacher Trendfilter, der den in der ursprünglichen MQL-Logik verwendeten gleitenden Durchschnitt widerspiegelt.

Handelsregeln

Entry

  • Bulles Signal (Durchdringungslinie):
    1. Die vorherige Kerze muss eine lange bärische Kerze sein, die über ihrem Schlusskurs öffnet.
    2. Die letzte Kerze muss eine lange bullische Kerze sein, die unterhalb des vorherigen Tiefs öffnet und innerhalb des vorherigen Körpers schließt, oberhalb ihres Mittelpunkts, aber unterhalb der vorherigen Eröffnung.
    3. Der Mittelpunkt der älteren Kerze muss unter dem gleitenden Durchschnitt liegen, um einen kurzfristigen Abwärtstrend zu bestätigen.
    4. The most recent completed CCI value must be less than or equal to -EntryConfirmationLevel (default 50).
    5. Wenn eine Short-Position besteht, wird diese vollständig geschlossen, bevor eine Long-Position eingegangen wird.
  • Bearisches Signal (dunkle Wolkendecke): spiegelte die Logik des bullischen Signals mit einer langen bullischen Kerze, gefolgt von einer langen bärischen Kerze, die eine Lücke nach oben bildet, den vorherigen Körper durchdringt und unter seinem Mittelpunkt schließt, während CCI größer oder gleich EntryConfirmationLevel ist.

Ausstieg

  • Long-Positionen: geschlossen, wenn der CCI unter ExitLevel fällt oder von oben unter -ExitLevel fällt, was signalisiert, dass sich die Dynamik normalisiert hat.
  • Short-Positionen: geschlossen, wenn der CCI über -ExitLevel oder über ExitLevel von unten kreuzt.

Positionsgrößen

  • Verwendet die Basiseigenschaft Volume. Wenn das Signal die Umkehrung einer bestehenden Position erfordert, addiert die Strategie automatisch die absolute Größe der aktuellen Position zum Auftragsvolumen und stellt so eine vollständige Umkehrung sicher.

Parameter

Name Beschreibung Standard
CandleType Kerzentyp und Zeitrahmen, die zur Erkennung verwendet werden. 1H Zeitrahmen
CciPeriod Lookback-Länge des Commodity Channel Index. 49
AverageBodyPeriod Anzahl der Kerzen für den gleitenden Durchschnitt der Körpergröße. 11
EntryConfirmationLevel Absoluter CCI-Level, der Mustereinträge validiert. 50
ExitLevel Absoluter CCI-Level, der Positionsausstiege auslöst. 80

Notizen

  • The strategy processes only finished candles and ignores partial updates.
  • No stop-loss or take-profit orders are set automatically; Ausstiege erfolgen ausschließlich signalbasiert wie im ursprünglichen Expert Advisor.
  • Ensure the instrument has a price step configured because the equality tolerance of the candlestick logic depends on the security settings.
namespace StockSharp.Samples.Strategies;

using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Dark Cloud Piercing CCI strategy: trades Dark Cloud Cover and Piercing Line
/// candlestick patterns confirmed by CCI indicator levels.
/// </summary>
public class DarkCloudPiercingCciStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<decimal> _entryLevel;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private readonly List<ICandleMessage> _candles = new();
	private decimal _prevCci;
	private bool _hasPrevCci;
	private int _candlesSinceTrade;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
	public decimal EntryLevel { get => _entryLevel.Value; set => _entryLevel.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public DarkCloudPiercingCciStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_cciPeriod = Param(nameof(CciPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("CCI Period", "CCI period", "Indicators");
		_entryLevel = Param(nameof(EntryLevel), 50m)
			.SetDisplay("Entry Level", "CCI level for confirmation", "Signals");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_candles.Clear();
		_prevCci = 0m;
		_hasPrevCci = false;
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_candles.Clear();
		_hasPrevCci = false;
		_candlesSinceTrade = SignalCooldownCandles;
		var cci = new CommodityChannelIndex { Length = CciPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(cci, ProcessCandle).Start();

		StartProtection(
			takeProfit: new Unit(2, UnitTypes.Percent),
			stopLoss: new Unit(1, UnitTypes.Percent)
		);
	}

	private void ProcessCandle(ICandleMessage candle, decimal cciValue)
	{
		if (candle.State != CandleStates.Finished) return;

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		_candles.Add(candle);
		if (_candles.Count > 5)
			_candles.RemoveAt(0);

		if (_candles.Count >= 2 && _hasPrevCci)
		{
			var curr = _candles[^1];
			var prev = _candles[^2];

			// Piercing Line: prev bearish, curr bullish, curr opens below prev low, closes above midpoint
			var isPiercing = prev.OpenPrice > prev.ClosePrice
				&& curr.ClosePrice > curr.OpenPrice
				&& curr.OpenPrice < prev.LowPrice
				&& curr.ClosePrice > (prev.OpenPrice + prev.ClosePrice) / 2m;

			// Dark Cloud Cover: prev bullish, curr bearish, curr opens above prev high, closes below midpoint
			var isDarkCloud = prev.ClosePrice > prev.OpenPrice
				&& curr.OpenPrice > curr.ClosePrice
				&& curr.OpenPrice > prev.HighPrice
				&& curr.ClosePrice < (prev.OpenPrice + prev.ClosePrice) / 2m;

			if (isPiercing && cciValue < -EntryLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (isDarkCloud && cciValue > EntryLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevCci = cciValue;
		_hasPrevCci = true;
	}
}