Auf GitHub ansehen

Strategie mit dreifachem gleitendem Durchschnitt-Crossover

Diese Strategie handelt auf Basis der Beziehung zwischen drei gleitenden Durchschnitten: schnell, mittel und langsam. Sie ist eine Konvertierung des MQL-Experten X3MA_EA_V2_0.

Handelslogik

  • Einstieg
    • Wenn EnableEntryMediumSlowCross wahr ist, wird eine Long-Position eröffnet, wenn der mittlere gleitende Durchschnitt den langsamen von unten kreuzt. Der umgekehrte Crossover löst einen Short-Einstieg aus.
    • Wenn die Option falsch ist, wartet die Strategie darauf, dass der schnelle Durchschnitt den mittleren kreuzt, während beide auf derselben Seite des langsamen bleiben. Long-Positionen erfordern fast > medium > slow, Short-Positionen erfordern fast < medium < slow.
  • Ausstieg
    • Wenn EnableExitFastSlowCross wahr ist, werden offene Positionen geschlossen, wenn sich der schnelle und langsame Durchschnitt in die entgegengesetzte Richtung kreuzen.

Alle Signale werden an abgeschlossenen Kerzen ausgewertet.

Parameter

Name Beschreibung
FastMaLength Periode des schnellen gleitenden Durchschnitts.
MediumMaLength Periode des mittleren gleitenden Durchschnitts.
SlowMaLength Periode des langsamen gleitenden Durchschnitts.
EnableEntryMediumSlowCross Einstiege bei Mittel-/Langsam-Crossover erlauben.
EnableExitFastSlowCross Positionen bei Schnell-/Langsam-Crossover schließen.
CandleType Zeitrahmen der Kerzen.

Hinweise

Die Strategie verwendet die High-Level-API mit SubscribeCandles und Bind. Indikatorwerte werden über den ProcessCandle-Callback abgerufen, ohne GetValue zu verwenden. Schutzlogik wird mit StartProtection() in OnStarted aktiviert.

using System;
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>
/// Triple EMA crossover strategy.
/// </summary>
public class X3MaEaV20Strategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _midPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevMid;
	private bool _hasPrev;

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

	public X3MaEaV20Strategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast MA", "Fast EMA period", "MA");
		_midPeriod = Param(nameof(MidPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("Mid MA", "Mid EMA period", "MA");
		_slowPeriod = Param(nameof(SlowPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("Slow MA", "Slow EMA period", "MA");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0;
		_prevMid = 0;
		_hasPrev = false;
	}

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

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

		SubscribeCandles(CandleType)
			.Bind(fast, mid, slow, ProcessCandle)
			.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal midVal, decimal slowVal)
	{
		if (candle.State != CandleStates.Finished) return;

		if (!_hasPrev)
		{
			_prevFast = fastVal;
			_prevMid = midVal;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevMid && fastVal > midVal;
		var crossDown = _prevFast >= _prevMid && fastVal < midVal;

		if (crossUp && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (crossDown && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevFast = fastVal;
		_prevMid = midVal;
	}
}