Auf GitHub ansehen

Strategie MultiStrategyEA v1.2 (StockSharp Port)

Überblick

Diese Strategie ist ein High-Level-StockSharp-Port des MetaTrader-Expertenberaters MultiStrategyEA v1.2. Das Original EA fasst sieben Oszillatoren zusammen und verwaltet mehrere Ordnungsgitter. Die StockSharp-Version konzentriert sich auf den Aspekt der Signalerzeugung und handelt eine einzelne Nettoposition, die durch einen Konsens zwischen den Indikatormodulen bestimmt wird. Auftragsverwaltung, Geldverwaltungsprofile, Raster und Wiederherstellungsfunktionen aus dem MT5-Code werden bewusst weggelassen, um die Implementierung an die übergeordnete API von StockSharp anzupassen und die Übersichtlichkeit zu wahren.

Module

Die Strategie bewertet die folgenden Indikatormodule im ausgewählten Zeitrahmen:

  1. Beschleunigungs-/Verzögerungsoszillator (AC) – Verwendet die Differenz zwischen dem Awesome-Oszillator und seinem 5-Perioden-SMA. Erfordert, dass der aktuelle Wert den Schwellenwert AcLevel überschreitet und relativ zum vorherigen Messwert ansteigt (oder abfällt).
  2. Durchschnittlicher Richtungsindex (ADX) – Bestätigt Trends, wenn die ADX-Stärke über AdxTrendLevel liegt und die vorherrschende Richtungsbewegung auch AdxDirectionalLevel überschreitet.
  3. Toller Oszillator (AO) – Erkennt Impulsausbrüche, wenn der Oszillator AoLevel überschreitet und in die gleiche Richtung weiterläuft.
  4. DeMarker – Zeigt mögliche Umkehrungen an, wenn der Oszillator überverkaufte (100 - DeMarkerThreshold) oder überkaufte (DeMarkerThreshold) Bereiche verlässt.
  5. Force-Index + Bollinger-Bänder – Erfordert, dass der Preis ein Bollinger-Band berührt, während der Force-Index (im Port genau wie im MT5-Skript skaliert) ein Momentum über ForceConfirmationLevel bestätigt. Ein optionales BandDistanceFilter weist Signale zurück, wenn die Bandbreite, gemessen in Pips, zu schmal oder zu breit ist.
  6. Money Flow Index (MFI) – Ähnlich wie DeMarker; reagiert auf überkaufte und überverkaufte Zonen, die durch MfiThreshold bestimmt werden.
  7. MACD + Stochastic – Erfordert, dass sowohl MACD (MacdLevel) als auch Stochastic (StochasticLevel) die gleiche Richtungsneigung bestätigen. MACD muss über/unter dem Füllstand und über/unter seiner Signallinie liegen. Stochastic muss über/unter dem Schwellenwert und über/unter der Signallinie liegen.

Jedes Modul gibt eine Kauf-, Verkaufs- oder Neutral-Stimme basierend auf der letzten fertigen Kerze ab.

Konsenslogik

  • Wenn TradeAllStrategies true ist (Standard), wartet die Strategie, bis mindestens RequiredConfirmations bullische Stimmen und null bärische Stimmen erscheinen, bevor sie eine Long-Position eingeht. Die gleiche Logik gilt auch für Kurzfilme.
  • Wenn TradeAllStrategies falsch ist, reicht eine einzige bullische oder bärische Stimme für den Handel aus.
  • Wenn CloseInReverse aktiviert ist, schließt die Strategie sofort eine entgegengesetzte Position, bevor sie eine neue eröffnet.

Die Implementierung betreibt nur eine Gesamtposition und versucht nicht, die ursprüngliche Auftragsbuchhaltung pro Modul von EA wiederherzustellen.

Risikomanagement

  • StopLossPips und TakeProfitPips werden mithilfe des PriceStep des Instruments in Preisversätze umgewandelt. Bei Symbolen mit 3 oder 5 Dezimalstellen wird die Pip-Größe automatisch mit 10 multipliziert, um das FX-Pip-Verhalten nachzuahmen.
  • Stopps und Ziele werden bei jeder fertigen Kerze anhand der Kerzenhochs/-tiefs überprüft. Wenn einer der Schwellenwerte erreicht wird, wird die gesamte Position geschlossen.

