Auf GitHub ansehen

MACross-Strategie

Die Strategie repliziert das Verhalten des ursprünglichen MQL/34176/MACross.mq4-Expertenberaters unter Verwendung des StockSharp-High-Level-API. Es handelt ein einzelnes Instrument mit einem Crossover mit gleitendem Durchschnitt und behält alle Risikokontrollen bei, ausgedrückt in Pips und Kontokapital.

Handelslogik

  1. Zwei einfache gleitende Durchschnitte (SMA) basieren auf dem konfigurierten Kerzentyp:
    • FastPeriod reagiert schnell auf Preisänderungen.
    • SlowPeriod glättet den längerfristigen Trend.
  2. Am Ende jeder fertigen Kerze werden die schnellen und langsamen Durchschnittswerte verglichen:
    • Ein bullischer Crossover (schneller Übergang über langsam) eröffnet eine Long-Position. Jeder aktive Short wird zuerst abgeflacht.
    • Ein bärischer Crossover (schneller Übergang unter langsam) eröffnet eine Short-Position, nachdem eine bestehende Long-Position geschlossen wurde.
  3. Jeder Eintrag verwendet ein festes Marktvolumen, das von LotSize abgeleitet und an den Instrumentenlimits (VolumeStep, MinVolume, MaxVolume) ausgerichtet ist.
  4. Nachdem die Position eröffnet wurde, verfolgt die Strategie zwei in Pips gemessene Risikoziele. Die Pip-Größe wird automatisch aus Security.Decimals (oder PriceStep als Fallback) abgeleitet:
    • TakeProfitPips definiert den Abstand zum Gewinnziel. Ein Treffer führt zu einem Marktausstieg in die aktuelle Richtung.
    • StopLossPips definiert den Schutzstoppabstand. Bei einem Verstoß wird die Position sofort geschlossen.
  5. Der Handel kann vom MinEquity-Wächter unterbrochen werden. Wenn der aktuelle Portfoliowert unter dem Schwellenwert liegt, verwaltet die Strategie weiterhin die aktive Position, lässt jedoch keine neuen Einträge zu.

Alle Berechnungen funktionieren nur bei fertigen Kerzen und stimmen vollständig mit dem ursprünglichen Expertenberater überein, der auf einen neuen Balken wartete, bevor er die gleitenden Durchschnitte auswertete.

Visualisierung

Wenn ein Diagrammbereich verfügbar ist, werden die Strategiediagramme wie folgt dargestellt:

  • Geben Sie Kerzen aus der abonnierten Serie ein.
  • Die schnellen und langsamen SMAs.
  • Eigene Trades zur Hervorhebung von Ein- und Ausstiegen, die durch die Crossover-Regeln ausgelöst werden.

Parameter

Name Typ Standard Beschreibung
FastPeriod int 8 Länge des schnellen SMA, der Crossover-Signale erzeugt.
SlowPeriod int 20 Länge des langsamen SMA, der als Referenztrendlinie verwendet wird.
TakeProfitPips decimal 20 Gewinnzieldistanz ausgedrückt in Pips. Die Pip-Größe wird aus den Dezimalstellen des Instruments abgeleitet.
StopLossPips decimal 20 Schutzstoppabstand in Pips. Verwendet die gleiche Pip-Größenberechnung wie das Gewinnziel.
LotSize decimal 1 Grundauftragsvolumen. Die Strategie rundet den Wert auf die nächste zulässige Größe, bevor Marktaufträge gesendet werden.
MinEquity decimal 100 Mindestkontoguthaben. Solange der Portfoliowert unter diesem Niveau liegt, werden neue Geschäfte blockiert.
CandleType DataType TimeSpan.FromMinutes(1).TimeFrame() Kerzenreihe, die für SMA-Berechnungen und Signalauswertung verwendet wird.

Unterschiede zur MQL-Version

  • Der ursprüngliche MQL-Experte hat Stop-Loss- und Take-Profit-Preise für OrderSend als Null angenommen. Der StockSharp-Port emuliert das gleiche Verhalten mit manuellen Exits, die den Schlusskurs jeder fertigen Kerze überwachen.
  • Die Eigenkapitalvalidierung (cekMinEquity) liest jetzt Portfolio.CurrentValue und Portfolio.BeginValue statt AccountEquity(), behält aber die Schwellenwertlogik bei.
  • Die Pip-Größenerkennung spiegelt den GetPipPoint-Helfer wider: 2- oder 3-stellige Anführungszeichen verwenden 0,01, 4- oder 5-stellige Anführungszeichen verwenden 0,0001, andernfalls wird PriceStep verwendet.

Die resultierende Strategie kann über alle exponierten Parameter optimiert werden und lässt sich nahtlos mit der Diagramm- und Risikomanagement-Infrastruktur von StockSharp kombinieren.

namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// MA Cross strategy: SMA crossover.
/// Buys when fast SMA crosses above slow SMA, sells on cross below.
/// </summary>
public class MacrossStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

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

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

	public MacrossStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 30)
			.SetGreaterThanZero()
			.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
	}

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevFast = 0;
		_prevSlow = 0;
		_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 fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;

		if (_hasPrev)
		{
			if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
				BuyMarket();
			else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
				SellMarket();
		}
		else
		{
			if (fastValue > slowValue && Position <= 0)
				BuyMarket();
			else if (fastValue < slowValue && Position >= 0)
				SellMarket();
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
		_hasPrev = true;
	}
}