Auf GitHub ansehen

Sidus v1-Strategie

Überblick

Sidus v1 ist eine Trendfolgestrategie, die zwei Sätze von Exponential Moving Averages (EMAs) mit Filtern für den Relative Strength Index (RSI) kombiniert. Der ursprüngliche MetaTrader 4-Expertenberater eröffnet eine Position, wenn ein schneller EMA von einem langsameren EMA abweicht und der RSI entweder überverkaufte oder überkaufte Bedingungen bestätigt. Dieser StockSharp-Port behält die Kernlogik bei, beschränkt den Handel auf Kerzen mit geringem Volumen und fügt asymmetrische Schutzaufträge für Long- und Short-Positionen hinzu.

Verwendete Indikatoren

  • Schneller EMA (Kaufbein) – misst die kurzfristige Dynamik für Long-Einstiege.
  • Langsamer EMA (Kaufbein) – stellt den längerfristigen Trendfilter für Long-Einstiege dar.
  • Fast EMA (Sell Leg) – misst die kurzfristige Dynamik für Short-Einstiege.
  • Slow EMA (Sell Leg) – stellt den längerfristigen Trendfilter für Short-Einstiege dar.
  • RSI (Kaufabschnitt) – validiert überverkaufte Bedingungen für Long-Trades.
  • RSI (Verkaufsabschnitt) – validiert überkaufte Bedingungen für Short-Trades.

Handelslogik

  1. Abonnieren Sie die konfigurierte Kerzenserie (Standardzeitrahmen 15 Minuten).
  2. Berechnen Sie alle EMA- und RSI-Indikatoren für jede fertige Kerze.
  3. Signalauswertung überspringen, wenn das Kerzenvolumen den konfigurierten Grenzwert überschreitet (Standard 10).
  4. Kaufbedingung:
    • Schneller EMA minus langsamer EMA liegt unter der Kaufschwelle.
    • Der Wert von RSI liegt unter dem Kaufschwellenwert von RSI.
    • Kein bestehendes Long-Engagement (Nettoposition muss nicht positiv sein).
  5. Verkaufszustand:
    • Schneller EMA (Verkaufszweig) minus langsamer EMA (Verkaufszweig) liegt über dem Verkaufsschwellenwert.
    • RSI (Verkaufsabschnitt) liegt über dem Verkaufsschwellenwert RSI.
    • Es besteht kein Short-Engagement (die Nettoposition darf nicht negativ sein).
  6. Wenn ein Signal ausgelöst wird, stornieren Sie alle ausstehenden Schutzaufträge, führen Sie einen Marktauftrag aus, dessen Größe die Nettoposition auf die gewünschte Seite dreht, und platzieren Sie sofort Take-Profit- und Stop-Loss-Aufträge, die auf die Positionsrichtung zugeschnitten sind.

Risikomanagement

  • Long-Trades setzen einen Take-Profit bei entry + BuyTakeProfitPips * priceStep und einen Stop-Loss bei entry - BuyStopLossPips * priceStep.
  • Short-Trades setzen einen Take-Profit bei entry - SellTakeProfitPips * priceStep und einen Stop-Loss bei entry + SellStopLossPips * priceStep.
  • Bei Schutzaufträgen wird die aktuelle Preisstufe des Wertpapiers wiederverwendet. Ändern Sie die Pip-Parameter, um sie an Instrumente mit unterschiedlichen Tick-Größen anzupassen.

Parameter

Parameter Beschreibung Standard
FastEmaLength Länge des schnellen EMA für Kaufsignale. 23
SlowEmaLength Länge des langsamen EMA für Kaufsignale. 62
FastEma2Length Länge des schnellen EMA für Verkaufssignale. 18
SlowEma2Length Länge des langsamen EMA für Verkaufssignale. 54
RsiPeriod RSI Zeitraum für die Kaufbestätigung. 67
RsiPeriod2 RSI Zeitraum für die Verkaufsbestätigung. 97
BuyDifferenceThreshold Maximale Schnell-Langsam-Differenz von EMA, um Käufe zu ermöglichen. 63
BuyRsiThreshold Maximales RSI-Level, um Käufe zuzulassen. 59
SellDifferenceThreshold Minimale Schnell-Langsam-Differenz EMA, um Verkäufe zu ermöglichen. -57
SellRsiThreshold Mindeststufe RSI, um Verkäufe zu ermöglichen. 60
BuyTakeProfitPips Take-Profit-Distanz (Pips) für Long-Trades. 95
BuyStopLossPips Stop-Loss-Distanz (Pips) für Long-Trades. 100
SellTakeProfitPips Take-Profit-Distanz (Pips) für Short-Trades. 17
SellStopLossPips Stop-Loss-Distanz (Pips) für Short-Trades. 69
OrderVolume Volumen für neu eröffnete Positionen. 0,5
MaxCandleVolume Maximal zulässiges Kerzenvolumen für den Handel. 10
CandleType Für Berechnungen verwendeter Zeitrahmen. 15-Minuten-Kerzen

