Auf GitHub ansehen

Sidus Alligator-Strategie

Überblick

Die Sidus-Strategie reproduziert die klassische MetaTrader-"Sidus"-Expertenberater-Logik in StockSharp. Sie kombiniert den Bill Williams Alligator-Indikator mit einem 14-Perioden Relative Strength Index (RSI)-Filter. Das System sucht nach einem RSI-Kreuz über oder unter die 50-Mittellinie, während alle drei Alligator-Gleitenden-Durchschnitte sich in die gleiche Richtung ausdehnen. Jeder Einstieg berechnet sofort Schutz-Stops und optionales Trailing-Management, ausgedrückt in Pip-Abständen, die den Preisschritt des Instruments respektieren.

Indikatoren und Daten

  • Alligator-Linien: Drei geglättete gleitende Durchschnitte, berechnet auf dem Kerzen-Median-Preis (Hoch + Tief ÷ 2) mit unabhängigen Längen und Vorwärts-Shifts für Kiefer, Zähne und Lippen. Aufeinanderfolgende Werte werden verglichen, um Aufwärts- oder Abwärtsausdehnung zu erkennen.
  • Relative Strength Index (RSI): Ein 14-Perioden-Oszillator, ausgewertet auf Schlusspreisen. Nur fertige Kerzen nehmen an der Entscheidung teil, um Vorausschau-Bias zu vermeiden.
  • Kerzen: Jeder Zeitrahmen kann über den Parameter CandleType ausgewählt werden. Standardmäßig verwendet die Strategie Kerzen im Einer-Minuten-Zeitrahmen.

Handelslogik

  1. RSI-Bestätigung
    • Long-Setup: RSI kreuzt aufwärts durch 50 (RSI[t-2] < 50 und RSI[t-1] > 50).
    • Short-Setup: RSI kreuzt abwärts durch 50 (RSI[t-2] > 50 und RSI[t-1] < 50).
  2. Alligator-Neigungsfilter
    • Long-Einstieg erfordert, dass die Kiefer-, Zahn- und Lippensteigungs-Differenzen zwischen den zwei vorherigen abgeschlossenen Werten (unter Berücksichtigung der Shifts) den Delta-Schwellenwert überschreiten.
    • Short-Einstieg erfordert, dass die gleichen Steigungen unter dem Schwellenwert liegen, was Kompression oder Rückgang anzeigt.
  3. Positions-Handling
    • Wenn ein Long-Signal erscheint, werden Shorts zuerst geschlossen wenn CloseOpposite = true. Die Strategie kauft dann das konfigurierte OrderVolume zu Markt.
    • Wenn ein Short-Signal erscheint, werden Longs geglättet wenn von CloseOpposite erlaubt, gefolgt von einem Markt-Verkauf von OrderVolume.

Ausstieg und Risikomanagement

  • Anfangs-Stop-Loss: Berechnet vom vorherigen Kerzen-Extrem minus/plus OffsetPips (umgerechnet mit dem Preisschritt des Instruments). Stops werden übersprungen wenn das berechnete Level den Trade ungültig machen würde (z.B. nicht-positiver Abstand).
  • Take-Profit: Optionaler Abstand definiert durch TakeProfitPips. Das Setzen des Parameters auf null deaktiviert das Ziel.
  • Trailing-Stop: Wenn TrailingStopPips und TrailingStepPips beide positiv sind, wird der Stop vorgerückt sobald der Preis mindestens TrailingStopPips + TrailingStepPips zugunsten der Position bewegt. Der neue Stop wird TrailingStopPips vom höchsten Hoch (Longs) oder niedrigsten Tief (Shorts) platziert, das während der Kerze erreicht wurde.
  • Glättungslogik: Stop-Loss, Take-Profit und Trailing-Logik werden bei jeder fertigen Kerze anhand von Hoch/Tief-Bereichen ausgewertet, um Intrabar-Berührungen zu simulieren.

