Auf GitHub ansehen

Harami CCI Bestätigung

Überblick

Die Harami CCI-Bestätigung ist eine hochrangige StockSharp-Portierung des MetaTrader 5-Expertenberaters Expert_ABH_BH_CCI. Der ursprüngliche EA handelt mit den Umkehrmustern Bullish Harami und Bearish Harami mit zwei Kerzen. Vor dem Eingehen eines Handels wird eine Bestätigung von einem Commodity Channel Index (CCI)-Oszillator angefordert und die Körpergröße der Kerze anhand eines gleitenden Durchschnitts gemessen, um sicherzustellen, dass die größere Kerze die Spanne wirklich dominiert. Die StockSharp-Konvertierung behält die gleiche Bestätigungslogik bei, verarbeitet nur abgeschlossene Kerzen und nutzt das integrierte Schutzmodul der Plattform zur Bestellsicherheit.

Strategielogik

Mustererkennung

  • Berechnung des durchschnittlichen Körpers – behält einen gleitenden Durchschnitt der absoluten Kerzenkörper über die letzten N Balken bei (Standard 5). Dies spiegelt die Hilfsklasse MetaTrader wider, die die Kerzengröße und Trendreferenz glättet.
  • Bullish Harami – erfordert, dass die vorherige Kerze bullisch ist, dass die vorherige Kerze bärisch ist und einen Körper hat, der länger als der Durchschnitt ist, und dass der bullische Körper innerhalb des bärischen Bereichs bleibt. Der Mittelpunkt der früheren Kerze muss ebenfalls unter dem gleitenden Durchschnitt der Schlusskurse liegen, was einen Abwärtstrend bestätigt.
  • Bearish Harami – gespiegelte Bedingungen: Die vorherige Kerze muss bärisch sein, die frühere Kerze muss bullisch und long sein, der bärische Körper muss innerhalb der bullischen Spanne liegen und der Mittelpunkt muss über dem nahen gleitenden Durchschnitt liegen, um einen Aufwärtstrend zu bestätigen.

CCI Bestätigung

  • Eingabefilter – die Strategie prüft den CCI-Wert der zuletzt abgeschlossenen Kerze (Schicht 1). Für Long-Trades muss der CCI unter -EntryThreshold liegen (Standardwert 50), während für Short-Trades ein Wert über +EntryThreshold erforderlich ist.
  • Ausgangsband – der CCI-Verlauf wird auf Überschreitungen von ±ExitBand überwacht (Standard 80). Wenn der Indikator über -ExitBand steigt, wird jede offene Short-Position geschlossen. Wenn es unter +ExitBand fällt, wird die bestehende Langzeitbelichtung geschlossen. Dies reproduziert die „Stimmen“, die der MetaTrader-Experte verwendet, um Positionen abzuflachen.

Handelsmanagement

  • Umkehrungen – wenn das entgegengesetzte Harami-Setup bestätigt wird, während die Strategie bereits eine Position hält, wird sie genug Volumen handeln, um sowohl das bestehende Risiko zu schließen als auch die neue Richtung zu eröffnen.
  • SchutzStartProtection() ist aktiviert, sodass Benutzer bei Bedarf Stop-Loss- oder Take-Profit-Einstellungen über die StockSharp-Benutzeroberfläche hinzufügen können. Standardmäßig werden keine festen Stopps erzwungen, um mit der Quelle EA in Einklang zu bleiben, die auf manuellen Geldverwaltungseinstellungen beruhte.

Parameter

  • Auftragsvolumen – Basisvolumen, das bei jedem Markteintritt gesendet wird. Bei einer Umkehrung wird automatisch zusätzliches Volumen hinzugefügt, um die Gegenposition zu schließen.
  • CCI Periode – Länge des Commodity Channel Index-Oszillators.
  • Körperdurchschnitt – Anzahl der historischen Kerzen, die bei der Mittelung der Körpergrößen und Schlusskurse verwendet werden.
  • CCI-Eintrag – minimaler absoluter CCI-Wert, der erforderlich ist, um ein Harami-Signal zu akzeptieren.
  • CCI Exit Band – Bandgröße, die die CCI Crossover-Exit-Regeln definiert.
  • Kerzentyp – für Kerzen verwendeter Zeitrahmen (Standard: 1-Stunden-Zeitrahmen).

Zusätzliche Hinweise

  • Alle Berechnungen werden auf abgeschlossenen Kerzen ausgeführt, die von SubscribeCandles bereitgestellt werden. Intrabar-Signale werden absichtlich ignoriert, um dem MetaTrader-Ausführungsmodell zu entsprechen.
  • Die Strategie behält einen kurzen gleitenden Verlauf von Kerzen und CCI-Werten bei, um die Harami-Regeln auszuwerten, ohne volle Indikatorpuffer neu zu erstellen.
  • In diesem Ordner wird nur die C#-Implementierung bereitgestellt. Für diese Konvertierung gibt es keine Python-Version.
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>
/// Harami CCI Confirmation strategy: Harami pattern with CCI confirmation.
/// </summary>
public class HaramiCciConfirmationStrategy : 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 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 HaramiCciConfirmationStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_cciPeriod = Param(nameof(CciPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("CCI Period", "CCI period", "Indicators");
		_entryLevel = Param(nameof(EntryLevel), 0m)
			.SetDisplay("Entry Level", "CCI threshold", "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();
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_candles.Clear();
		_candlesSinceTrade = SignalCooldownCandles;
		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 (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

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

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

			var bullishHarami = prev.OpenPrice > prev.ClosePrice
				&& curr.ClosePrice > curr.OpenPrice
				&& curr.OpenPrice > prev.ClosePrice
				&& curr.ClosePrice < prev.OpenPrice;

			var bearishHarami = prev.ClosePrice > prev.OpenPrice
				&& curr.OpenPrice > curr.ClosePrice
				&& curr.ClosePrice > prev.OpenPrice
				&& curr.OpenPrice < prev.ClosePrice;

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