Auf GitHub ansehen

Morning/Evening Star CCI-Strategie

Überblick

Diese Strategie repliziert den MetaTrader 5 Expert Advisor Expert_AMS_ES_CCI unter Verwendung des StockSharp High-Level API. Es sucht nach Drei-Kerzen-Umkehrmustern von Morning Star und Evening Star und erfordert eine Bestätigung durch den Commodity Channel Index (CCI), bevor neue Positionen eröffnet werden. Die Logik funktioniert nur mit fertigen Kerzen und arbeitet mit dem in den Strategieeinstellungen angegebenen primären Wertpapier.

Handelslogik

  • Morning Star langer Eintrag
    • Erkennen Sie drei aufeinanderfolgende Kerzen, die ein Morning Star-Muster bilden:
      • Kerze 1: starker bärischer Körper (Körpergröße größer als der durchschnittliche Körper im ausgewählten Fenster).
      • Kerze 2: Kerze mit kleinem Körper und geringerem Abstand als Kerze 1.
      • Kerze 3: schließt über dem Mittelpunkt von Kerze 1.
    • Bestätigen Sie, dass der CCI-Wert in der Signalleiste unter dem negativen Eingabeschwellenwert liegt (Standard: −50).
  • Evening Star Kurzeintrag
    • Erkennen Sie ein gültiges Evening Star-Muster:
      • Kerze 1: starker bullischer Körper.
      • Kerze 2: Kerze mit kleinem Körper, die über Kerze 1 hinausragt.
      • Kerze 3: schließt unter dem Mittelpunkt von Kerze 1.
    • Bestätigen Sie, dass der CCI-Wert auf der Signalleiste größer als der positive Eingabeschwellenwert ist (Standard +50).
  • Positionsausstiegsregeln
    • Schließen Sie Short-Positionen, wenn CCI wieder über −NeutralThreshold kreuzt oder unter +NeutralThreshold fällt (Standard ±80).
    • Schließen Sie Long-Positionen, wenn CCI wieder unter +NeutralThreshold fällt oder unter −NeutralThreshold fällt.
    • Es sind keine zusätzlichen Stop-Loss- oder Take-Profit-Regeln eingebettet; Benutzer können bei Bedarf externe Schutzmaßnahmen hinzufügen.

Indikatoren

  • Commodity Channel Index (CCI) – Bestätigungsfilter, Standardzeitraum 25.
  • Einfacher gleitender Durchschnitt der Kerzenkörper – berechnet die durchschnittliche Körpergröße über die letzten BodyAveragePeriod-Kerzen (Standard 5), um die Musterstärke zu validieren.

Parameter

Name Beschreibung Standard Notizen
CciPeriod Anzahl der Balken, die in der CCI-Berechnung verwendet werden. 25 Optimierbar.
BodyAveragePeriod Anzahl der Kerzen, die zur Messung der durchschnittlichen Körpergröße verwendet werden. 5 Optimierbar.
EntryThreshold Absoluter CCI-Wert für neue Trades erforderlich. 50 Positiver Wert; Die Strategie prüft ±EntryThreshold.
NeutralThreshold Absolutes CCI-Niveau, das die Ausgangszone definiert. 80 Positiver Wert; Die Strategie prüft ±NeutralThreshold.
CandleType Für die Analyse verwendeter Kerzentyp (Zeitrahmen). Zeitrahmen 1 Stunde Ändern Sie die Einstellung, um sie an die gewünschte Auflösung anzupassen.

Notizen

  • Die Strategie abonniert Kerzenaktualisierungen über SubscribeCandles und verwendet Bind, um Indikatorwerte zu empfangen.
  • Trades werden mit Marktaufträgen unter Verwendung von BuyMarket und SellMarket ausgeführt.
  • Alle Kommentare im Code sind nach Bedarf in Englisch verfasst.
  • Um das Risikomanagement zu erweitern, kombinieren Sie die Strategie mit StartProtection oder benutzerdefinierten Geldverwaltungsmodulen.
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Morning/Evening Star + CCI strategy.
/// Buys on morning star with negative CCI, sells on evening star with positive CCI.
/// </summary>
public class MorningEveningStarCciStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<decimal> _cciLevel;

	private ICandleMessage _prevCandle;
	private ICandleMessage _prevPrevCandle;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
	public decimal CciLevel { get => _cciLevel.Value; set => _cciLevel.Value = value; }

	public MorningEveningStarCciStrategy()
	{
		_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");
		_cciLevel = Param(nameof(CciLevel), 0m)
			.SetDisplay("CCI Level", "CCI threshold for confirmation", "Signals");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevCandle = null;
		_prevPrevCandle = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevCandle = null;
		_prevPrevCandle = null;
		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 (_prevCandle != null && _prevPrevCandle != null)
		{
			var prevBody = Math.Abs(_prevCandle.ClosePrice - _prevCandle.OpenPrice);
			var prevRange = _prevCandle.HighPrice - _prevCandle.LowPrice;
			var isSmallBody = prevRange > 0 && prevBody < prevRange * 0.3m;

			var firstBearish = _prevPrevCandle.OpenPrice > _prevPrevCandle.ClosePrice;
			var currBullish = candle.ClosePrice > candle.OpenPrice;
			var isMorningStar = firstBearish && isSmallBody && currBullish &&
							   candle.ClosePrice > _prevPrevCandle.OpenPrice * 0.5m + _prevPrevCandle.ClosePrice * 0.5m;

			var firstBullish = _prevPrevCandle.ClosePrice > _prevPrevCandle.OpenPrice;
			var currBearish = candle.OpenPrice > candle.ClosePrice;
			var isEveningStar = firstBullish && isSmallBody && currBearish &&
							   candle.ClosePrice < _prevPrevCandle.OpenPrice * 0.5m + _prevPrevCandle.ClosePrice * 0.5m;

			if (isMorningStar && cciValue < -CciLevel && Position <= 0)
				BuyMarket();
			else if (isEveningStar && cciValue > CciLevel && Position >= 0)
				SellMarket();
		}

		_prevPrevCandle = _prevCandle;
		_prevCandle = candle;
	}
}