Parameter

  • OrderVolume (Standard 0.1): Trade-Größe in Lots oder Kontrakten.
  • OffsetPips (Standard 3): Abstand vom vorherigen Kerzen-Extrem zum Stop-Loss. Null deaktiviert den anfänglichen Stop.
  • TakeProfitPips (Standard 75): Take-Profit-Abstand. Null deaktiviert das Ziel.
  • TrailingStopPips (Standard 5): Trailing-Stop-Abstand. Muss positiv sein wenn Trailing aktiviert ist.
  • TrailingStepPips (Standard 15): Zusätzliche Bewegung erforderlich bevor der Trailing-Stop vorrückt. Muss positiv sein wenn Trailing aktiviert ist.
  • Delta (Standard 0.00003): Minimale Steigungs-Differenz für jede Alligator-Linie zwischen aufeinanderfolgenden Proben.
  • CloseOpposite (Standard false): Wenn true, werden entgegengesetzte Positionen vor dem Öffnen eines neuen Trades geschlossen; wenn false, wartet die Strategie darauf, dass die aktuelle Position natürlich geglättet wird.
  • JawPeriod, TeethPeriod, LipsPeriod: Längen der geglätteten gleitenden Durchschnitte für Alligator-Kiefer, -Zähne und -Lippen (Standard 13/8/5).
  • JawShift, TeethShift, LipsShift: Vorwärts-Shifts (Standard 8/5/3), die beim Abrufen von Steigungsvergleichen verwendet werden.
  • RsiPeriod (Standard 14): RSI-Mittelungsfenster.
  • CandleType: Kerzen-Datentyp/Zeitrahmen zur Anmeldung (Standard 1 Minute).

Implementierungshinweise

  • Pip-basierte Abstände passen sich automatisch an die Preisgenauigkeit des Instruments an: Fünf- und Dreistellen-Instrumente multiplizieren den Preisschritt mit zehn, um der MQL-Pip-Definition zu entsprechen.
  • Alligator-Steigungsprüfungen basieren auf gespeicherten historischen Werten, die die konfigurierten Vorwärts-Shifts respektieren, und vermeiden manuelles Array-Management über einen minimalen Ringpuffer hinaus.
  • Orders werden mit den High-Level-Helfern BuyMarket und SellMarket ausgeführt, sodass die Strategie auf die Signalgenerierung fokussiert bleibt, während StockSharp das Routing übernimmt.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Sidus Alligator strategy using triple EMA alignment.
/// </summary>
public class SidusAlligatorStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _jawPeriod;
	private readonly StrategyParam<int> _teethPeriod;
	private readonly StrategyParam<int> _lipsPeriod;

	private decimal? _prevLips;
	private decimal? _prevTeeth;

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

	public int JawPeriod
	{
		get => _jawPeriod.Value;
		set => _jawPeriod.Value = value;
	}

	public int TeethPeriod
	{
		get => _teethPeriod.Value;
		set => _teethPeriod.Value = value;
	}

	public int LipsPeriod
	{
		get => _lipsPeriod.Value;
		set => _lipsPeriod.Value = value;
	}

	public SidusAlligatorStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_jawPeriod = Param(nameof(JawPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("Jaw Period", "Slow EMA (Jaw)", "Indicators");

		_teethPeriod = Param(nameof(TeethPeriod), 25)
			.SetGreaterThanZero()
			.SetDisplay("Teeth Period", "Medium EMA (Teeth)", "Indicators");

		_lipsPeriod = Param(nameof(LipsPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Lips Period", "Fast EMA (Lips)", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

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

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

		_prevLips = null;
		_prevTeeth = null;

		var jaw = new ExponentialMovingAverage { Length = JawPeriod };
		var teeth = new ExponentialMovingAverage { Length = TeethPeriod };
		var lips = new ExponentialMovingAverage { Length = LipsPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(jaw, teeth, lips, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, jaw);
			DrawIndicator(area, teeth);
			DrawIndicator(area, lips);
			DrawOwnTrades(area);
		}
	}

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

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_prevLips = lipsVal;
			_prevTeeth = teethVal;
			return;
		}

		if (_prevLips == null || _prevTeeth == null)
		{
			_prevLips = lipsVal;
			_prevTeeth = teethVal;
			return;
		}

		// Lips crosses above teeth with alligator aligned (lips > teeth > jaw)
		if (_prevLips.Value <= _prevTeeth.Value && lipsVal > teethVal && lipsVal > jawVal)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		// Lips crosses below teeth with alligator aligned (lips < teeth < jaw)
		else if (_prevLips.Value >= _prevTeeth.Value && lipsVal < teethVal && lipsVal < jawVal)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}

		_prevLips = lipsVal;
		_prevTeeth = teethVal;
	}
}