Auf GitHub ansehen

Wajdyss MA Expertenstrategie

Überblick

Die Wajdyss MA Expert Strategy ist eine C#-Portierung des MetaTrader 4 Expert Advisors „wajdyss MA expert v3“. Es vergleicht zwei gleitende Durchschnitte, die mit unabhängigen Zeiträumen, Berechnungsmodi, Verschiebungen und angewendeten Preisen konfiguriert sind. Ein bullischer Crossover des schnellen Durchschnitts über den langsamen Durchschnitt eröffnet ein Long-Engagement, während ein bärischer Crossover ein Short-Engagement eröffnet. Die Konvertierung reproduziert die ursprünglichen Money-Management-Regeln, optionale automatische Schließung gegensätzlicher Geschäfte und Liquidationsfilter am Ende des Tages/am Ende der Woche.

Handelslogik

  1. Abonnieren Sie die ausgewählten CandleType (standardmäßig 15-Minuten-Kerzen) und berechnen Sie die schnellen und langsamen gleitenden Durchschnitte mithilfe der ausgewählten MovingAverageMethod- und PriceSource-Einstellungen für jedes Bein.
  2. Speichern Sie die Indikatorwerte für fertige Kerzen. Bewerten Sie ein bullisches Signal, wenn der schnelle Durchschnitt (mit seiner konfigurierten Verschiebung) über dem langsamen Durchschnitt des letzten geschlossenen Balkens liegt, während er vor zwei Balken unter diesem lag. Bewerten Sie ein bärisches Signal mit der umgekehrten Bedingung.
  3. Erzwingen Sie eine Abklingzeit zwischen neuen Einträgen in die gleiche Richtung. Die Strategie muss nach dem letzten Trade dieser Seite mindestens eine volle Kerze des abonnierten Zeitrahmens warten und spiegelt damit den globalen Variablen-Timing-Guard der MT4-Version wider.
  4. Wenn AutoCloseOpposite aktiviert ist, stornieren Sie Arbeitsaufträge und kehren Sie das Engagement in einer einzigen Marktorder um: Das neue Auftragsvolumen umfasst alle ausstehenden Positionen in die entgegengesetzte Richtung, sodass das Konto sofort umgedreht wird.
  5. Wenden Sie Tages- und Freitagsabschlussfilter an. Nach dem konfigurierten DailyCloseHour/DailyCloseMinute oder FridayCloseHour/FridayCloseMinute werden alle Positionen abgeflacht und neue Trades bis zur nächsten Sitzung blockiert.

Risiko- und Geldmanagement

  • TakeProfitPips, StopLossPips und TrailingStopPips werden in ganzen Pips interpretiert. Die Implementierung wandelt sie unter Verwendung der Sicherheitsmetadaten in Preisschritte um und steuert die StartProtection-Engine von StockSharp mit Marktausgängen für Parität mit der ursprünglichen Trailing-Logik.
  • UseMoneyManagement emuliert die MT4-Lotberechnung: volume = (account_balance / BalanceReference) * InitialVolume. Umtauschgrenzen werden durch Volumenschritt-, Mindest- und Höchstprüfungen eingehalten.
  • Wenn die Geldverwaltung deaktiviert ist, verwenden Bestellungen direkt InitialVolume.

Parameter