Nutzungshinweise

  • Stellen Sie sicher, dass das angeschlossene Wertpapier gleichzeitige Markt-, Stop- und Limit-Orders für ein ordnungsgemäßes Risikomanagement unterstützt.
  • Passen Sie die Pip-Einstellungen an, um die Tick-Größe des Instruments widerzuspiegeln, wenn diese vom vom ursprünglichen Experten angenommenen MT4-Punktwert abweicht.
  • Die Strategie basiert auf Nettopositionen; Es wird das gegnerische Engagement abflachen, bevor ein neuer Handel in die entgegengesetzte Richtung etabliert wird.
using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy based on the Sidus v1 expert advisor using EMA and RSI filters.
/// Buys when the fast EMA is sufficiently below the slow EMA and RSI is oversold.
/// Sells when the fast EMA is sufficiently above the slow EMA and RSI is overbought.
/// </summary>
public class SidusV1Strategy : Strategy
{
	private readonly StrategyParam<int> _fastEmaLength;
	private readonly StrategyParam<int> _slowEmaLength;
	private readonly StrategyParam<int> _fastEma2Length;
	private readonly StrategyParam<int> _slowEma2Length;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _rsiPeriod2;
	private readonly StrategyParam<decimal> _buyDifferenceThreshold;
	private readonly StrategyParam<decimal> _buyRsiThreshold;
	private readonly StrategyParam<decimal> _sellDifferenceThreshold;
	private readonly StrategyParam<decimal> _sellRsiThreshold;
	private readonly StrategyParam<decimal> _stopLoss;
	private readonly StrategyParam<decimal> _takeProfit;
	private readonly StrategyParam<DataType> _candleType;

	/// <summary>
	/// Length of the fast EMA for buy signal calculation.
	/// </summary>
	public int FastEmaLength
	{
		get => _fastEmaLength.Value;
		set => _fastEmaLength.Value = value;
	}

	/// <summary>
	/// Length of the slow EMA for buy signal calculation.
	/// </summary>
	public int SlowEmaLength
	{
		get => _slowEmaLength.Value;
		set => _slowEmaLength.Value = value;
	}

	/// <summary>
	/// Length of the fast EMA for sell signal calculation.
	/// </summary>
	public int FastEma2Length
	{
		get => _fastEma2Length.Value;
		set => _fastEma2Length.Value = value;
	}

	/// <summary>
	/// Length of the slow EMA for sell signal calculation.
	/// </summary>
	public int SlowEma2Length
	{
		get => _slowEma2Length.Value;
		set => _slowEma2Length.Value = value;
	}

	/// <summary>
	/// RSI period used for buy signals.
	/// </summary>
	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	/// <summary>
	/// RSI period used for sell signals.
	/// </summary>
	public int RsiPeriod2
	{
		get => _rsiPeriod2.Value;
		set => _rsiPeriod2.Value = value;
	}

	/// <summary>
	/// Threshold for EMA difference to allow buy orders (negative means fast below slow).
	/// </summary>
	public decimal BuyDifferenceThreshold
	{
		get => _buyDifferenceThreshold.Value;
		set => _buyDifferenceThreshold.Value = value;
	}

	/// <summary>
	/// RSI threshold to confirm oversold conditions.
	/// </summary>
	public decimal BuyRsiThreshold
	{
		get => _buyRsiThreshold.Value;
		set => _buyRsiThreshold.Value = value;
	}

	/// <summary>
	/// Threshold for EMA difference to allow sell orders (positive means fast above slow).
	/// </summary>
	public decimal SellDifferenceThreshold
	{
		get => _sellDifferenceThreshold.Value;
		set => _sellDifferenceThreshold.Value = value;
	}

	/// <summary>
	/// RSI threshold to confirm overbought conditions.
	/// </summary>
	public decimal SellRsiThreshold
	{
		get => _sellRsiThreshold.Value;
		set => _sellRsiThreshold.Value = value;
	}

