Auf GitHub ansehen

Head-and-Shoulders-Strategie

Überblick

Die Head-and-Shoulders-Strategie ist ein direkter Port des MetaTrader-Expert-Advisors "HEAD AND SHOULDERS" (MQL ID 26066). Der ursprüngliche Roboter kombiniert Erkennung des Kopf-Schulter-Musters mit Momentum-, Moving-Average- und MACD-Filtern und verwaltet Positionen mit Trailing Stops, Equity-Schutz und Break-even-Regeln. Diese StockSharp-Implementierung konzentriert sich auf die diskretionäre Logik der Ein- und Ausstiegsengine über die High-Level-API und bietet saubere Indikatorbindungen sowie automatisiertes Risikomanagement über StartProtection.

Handelslogik

  1. Mustererkennung
    • Verwendet ein Fünf-Bars-Fraktalfenster zur Annäherung von Swing-Hochs und -Tiefs und spiegelt damit die fraktalbasierte Mustererkennung des Quell-EA.
    • Bestätigt ein bärisches Kopf-Schulter-Muster, wenn drei sequenzielle Fraktalhochs erscheinen und das mittlere Hoch (der Kopf) beide Schultern um eine konfigurierbare Dominanzschwelle übersteigt.
    • Bestätigt ein invertiertes Kopf-Schulter-Muster, wenn drei sequenzielle Fraktaltiefs entstehen und das mittlere Tief ausreichend unter beiden Schultern liegt.
    • Die Nackenlinie wird aus den jüngsten Fraktaltiefs (bärisches Muster) oder -hochs (bullisches Muster) zwischen Schultern und Kopf berechnet.
  2. Momentum- und Trendfilter
    • Schnelle und langsame einfache gleitende Durchschnitte müssen mit der erwarteten Trendrichtung übereinstimmen.
    • Absolutes Momentum (Differenz zwischen aktuellem Wert und Rückblickperiode) muss eine Schwelle überschreiten und in dieselbe Richtung wie der Trade zeigen.
    • Der MACD-Wert muss zur Ausbruchsrichtung passen, um Gegentrendsignale zu vermeiden.
  3. Ausbruchsausführung
    • Long-Trades werden ausgelöst, wenn der Schlusskurs über die bullische Nackenlinie ausbricht und alle Filter übereinstimmen.
    • Short-Trades werden ausgelöst, wenn der Schlusskurs unter die bärische Nackenlinie bricht und bärische Filter ausgerichtet sind.
  4. Positionsverwaltung
    • Positionen steigen aus, wenn die Nackenlinie in Gegenrichtung verletzt wird oder die gleitenden Durchschnitte und MACD ihre Ausrichtung verlieren.
    • Optionale Schutzorders werden über den integrierten StartProtection-Helper mit Stop-Loss-, Take-Profit- und Trailing-Stop-Parametern in Preisschritten konfiguriert.

Parameter

Parameter Standard Beschreibung
CandleType 1H-Zeitrahmen Primäre Kerzenserie für die Mustererkennung.
OrderVolume 1 Basisordergröße.
FastMaLength / SlowMaLength 6 / 85 Längen der Moving-Average-Trendfilter.
MomentumPeriod 14 Rückblickperiode für den Momentum-Indikator.
MomentumThreshold 0.3 Minimales absolutes Momentum zur Bestätigung.
MacdFastLength, MacdSlowLength, MacdSignalLength 12, 26, 9 MACD-Konfiguration.
ShoulderTolerancePercent 5 Maximal erlaubte Abweichung zwischen linker und rechter Schulter.
HeadDominancePercent 2 Mindestbetrag, um den der Kopf jede Schulter übersteigen muss.
StopLossSteps, TakeProfitSteps, TrailingStopSteps 100, 200, 0 Schutzordergrößen in Preisschritten (null deaktiviert eine Komponente).

Alle mit Param() erstellten Parameter stellen Metadaten für die UI bereit und können über den StockSharp-Optimierer optimiert werden.

Unterschiede zum Original-Experten

  • Entfernt MetaTrader-spezifische Equity-Stop-, Trailing- und Orderänderungsroutinen zugunsten der integrierten Portfolio-Schutzmechanismen von StockSharp.
  • Konzentriert sich ausschließlich auf Marktorders und High-Level-API-Aufrufe (BuyMarket / SellMarket).
  • Vereinfacht Hilfsfunktionen wie Alerts, Push-Benachrichtigungen und das Zeichnen grafischer Objekte; die StockSharp-Version protokolliert Erkennungen stattdessen mit LogInfo.
  • Die Mustererkennung behält den Geist der ursprünglichen fraktalbasierten Logik bei, wurde aber neu geschrieben, um direkten Datenarray-Zugriff und Orderticket-Manipulation zu vermeiden.

Nutzungshinweise

  • Da die Strategie auf abgeschlossenen Kerzen basiert, stellen Sie sicher, dass Datenabonnements fertige Bars liefern (CandleStates.Finished).
  • Trailing-Schutz verwendet Preisschritte; prüfen Sie, dass Security.PriceStep die Tickgröße des Instruments widerspiegelt, bevor Trailing Stops aktiviert werden.
  • Der Musterdetektor speichert nur jüngste Fraktale, um unbegrenzte Sammlungen zu vermeiden, und eignet sich daher für lange Live-Sitzungen.
  • Für zusätzliche Bestätigungsebenen (z. B. MACD auf höherem Zeitrahmen wie im Original-EA) erweitern Sie die Strategie mit zusätzlichen Abonnements nach demselben Binding-Ansatz.

Referenzen

using System;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Head and Shoulders strategy: EMA crossover + RSI confirmation.
/// Buys when fast EMA crosses above slow EMA and RSI &lt; 55.
/// Sells when fast EMA crosses below slow EMA and RSI &gt; 45.
/// </summary>
public class HeadAndShouldersStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _rsiPeriod;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	public HeadAndShouldersStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 21)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		decimal? prevFast = null;
		decimal? prevSlow = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, rsi, (candle, fastVal, slowVal, rsiVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				if (prevFast.HasValue && prevSlow.HasValue)
				{
					var crossUp = prevFast.Value <= prevSlow.Value && fastVal > slowVal;
					var crossDown = prevFast.Value >= prevSlow.Value && fastVal < slowVal;

					if (crossUp && rsiVal < 55m && Position <= 0)
						BuyMarket();
					else if (crossDown && rsiVal > 45m && Position >= 0)
						SellMarket();
				}

				prevFast = fastVal;
				prevSlow = slowVal;
			})
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, fast);
			DrawIndicator(area, slow);
			DrawOwnTrades(area);
		}
	}
}