Parameter Typ Standard Beschreibung
FastPeriod int 10 Periode des schnellen gleitenden Durchschnitts.
FastShift int 0 Balken zum Verschieben des schnellen Durchschnitts vor dem Vergleich der Crossover-Werte.
FastMethod MovingAverageMethod Ema Gleitender Durchschnittsmodus für die schnelle Linie (Sma, Ema, Smma, Lwma).
FastPriceType PriceSource Close Der Kerzenpreis floss in den sich schnell bewegenden Durchschnitt ein (Close, Open, High, Low, Median, Typical, Weighted).
SlowPeriod int 20 Periode des langsamen gleitenden Durchschnitts.
SlowShift int 0 Balken zur Verschiebung des langsamen Durchschnitts vor dem Vergleich.
SlowMethod MovingAverageMethod Ema Moving-Average-Modus für die langsame Linie.
SlowPriceType PriceSource Close Der Kerzenpreis trug zum langsamen Durchschnitt bei.
TakeProfitPips decimal 100 Abstand zum Gewinnziel in Pips (zum Deaktivieren auf 0 setzen).
StopLossPips decimal 50 Abstand zum Schutzstopp in Pips (zum Deaktivieren auf 0 einstellen).
TrailingStopPips decimal 0 Trailing-Stop-Distanz in Pips (zum Deaktivieren auf 0 setzen).
AutoCloseOpposite bool true Schließen Sie das gegnerische Engagement, bevor Sie einen neuen Trade in die andere Richtung eröffnen.
InitialVolume decimal 0.1 Bestimmen Sie das Handelsvolumen, bevor Sie das Money-Management anwenden.
UseMoneyManagement bool true Aktivieren Sie die ausgleichsbasierte Positionsgrößenbestimmung.
BalanceReference decimal 1000 Divisor, der beim Skalieren des Volumens mit dem Kontostand verwendet wird.
DailyCloseHour int 23 Stunde (0-23), nach der tägliche Positionen geschlossen werden.
DailyCloseMinute int 45 Minutenkomponente des täglichen Abschlussfilters.
FridayCloseHour int 22 Stunde (0-23), nach der der Freitagshandel endet.
FridayCloseMinute int 45 Minutenkomponente des Freitagsschlussfilters.
CandleType DataType 15m Zeitrahmen Kerzenserien, die für Berechnungen und Abklingzeiten verwendet werden.

Notizen

  • Die Strategie basiert ausschließlich auf dem übergeordneten StockSharp API: Kerzen werden über SubscribeCandles verarbeitet, Indikatorbindungen versorgen gleitende Durchschnitte und StartProtection verwaltet Stops/Take-Profit/Trailing-Orders.
  • Beim Positionsflattening werden Marktaufträge verwendet, um die unmittelbaren Schließungen entgegengesetzter Tickets durch den MT4-Experten widerzuspiegeln.
  • In diesem Ordner ist keine Python-Übersetzung enthalten; Es wird nur die C#-Implementierung bereitgestellt.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Wajdyss MA Expert: Fast/slow EMA crossover with ATR stops.
/// </summary>
public class WajdyssMaExpertStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;

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

		_fastLength = Param(nameof(FastLength), 10)
			.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators");

		_slowLength = Param(nameof(SlowLength), 20)
			.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators");

		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period for stops.", "Indicators");
	}

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

	/// <inheritdoc />
	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevFast = 0;
		_prevSlow = 0;
		_entryPrice = 0;
	}

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

		_prevFast = 0;
		_prevSlow = 0;
		_entryPrice = 0;

		var fast = new ExponentialMovingAverage { Length = FastLength };
		var slow = new ExponentialMovingAverage { Length = SlowLength };
		var atr = new AverageTrueRange { Length = AtrLength };

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

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

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

		if (_prevFast == 0 || _prevSlow == 0 || atrVal <= 0)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			return;
		}

		var close = candle.ClosePrice;

		// Exit
		if (Position > 0)
		{
			if (close <= _entryPrice - atrVal * 2m || close >= _entryPrice + atrVal * 3m || fastVal < slowVal)
			{
				SellMarket();
				_entryPrice = 0;
			}
		}
		else if (Position < 0)
		{
			if (close >= _entryPrice + atrVal * 2m || close <= _entryPrice - atrVal * 3m || fastVal > slowVal)
			{
				BuyMarket();
				_entryPrice = 0;
			}
		}

		// Entry: EMA crossover
		if (Position == 0)
		{
			if (_prevFast <= _prevSlow && fastVal > slowVal)
			{
				_entryPrice = close;
				BuyMarket();
			}
			else if (_prevFast >= _prevSlow && fastVal < slowVal)
			{
				_entryPrice = close;
				SellMarket();
			}
		}

		_prevFast = fastVal;
		_prevSlow = slowVal;
	}
}