Unterschiede zum MT5 Expert Advisor

  • Keine Raster-, Martingal- oder Wiederherstellungsfunktionen. Die Positionsgröße wird über den Parameter Volume festgelegt.
  • Close-Signal-Varianten (CloseOrdersType-Optionen in MT5) sind nicht implementiert; Ausstiege basieren auf einem globalen Stop-Loss/Take-Profit oder dem optionalen Reverse-on-Oposite-Signal-Verhalten.
  • Die Indikatorkonfiguration in StockSharp spiegelt die Hauptidee jedes Moduls wider, unterstützt jedoch nur die gängigste Interpretation anstelle der vielen Modusaufzählungen, die im Originalskript zu finden sind.
  • Geldverwaltungsblöcke (automatisches Lot, Kontoschutz, symbolspezifische Pip-Bewertung) sind für diesen High-Level-Port nicht möglich.

Parameter

Parameter Beschreibung
CandleType Von jedem Indikatormodul verwendete Datenreihe.
Volume Gehandeltes Nettovolumen, wenn ein Konsenssignal erscheint.
TradeAllStrategies Ermöglicht Konsensabstimmung; andernfalls löst jede einzelne Stimme einen Handel aus.
RequiredConfirmations Anzahl der passenden bullischen oder bärischen Stimmen, die erforderlich sind, wenn ein Konsens ermöglicht wird.
CloseInReverse Schließen Sie eine bestehende Position, bevor Sie die gegenüberliegende Seite öffnen.
StopLossPips / TakeProfitPips Schutzstopp und Gewinnziel, gemessen in Pips.
UseAcModule, AcLevel Umschalter und Schwellenwert für das Accelerator Oscillator-Modul.
UseAdxModule, AdxPeriod, AdxTrendLevel, AdxDirectionalLevel ADX-Konfiguration.
UseAoModule, AoLevel Tolle Oszillatorkonfiguration.
UseDeMarkerModule, DeMarkerPeriod, DeMarkerThreshold Einstellungen des DeMarker-Oszillators.
UseForceBollingerModule, BollingerPeriod, BollingerDeviation, ForceConfirmationLevel, BandDistanceFilter Index + Bollinger Bandfiltereinstellungen erzwingen.
UseMfiModule, MfiPeriod, MfiThreshold Einstellungen für den Geldflussindex.
UseMacdStochasticModule, MacdFastPeriod, MacdSlowPeriod, MacdSignalPeriod, MacdLevel, StochasticPeriod, StochasticSignalPeriod, StochasticSlowing, StochasticLevel Kombinationskonfiguration aus MACD und Stochastic.

Nutzungshinweise

  1. Hängen Sie die Strategie an ein Instrument mit ausreichend historischen Daten an, damit alle Indikatoren gebildet werden können.
  2. Konfigurieren Sie den Zeitrahmen und die Modulschwellenwerte entsprechend den gewünschten Marktbedingungen. Die Standardwerte replizieren die in den MT5-EA-Eingaben verwendeten Werte.
  3. Die Konsenslogik hängt davon ab, wie viele Module aktiv sind. Wenn Sie Module deaktivieren, sollten Sie erwägen, RequiredConfirmations entsprechend zu senken.
  4. Da die Strategie eine einzelne Nettoposition handelt, eignet sie sich für den Einsatz in Designer-, Runner- oder anderen StockSharp-High-Level-Umgebungen ohne zusätzliches Portfolio-Routing.

Haftungsausschluss

Dieser Port konzentriert sich auf die Signalparität und nicht auf die Reproduktion des gesamten Risiko- und Geldmanagement-Stacks des ursprünglichen MetaTrader-Experten. Die vereinfachte Architektur erleichtert das Testen, Erweitern oder Integrieren in StockSharp-basierte Lösungen, die Ergebnisse weichen jedoch von der MT5-Version ab, als komplexe Funktionen (Raster, Wiederherstellungslose, Teilabschlüsse) der Hauptleistungstreiber waren.

namespace StockSharp.Samples.Strategies;