	/// <summary>
	/// Stop loss distance in absolute price units.
	/// </summary>
	public decimal StopLoss
	{
		get => _stopLoss.Value;
		set => _stopLoss.Value = value;
	}

	/// <summary>
	/// Take profit distance in absolute price units.
	/// </summary>
	public decimal TakeProfit
	{
		get => _takeProfit.Value;
		set => _takeProfit.Value = value;
	}

	/// <summary>
	/// Candle type used for indicator calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of the <see cref="SidusV1Strategy"/> class.
	/// </summary>
	public SidusV1Strategy()
	{
		_fastEmaLength = Param(nameof(FastEmaLength), 23)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA Length", "Length of the fast EMA for buy signals", "Indicators");

		_slowEmaLength = Param(nameof(SlowEmaLength), 62)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA Length", "Length of the slow EMA for buy signals", "Indicators");

		_fastEma2Length = Param(nameof(FastEma2Length), 18)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA Length (Sell)", "Length of the fast EMA for sell signals", "Indicators");

		_slowEma2Length = Param(nameof(SlowEma2Length), 54)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA Length (Sell)", "Length of the slow EMA for sell signals", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 67)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period used for buy signals", "Indicators");

		_rsiPeriod2 = Param(nameof(RsiPeriod2), 97)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period (Sell)", "RSI period used for sell signals", "Indicators");

		_buyDifferenceThreshold = Param(nameof(BuyDifferenceThreshold), -100m)
			.SetDisplay("Buy EMA Threshold", "Maximum fast-slow EMA difference to allow buy", "Trading Rules");

		_buyRsiThreshold = Param(nameof(BuyRsiThreshold), 45m)
			.SetDisplay("Buy RSI Threshold", "Maximum RSI level to allow buy", "Trading Rules");

		_sellDifferenceThreshold = Param(nameof(SellDifferenceThreshold), 100m)
			.SetDisplay("Sell EMA Threshold", "Minimum fast-slow EMA difference to allow sell", "Trading Rules");

		_sellRsiThreshold = Param(nameof(SellRsiThreshold), 55m)
			.SetDisplay("Sell RSI Threshold", "Minimum RSI level to allow sell", "Trading Rules");

		_stopLoss = Param(nameof(StopLoss), 500m)
			.SetNotNegative()
			.SetDisplay("Stop Loss", "Stop loss distance in absolute price units", "Risk Management");

		_takeProfit = Param(nameof(TakeProfit), 500m)
			.SetNotNegative()
			.SetDisplay("Take Profit", "Take profit distance in absolute price units", "Risk Management");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles used for calculations", "General");
	}

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		var fastEma = new EMA { Length = FastEmaLength };
		var slowEma = new EMA { Length = SlowEmaLength };
		var fastEma2 = new EMA { Length = FastEma2Length };
		var slowEma2 = new EMA { Length = SlowEma2Length };
		var rsi = new RSI { Length = RsiPeriod };
		var rsi2 = new RSI { Length = RsiPeriod2 };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastEma, slowEma, fastEma2, slowEma2, rsi, rsi2, ProcessCandle)
			.Start();

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

		// Use StartProtection for SL/TP
		var tp = TakeProfit > 0 ? new Unit(TakeProfit, UnitTypes.Absolute) : null;
		var sl = StopLoss > 0 ? new Unit(StopLoss, UnitTypes.Absolute) : null;
		StartProtection(tp, sl);

		base.OnStarted2(time);
	}

	private void ProcessCandle(ICandleMessage candle,
		decimal fastEmaValue,
		decimal slowEmaValue,
		decimal fastEma2Value,
		decimal slowEma2Value,
		decimal rsiValue,
		decimal rsi2Value)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var diffBuy = fastEmaValue - slowEmaValue;
		var diffSell = fastEma2Value - slowEma2Value;

		// Buy when fast EMA is sufficiently below slow EMA and RSI is oversold
		if (diffBuy < BuyDifferenceThreshold && rsiValue < BuyRsiThreshold && Position <= 0)
		{
			if (Position < 0)
				BuyMarket(Math.Abs(Position));
			BuyMarket(Volume);
		}
		// Sell when fast EMA is sufficiently above slow EMA and RSI is overbought
		else if (diffSell > SellDifferenceThreshold && rsi2Value > SellRsiThreshold && Position >= 0)
		{
			if (Position > 0)
				SellMarket(Position);
			SellMarket(Volume);
		}
	}
}