Auf GitHub ansehen

Franks 4-Stunden-Limit-Orders-Strategie

Überblick

Die Franks 4 Hour Limit Orders Strategy portiert den MetaTrader 4 Expert Advisor von MQL/7684/Franks_4hour_limit_orders.mq4 zum StockSharp High-Level API. Der ursprüngliche EA kombiniert die Triple-Screen-Ideen von Alexander Elder: Er bewertet die Dynamik auf einem Vier-Stunden-Chart unter Verwendung des MACD-Histogramms (OsMA) zusammen mit dem Force Index und platziert dann konträre Limit-Orders um die vorherigen Candle-Extreme. Die StockSharp-Implementierung behält diese Multi-Indikator-Logik bei, befolgt aber gleichzeitig die Repository-Richtlinien (Tabs, API auf hoher Ebene, keine benutzerdefinierten Sammlungen) und fügt der Übersichtlichkeit halber ausführliche Inline-Kommentare auf Englisch hinzu.

Handelslogik

  1. Datenquelle – Die Strategie abonniert einen konfigurierbaren Kerzentyp, der standardmäßig Vier-Stunden-Kerzen verwendet. Alle Berechnungen werden nur für abgeschlossene Kerzen durchgeführt, um dem Verhalten des MT4-Experten zu entsprechen.
  2. Indikatoren – Es werden zwei verwaltete Indikatoren verwendet:
    • MovingAverageConvergenceDivergenceSignal(12, 26, 9) stellt sowohl die MACD-Leitung als auch die Signalleitung bereit. Ihre Differenz stellt das im EA verwendete OsMA-Histogramm wieder her.
    • ForceIndex(24) misst die Kraft der vorherigen Kerze. Es werden nur endgültige Indikatorwerte berücksichtigt.
  3. Historischer Kontext – Der EA erfordert zwei abgeschlossene Kerzen, um die Steigung des Indikators zu bestimmen. Der Port speichert die vorherigen OsMA-Werte, den vorherigen Force-Index-Wert und das vorherige Kerzenhoch/-tief, um diese Anforderung widerzuspiegeln.
  4. Verkaufs-Setup – Wenn das OsMA-Histogramm ansteigt (OsMA[1] > OsMA[2]) und der vorherige Force-Index-Wert negativ ist, plant der Roboter eine konträre Verkaufs-Limit-Order:
    • Der Basispreis ist das vorherige Kerzenhoch plus einen Punkt.
    • Es wird ein Sicherheitspuffer von 16 Pips (konfigurierbar) gegenüber dem aktuellen Gebot erzwungen. Der Zielpreis wird zum Maximum zwischen dem Grundpreis und Bid + buffer.
    • Stop-Loss- und Take-Profit-Preise werden anhand der konfigurierten Pip-Abstände (standardmäßig 35 Pips und 150 Pips) an der Preisstufe des Instruments ausgerichtet.
  5. Kauf-Setup – Wenn das OsMA-Histogramm abnimmt (OsMA[1] < OsMA[2]) und der vorherige Force-Index positiv ist, bereitet die Strategie eine Kauf-Limit-Order unterhalb des Marktes vor:
    • Der Basispreis ist das vorherige Kerzentief minus einen Punkt.
    • Der Algorithmus erzwingt den gleichen 16-Pip-Puffer relativ zum aktuellen Brief und wählt das Minimum zwischen dem Basispreis und Ask - buffer.
  6. Aufrechterhaltung der ausstehenden Order – Wenn sich die OsMA-Steigung vor der Ausführung in die entgegengesetzte Richtung dreht, wird die entsprechende ausstehende Order storniert. Wenn eine Seite gefüllt ist, wird die gegenüberliegende ausstehende Bestellung entfernt, um eine Doppelbelichtung zu vermeiden.
  7. Positionsverwaltung – Bei der Ausführung wird der Füllpreis gespeichert und die vorberechneten Stop-Loss- und Take-Profit-Level werden aktiviert. Die Strategie implementiert außerdem einen Pip-basierten Trailing Stop (standardmäßig 30 Pips), der den Schutzstopp nur dann in die günstige Richtung verschiebt, wenn der Preis über den Einstiegspunkt plus die Trailing-Distanz hinaus steigt.
  8. Exits – Schutzaufträge werden bei jeder abgeschlossenen Kerze überwacht. Eine Long-Position wird geschlossen, wenn das Kerzentief den Stopp berührt oder das Kerzenhoch das Ziel erreicht. Bei Short-Positionen gelten die gespiegelten Regeln.

Parameter

Parameter Standard Beschreibung
OrderVolume 1 Festes Volumen für ausstehende Limit-Orders.
StopLossPips 35 Abstand in Pips zwischen dem Einstiegspreis und dem Schutzstopp.
TakeProfitPips 150 Abstand (in Pips) zwischen dem Einstiegspreis und dem Take-Profit-Niveau.
TrailingStopPips 30 Abstand (in Pips) für den Trailing Stop, der Gewinne sichert, sobald sich der Preis weit genug bewegt.
EntryBufferPips 16 Mindestlücke in Pips zwischen dem aktuellen Marktpreis und der ausstehenden Order.
PipSize 0,0001 Pip-Größe, die für Preisumrechnungen verwendet wird; Der Standardwert ist 0,0001, kann aber mit exotischen Symbolen ausgerichtet werden.
CandleType 4h Zeitrahmen Von der Strategie verarbeitete Kerzenserie.

Dateien

  • CS/Franks4HourLimitOrdersStrategy.cs – Haupt-C#-Implementierung mit detaillierten englischen Kommentaren.
  • README.md – Diese englische Beschreibung des Algorithmus.
  • README_ru.md – Russische Dokumentation.
  • README_zh.md – Chinesische Dokumentation.

Implementierungshinweise

  • Die Strategie basiert ausschließlich auf den übergeordneten API (SubscribeCandles, Indikatorbindungen und praktischen Bestellhilfen).
  • Alle Preisberechnungen orientieren sich an der Preisstufe des Instruments, um ungültige Niveaus zu vermeiden.
  • Zustandsvariablen speichern nur die notwendigen historischen Daten und entsprechen damit der Repository-Regel, die benutzerdefinierte Sammlungen verbietet.
  • Stop-Loss-, Take-Profit- und Trailing-Stop-Management werden innerhalb der Kerzenverarbeitungsroutine durchgeführt, um das MT4-Trailing-Verhalten zu emulieren.
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>
/// Franks 4H strategy - EMA crossover with momentum filter.
/// Buys on bullish EMA crossover with positive momentum.
/// Sells on bearish EMA crossover with negative momentum.
/// </summary>
public class Franks4HourLimitOrdersStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _momentumPeriod;
	private readonly StrategyParam<DataType> _candleType;

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

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

	public Franks4HourLimitOrdersStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 26)
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

		_momentumPeriod = Param(nameof(MomentumPeriod), 10)
			.SetDisplay("Momentum", "Momentum period", "Indicators");

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

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }

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

		_hasPrev = false;

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var momentum = new Momentum { Length = MomentumPeriod };

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

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

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fast > slow;
		var crossDown = _prevFast >= _prevSlow && fast < slow;

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

		_prevFast = fast;
		_prevSlow = slow;
	}
}