using System;

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

/// <summary>
/// Simplified port of the MetaTrader expert advisor "MultiStrategyEA v1.2".
/// Combines multiple oscillators (RSI, Stochastic, MACD, Bollinger, ADX)
/// and requires a configurable number of bullish or bearish confirmations before entering a trade.
/// </summary>
public class MultiEaV12Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _requiredConfirmations;

	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _rsiUpper;
	private readonly StrategyParam<decimal> _rsiLower;

	private readonly StrategyParam<int> _stochKPeriod;
	private readonly StrategyParam<int> _stochDPeriod;
	private readonly StrategyParam<decimal> _stochUpper;
	private readonly StrategyParam<decimal> _stochLower;

	private readonly StrategyParam<int> _bollingerPeriod;
	private readonly StrategyParam<decimal> _bollingerDeviation;

	private readonly StrategyParam<int> _adxPeriod;
	private readonly StrategyParam<decimal> _adxTrendLevel;

	private readonly StrategyParam<int> _macdFast;
	private readonly StrategyParam<int> _macdSlow;
	private readonly StrategyParam<int> _macdSignal;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int RequiredConfirmations { get => _requiredConfirmations.Value; set => _requiredConfirmations.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public decimal RsiUpper { get => _rsiUpper.Value; set => _rsiUpper.Value = value; }
	public decimal RsiLower { get => _rsiLower.Value; set => _rsiLower.Value = value; }
	public int StochKPeriod { get => _stochKPeriod.Value; set => _stochKPeriod.Value = value; }
	public int StochDPeriod { get => _stochDPeriod.Value; set => _stochDPeriod.Value = value; }
	public decimal StochUpper { get => _stochUpper.Value; set => _stochUpper.Value = value; }
	public decimal StochLower { get => _stochLower.Value; set => _stochLower.Value = value; }
	public int BollingerPeriod { get => _bollingerPeriod.Value; set => _bollingerPeriod.Value = value; }
	public decimal BollingerDeviation { get => _bollingerDeviation.Value; set => _bollingerDeviation.Value = value; }
	public int AdxPeriod { get => _adxPeriod.Value; set => _adxPeriod.Value = value; }
	public decimal AdxTrendLevel { get => _adxTrendLevel.Value; set => _adxTrendLevel.Value = value; }
	public int MacdFast { get => _macdFast.Value; set => _macdFast.Value = value; }
	public int MacdSlow { get => _macdSlow.Value; set => _macdSlow.Value = value; }
	public int MacdSignal { get => _macdSignal.Value; set => _macdSignal.Value = value; }

	public MultiEaV12Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_requiredConfirmations = Param(nameof(RequiredConfirmations), 3)
			.SetDisplay("Required Confirmations", "Number of modules required for entry", "Consensus");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetDisplay("RSI Period", "RSI length", "RSI");

		_rsiUpper = Param(nameof(RsiUpper), 65m)
			.SetDisplay("RSI Upper", "Overbought level", "RSI");

		_rsiLower = Param(nameof(RsiLower), 35m)
			.SetDisplay("RSI Lower", "Oversold level", "RSI");

		_stochKPeriod = Param(nameof(StochKPeriod), 10)
			.SetDisplay("Stochastic %K", "%K period", "Stochastic");

		_stochDPeriod = Param(nameof(StochDPeriod), 3)
			.SetDisplay("Stochastic %D", "%D period", "Stochastic");

		_stochUpper = Param(nameof(StochUpper), 70m)
			.SetDisplay("Stoch Upper", "Overbought", "Stochastic");

		_stochLower = Param(nameof(StochLower), 30m)
			.SetDisplay("Stoch Lower", "Oversold", "Stochastic");

		_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
			.SetDisplay("Bollinger Period", "BB length", "Bollinger");

		_bollingerDeviation = Param(nameof(BollingerDeviation), 2m)
			.SetDisplay("Bollinger Deviation", "BB width", "Bollinger");

		_adxPeriod = Param(nameof(AdxPeriod), 14)
			.SetDisplay("ADX Period", "ADX length", "ADX");

		_adxTrendLevel = Param(nameof(AdxTrendLevel), 20m)
			.SetDisplay("ADX Trend Level", "Min ADX for trend", "ADX");

		_macdFast = Param(nameof(MacdFast), 12)
			.SetDisplay("MACD Fast", "Fast EMA period", "MACD");

		_macdSlow = Param(nameof(MacdSlow), 26)
			.SetDisplay("MACD Slow", "Slow EMA period", "MACD");

		_macdSignal = Param(nameof(MacdSignal), 9)
			.SetDisplay("MACD Signal", "Signal line period", "MACD");
	}

	/// <inheritdoc />
	public override System.Collections.Generic.IEnumerable<(StockSharp.BusinessEntities.Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		var stochastic = new StochasticOscillator();
		stochastic.K.Length = StochKPeriod;
		stochastic.D.Length = StochDPeriod;

		var bollinger = new BollingerBands { Length = BollingerPeriod, Width = BollingerDeviation };

		var adx = new AverageDirectionalIndex { Length = AdxPeriod };

		var macd = new MovingAverageConvergenceDivergenceSignal();
		macd.Macd.ShortMa.Length = MacdFast;
		macd.Macd.LongMa.Length = MacdSlow;
		macd.SignalMa.Length = MacdSignal;

		var subscription = SubscribeCandles(CandleType);

		subscription
			.BindEx(rsi, stochastic, bollinger, adx, macd, ProcessCandle)
			.Start();

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

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue rsiVal, IIndicatorValue stochVal, IIndicatorValue bbVal, IIndicatorValue adxVal, IIndicatorValue macdVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!rsiVal.IsFinal || !stochVal.IsFinal || !bbVal.IsFinal || !adxVal.IsFinal || !macdVal.IsFinal)
			return;

		if (!rsiVal.IsFormed || !stochVal.IsFormed || !bbVal.IsFormed || !adxVal.IsFormed || !macdVal.IsFormed)
			return;

		var rsi = rsiVal.GetValue<decimal>();
		var stoch = (StochasticOscillatorValue)stochVal;
		var stochK = stoch.K ?? 50m;
		var bb = (BollingerBandsValue)bbVal;
		var bbUpper = bb.UpBand ?? candle.ClosePrice;
		var bbLower = bb.LowBand ?? candle.ClosePrice;
		var adxTyped = (AverageDirectionalIndexValue)adxVal;
		var adxMain = adxTyped.MovingAverage ?? 0m;
		var adxPlus = adxTyped.Dx.Plus ?? 0m;
		var adxMinus = adxTyped.Dx.Minus ?? 0m;
		var macdTyped = (MovingAverageConvergenceDivergenceSignalValue)macdVal;
		var macdLine = macdTyped.Macd ?? 0m;
		var macdSignalLine = macdTyped.Signal ?? 0m;

		var close = candle.ClosePrice;

		// Count bullish and bearish signals from each module
		var bullish = 0;
		var bearish = 0;

		// Module 1: RSI
		if (rsi < RsiLower) bullish++;
		else if (rsi > RsiUpper) bearish++;

		// Module 2: Stochastic
		if (stochK < StochLower) bullish++;
		else if (stochK > StochUpper) bearish++;

		// Module 3: Bollinger Bands
		if (close <= bbLower) bullish++;
		else if (close >= bbUpper) bearish++;

		// Module 4: ADX directional
		if (adxMain >= AdxTrendLevel)
		{
			if (adxPlus > adxMinus) bullish++;
			else if (adxMinus > adxPlus) bearish++;
		}

		// Module 5: MACD
		if (macdLine > macdSignalLine && macdLine > 0) bullish++;
		else if (macdLine < macdSignalLine && macdLine < 0) bearish++;

		var minConfirmations = RequiredConfirmations;

		// Enter on consensus
		if (bullish >= minConfirmations && bearish == 0 && Position <= 0)
		{
			BuyMarket();
		}
		else if (bearish >= minConfirmations && bullish == 0 && Position >= 0)
		{
			SellMarket();
		}
		// Exit when consensus breaks
		else if (Position > 0 && bearish >= 2)
		{
			SellMarket();
		}
		else if (Position < 0 && bullish >= 2)
		{
			BuyMarket();
		}
	}
}