Auf GitHub ansehen

EMA 6/12 Crossover-Strategie

Diese Strategie repliziert den MetaTrader-Expertenberater, der den Übergang zwischen einem schnellen EMA(6) und einem langsamen EMA(12) tauscht. Es abonniert standardmäßig stündliche Kerzen, berechnet beide gleitenden Durchschnitte und wartet auf einen bestätigten Crossover am Ende einer Kerze, bevor es handelt.

Handelslogik

  • Eintrag:
    • Ein bullisches Signal erscheint, wenn EMA(6) EMA(12) überschreitet. Die Strategie eröffnet eine Long-Position, wenn keine aktive Position vorhanden ist.
    • Ein rückläufiges Signal erscheint, wenn EMA(6) unter EMA(12) fällt. Die Strategie eröffnet eine Short-Position, wenn keine aktive Position vorhanden ist.
  • Ausgang:
    • Wenn UseCloseSignals aktiviert ist (Standardverhalten), schließt die Strategie die aktuelle Position, sobald ein entgegengesetzter Crossover erkannt wird. Es wartet auf den nächsten Crossover, bevor es einen neuen Trade eröffnet, und spiegelt damit den ursprünglichen Expert Advisor wider.
    • Optionale Take-Profit- und Trailing-Stop-Schutzmaßnahmen werden über den integrierten StartProtection-Helper von StockSharp verwaltet.
  • Positionsgröße:
    • Bestellungen verwenden den Parameter OrderVolume (Standard 1 Los). Vor dem Versenden von Bestellungen werden die Volumina an die Sicherheitseinstellungen angepasst.

Risikomanagement

  • Trailing Stop: Wandelt die ursprüngliche „Punkte“-Einstellung in Preisschritte um. Wenn der Stop größer als Null ist, bewegt er sich automatisch in die Richtung des Handels, sobald die Position profitabel wird.
  • Take Profit: Ausgedrückt in Preisschritten. Zum Deaktivieren auf Null setzen.
  • Bei der Strategie werden niemals Durchschnittswerte nach unten oder Pyramiden gebildet. Es ist nur eine Position pro Symbol zulässig.

Parameter

Parameter Beschreibung
CandleType Zeitrahmen, der zum Aufbau von Kerzen und EMAs verwendet wird. Der Standardwert ist 1 Stunde.
OrderVolume Handelsgröße in Losen.
ShortEmaLength Zeitraum für das Fasten EMA (Standard 6).
LongEmaLength Zeitraum für den langsamen EMA (Standard 12).
UseCloseSignals Schließen Sie die aktuelle Position an einer gegenüberliegenden Kreuzung (Standard: aktiviert).
TrailingStopSteps Nachlaufdistanz in Preisschritten. Null deaktiviert das Nachziehen.
TakeProfitSteps Nehmen Sie die Gewinndistanz in Preisschritten. Null deaktiviert es.

Notizen

  • Signale werden nur bei fertigen Kerzen verarbeitet, um Intrabar-Rauschen zu vermeiden.
  • Die vorherigen EMA-Werte werden jedes Mal zurückgesetzt, wenn die Position auf Null zurückkehrt, um eine saubere Erkennung für den nächsten Crossover sicherzustellen.
  • Alle Codekommentare sind auf Englisch verfasst und beim Einrücken werden Tabulatoren gemäß den Projektrichtlinien verwendet.
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>
/// EMA 6/12 crossover strategy.
/// Buys when EMA(6) crosses above EMA(12).
/// Sells when EMA(6) crosses below EMA(12).
/// </summary>
public class Ema612Strategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

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

	public Ema612Strategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 6)
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

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

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

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }

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

		_hasPrev = false;

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

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

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

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_hasPrev = true;
			return;
		}

		if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}