Auf GitHub ansehen

Myfriend Forex Instruments-Strategie

Die Myfriend Forex Instruments Strategy reproduziert den Experten von „MyFriend“ MetaTrader aus dem Jahr 2006. Es handelt EUR/USD auf 30-Minuten-Kerzen durch die Kombination von täglichen Pivot-Levels, Donchian-Kanalerweiterungen und einem kurzen vs. langen Momentum-Spread, gemessen an den Schlusskursen. Das System sucht nach Kerzen, die den täglichen Pivot mit einem breiten realen Körper durchdringen oder nach abrupten Donchian-Breitenerweiterungen. Wenn einer dieser Impulse mit dem Intraday-Momentum-Bias übereinstimmt, eröffnet die Strategie eine einzelne Position mit vordefinierten Schutzniveaus.

Handelslogik

  1. Tägliche Pivot-Karte – Die Höchst-, Tiefst- und Schlusskurse des Vortages bilden die klassische Pivot-Leiter (Pivot, R1, S1). Diese Niveaus bleiben während der gesamten Handelssitzung unverändert und definieren die erwartete Handelsspanne.
  2. Momentum-Puls – Zwei einfache gleitende Durchschnitte des Schlusskurses (3 und 9 Perioden) bilden einen Short/Long-Momentum-Spread. Der Spread wird mit 1000 multipliziert, um die MetaTrader „MP“-Berechnung nachzuahmen und zu bestimmen, ob bullischer oder bärischer Druck dominiert.
  3. Breakout-Filter
    • Pivot-Schub: Nachdem eine Kerze mit einem Körper von mehr als 12 Punkten über den Pivot schließt und die nächste Kerze in die gleiche Richtung schließt, markiert die Strategie einen potenziellen Handel.
    • Donchian-Erweiterung: Wenn sich der 16-Perioden-Donchian-Kanal über den R1 - S1-Bereich hinaus erweitert und seine Richtung mit der Preisbewegung übereinstimmt, wird das Signal ebenfalls ausgelöst.
  4. Auftragsverwaltung – Es ist jeweils nur eine Position zulässig. Bei Long-Einstiegen wird das vorherige Kerzentief abzüglich eines Puffers als Stop und ein fester Take-Profit von 70 Punkten verwendet. Short-Einträge spiegeln diese Logik mit dem vorherigen Hoch plus einem Puffer wider.
  5. Ausstiegstaktik
    • Zeitbasierter Ausstieg: Wenn sich der letzte geschlossene Balken zwischen der 3. und 4. Kerze nach dem Einstieg um 3 Punkte gegenüber der Position bewegt, wird der Handel vorzeitig geschlossen.
    • Trailing Stop: Sobald der offene Gewinn 5 Punkte überschreitet und sich die Donchian-Grenze weiterhin zu Gunsten des Handels bewegt, wird der Stop entlang des Kanals plus/minus eines 1-Punkt-Puffers nachgezogen.
    • Harte Ziele: Wenn der Preis den berechneten Stop oder Take-Profit berührt, wird die Position sofort geschlossen.

Parameter

Name Beschreibung Standard
BaseVolume Auftragsvolumen, das für jeden neuen Trade verwendet wird. 1
TakeProfitPoints Abstand des Take-Profits vom Einstieg in MetaTrader Punkten. 70
StopLossBufferPoints Zusätzlicher Puffer, der über das vorherige Kerzenextremum hinaus für den Schutzstopp hinzugefügt wurde. 13
ChannelPeriod Donchian Kanalzeitraum, der für Breitenerweiterungstests und Trailing verwendet wird. 16
UseTrailingStop Aktiviert oder deaktiviert den Donchian-basierten Trailing Stop. true
TrailingStartPoints Erforderlicher offener Gewinn (Punkte), bevor der Trailing Stop enger werden kann. 5
TrailingBufferPoints Puffer (Punkte), der beim Trailing auf die Donchian-Grenze angewendet wird. 1
UseTimeClose Aktiviert den 3–4-Kerzen-Ablehnungsausgang. true
CandleType Primärer Kerzentyp (Standardzeitrahmen 30 Minuten). M30
DailyCandleType Täglicher Kerzentyp, der zur Wiederherstellung der Pivot-Levels verwendet wird. D1

Notizen

  • Die Strategie ist für EUR/USD und 30-Minuten-Kerzen konzipiert und spiegelt den ursprünglichen Experten wider. Unterschiedliche Instrumente oder Zeitrahmen erfordern möglicherweise Parameteranpassungen.
  • Punktbasierte Parameter basieren auf dem PriceStep des Instruments. Ist dies nicht durch die Marktdaten gegeben, greift die Strategie auf eine Stückpreiserhöhung zurück.
  • Es werden nur abgeschlossene Kerzen verarbeitet, was dem MetaTrader-Verhalten des Quellalgorithmus entspricht.
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>
/// MyFriend Forex strategy - Donchian channel breakout with SMA momentum filter.
/// Buys when close breaks above upper Donchian and fast SMA > slow SMA.
/// Sells when close breaks below lower Donchian and fast SMA less than slow SMA.
/// </summary>
public class MyfriendForexInstrumentsStrategy : Strategy
{
	private readonly StrategyParam<int> _channelPeriod;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevClose;
	private decimal _prevUpper;
	private decimal _prevLower;
	private bool _hasPrev;

	public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }
	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 MyfriendForexInstrumentsStrategy()
	{
		_channelPeriod = Param(nameof(ChannelPeriod), 16)
			.SetDisplay("Channel Period", "Donchian channel period", "Indicators");

		_fastPeriod = Param(nameof(FastPeriod), 3)
			.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 9)
			.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");

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

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevClose = 0m;
		_prevUpper = 0m;
		_prevLower = 0m;
		_hasPrev = false;
	}

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

		_hasPrev = false;

		var highest = new Highest { Length = ChannelPeriod };
		var lowest = new Lowest { Length = ChannelPeriod };
		var fastSma = new SimpleMovingAverage { Length = FastPeriod };
		var slowSma = new SimpleMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(highest, lowest, fastSma, slowSma, ProcessCandle)
			.Start();
	}

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

		var close = candle.ClosePrice;

		if (!_hasPrev)
		{
			_prevClose = close;
			_prevUpper = high;
			_prevLower = low;
			_hasPrev = true;
			return;
		}

		// Breakout above channel with bullish momentum
		if (_prevClose <= _prevUpper && close > high && fast > slow && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Breakout below channel with bearish momentum
		else if (_prevClose >= _prevLower && close < low && fast < slow && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
		// Mean reversion: close crosses midpoint
		else
		{
			var mid = (high + low) / 2m;
			var prevMid = (_prevUpper + _prevLower) / 2m;

			if (_prevClose <= prevMid && close > mid && fast > slow && Position <= 0)
			{
				if (Position < 0)
					BuyMarket();
				BuyMarket();
			}
			else if (_prevClose >= prevMid && close < mid && fast < slow && Position >= 0)
			{
				if (Position > 0)
					SellMarket();
				SellMarket();
			}
		}

		_prevClose = close;
		_prevUpper = high;
		_prevLower = low;
	}
}