Auf GitHub ansehen

Dreifache SMA Crossover-Strategie

Überblick

Die Triple-SMA-Crossover-Strategie repliziert den ursprünglichen MQL-Expertenberater 3sma.mq4. Das System analysiert drei einfache gleitende Durchschnitte (SMA), die auf der Grundlage des Schlusskurses berechnet werden, und handelt, wenn der kurzfristige Trend mit den mittel- und langfristigen Durchschnittswerten übereinstimmt. Bei der Konvertierung bleiben die ursprünglichen Handelsregeln erhalten, während sie gleichzeitig an die übergeordnete Strategie StockSharp API angepasst werden.

Handelslogik

  1. Berechnen Sie drei SMAs mit konfigurierbaren Zeiträumen.
  2. Verlassen Sie bestehende Long-Positionen, wenn der schnelle SMA unter den mittleren SMA fällt.
  3. Bestehende Short-Positionen verlassen, wenn der schnelle SMA über den mittleren SMA steigt.
  4. Geben Sie eine neue Long-Position ein, wenn:
    • Schnell SMA liegt mindestens um die konfigurierte Spanne über dem Mittelwert SMA.
    • Der mittlere SMA liegt mindestens um die konfigurierte Spanne über dem langsamen SMA.
    • Derzeit ist keine Long-Position offen.
  5. Geben Sie eine neue Short-Position ein, wenn:
    • Schnell SMA liegt mindestens um die konfigurierte Spanne unter dem Mittelwert SMA.
    • Der mittlere SMA liegt mindestens um die konfigurierte Spanne unter dem langsamen SMA.
    • Derzeit ist keine Short-Position offen.

Parameter

  • Kerzentyp – Primärer Zeitrahmen, der zur Berechnung der gleitenden Durchschnitte verwendet wird.
  • Schnelle SMA-Länge – Zeitraum für die schnelle SMA (MQL-Eingabe SMA1).
  • Medium SMA Länge – Zeitraum für das Medium SMA (MQL Eingabe SMA2).
  • Langsame SMA-Länge – Zeitraum für die langsame SMA (MQL-Eingabe SMA3).
  • SMA Spread Steps – Zusätzlicher Filter, der erfordert, dass SMAs um eine Reihe von Preisschritten divergieren (MQL Eingabe SMAspread).
  • Handelsvolumen – Auftragsvolumen, das beim Öffnen von Positionen verwendet wird (MQL Eingabe lots).

Notizen

  • Die Stop-Loss-Behandlung der Version MQL wird weggelassen, da sie im Quellskript deaktiviert wurde.
  • Bei allen Ausstiegen handelt es sich um Marktaufträge, die dem unkomplizierten Verhalten des ursprünglichen Experten entsprechen.
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>
/// Triple SMA crossover strategy.
/// Goes long when fast > medium > slow, short when fast less than medium less than slow.
/// Exits when fast crosses medium in opposite direction.
/// </summary>
public class TripleSmaCrossoverStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _mediumPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevMed;
	private bool _hasPrev;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int MediumPeriod { get => _mediumPeriod.Value; set => _mediumPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public TripleSmaCrossoverStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 5)
			.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");

		_mediumPeriod = Param(nameof(MediumPeriod), 10)
			.SetDisplay("Medium SMA", "Medium SMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 20)
			.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0m;
		_prevMed = 0m;
		_hasPrev = false;
	}

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

		_hasPrev = false;

		var fast = new SimpleMovingAverage { Length = FastPeriod };
		var medium = new SimpleMovingAverage { Length = MediumPeriod };
		var slow = new SimpleMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, medium, slow, ProcessCandle)
			.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal med, decimal slow)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevMed = med;
			_hasPrev = true;
			return;
		}

		// Bullish alignment: fast > medium > slow
		if (fast > med && med > slow && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Bearish alignment: fast < medium < slow
		else if (fast < med && med < slow && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
		// Exit long when fast crosses below medium
		else if (Position > 0 && _prevFast >= _prevMed && fast < med)
		{
			SellMarket();
		}
		// Exit short when fast crosses above medium
		else if (Position < 0 && _prevFast <= _prevMed && fast > med)
		{
			BuyMarket();
		}

		_prevFast = fast;
		_prevMed = med;
	}
}