Auf GitHub ansehen

Strategie Profit Hunter HSI with Fibonacci Strategy

Überblick

Diese Strategie ist eine C#-Portierung des MetaTrader 4 Expert Advisors Profit_Hunter_HSI_with_fibonacci.mq4. The original script combines ein Intraday-Filter für den exponentiellen gleitenden Durchschnitt (EMA) mit Fibonacci Retracement-Zonen, abgeleitet vom Tages-Chart. Der StockSharp Die Implementierung folgt der gleichen Idee unter Verwendung des High-Level-API: Es abonniert zwei Candle-Streams (Intraday und Daily) und berechnet Das Fibonacci-Raster generiert dynamisch Handelssignale, wenn der Preis mit diesen Bändern interagiert, und verwaltet die resultierende Position mit adaptiver Stop-Platzierung und einer abgestuften Trailing-Stop-Logik.

Marktdatenfluss

  1. Intraday-Kerzen – der Parameter TimeFrame definiert die Arbeitsauflösung (Standard: 1 Minute). Each finished candle feeds the EMA trend filter, updates the most recent support/resistance reference taken NumBars bars ago, and triggers the trading Logik.
  2. Tägliche Kerzen – ein spezielles Abonnement sammelt Daten über einen längeren Zeitraum. Zwei vom Benutzer konfigurierbare Indizes bestimmen das Swing-Hoch und Swing Low, die als Anker für das Fibonacci-Gitter dienen. Immer wenn eine neue Tageskerze eintrifft, wird die gesamte Retracement-Leiter angezeigt neu berechnet, einschließlich der Verlängerungen (161,8 %, 261,8 %, 423,6 %).

Signalerzeugung

Der MQL-Berater speicherte den zuletzt entdeckten Swing-Hoch/Tief-Wert und ermittelte, welcher Swing zuerst auftrat (highFirst). Der Port behält die same concept by comparing the day indices:

  • If the selected high is more recent than the selected low (highFirst = true) the market is treated as descending and the Fibonacci levels are measured upward from the low.
  • Andernfalls wird die Bewegung als aufsteigend betrachtet und das Raster wird vom Hoch nach unten projiziert.

Für jede abgeschlossene Intraday-Kerze spiegeln die folgenden Regeln das Original EA wider:

  1. Trendfilter – ein EMA mit dem Zeitraum MaPeriod klassifiziert die kurzfristige Tendenz. If the close price (treated as both bid and ask) is above the EMA the trend is "Naik" (up); if it is below, the trend is "Turun" (down). When the price hovers exactly around the EMA no trade will be opened.
  2. Fibonacci-Signal – abhängig von highFirst erzeugt die Preisinteraktion mit den Niveaus 23,6 %, 76,4 %, 91 % und 14,6 % eines von vier String-Signale aus dem MT4-Code: Reverse-Buy, Reverse-Sell, Trading-Area oder Continuation. Nur die ersten drei sind es used for actual entries, the last one simply reports a trend continuation.
  3. Entry rules – the original script contained six entry branches. They are reproduced verbatim:
    • Aufwärtstrend + Handelsbereich + Ausbruch über den Referenzwiderstand → Kauf mit dem Schutzstopp bei der referenzierten Unterstützung.
    • Aufwärtstrend + umgekehrter Verkauf + highFirst == false + Preis immer noch unter dem Widerstand → Eröffnen Sie einen Short mit dem Stop bei 14,6 %.
    • Aufwärtstrend + umgekehrter Kauf + highFirst == false + Preis unter dem Widerstand → Kauf mit dem Stop bei 91 %.
    • Abwärtstrend + Handelsbereich + Durchbruch unter Unterstützung → Verkauf mit Stopp an der Widerstandslinie.
    • Abwärtstrend + umgekehrter Verkauf + highFirst == true + Preis unter dem Widerstand → Verkauf mit dem Stop bei 91 %.
    • Abwärtstrend + umgekehrter Kauf + highFirst == true + Preis unter dem Widerstand → Kauf mit dem Stop bei 14,6 %. Only one position may exist at a time; Aktive Aufträge werden nicht gestapelt.

Positionsmanagement

  • Unterstützungs-/Widerstandsausgänge – wie im EA wird eine Long-Position aufgelöst, wenn der Preis während a auf die Unterstützungsreferenz zurückfällt Der Short wird geschlossen, wenn der Preis auf die Widerstandsreferenz steigt, unabhängig vom aktuellen Gewinn.
  • Anfänglicher Schutzstopp – der während der Eintrittsentscheidung berechnete Stopppegel wird intern gespeichert und als Ausstiegsauslöser verwendet. Die StockSharp-Version führt bei jeder Kerze die gleiche Prüfung durch, anstatt Brokeraufträge direkt zu ändern.
  • Stepped trailing stop – the MQL script raised the stop level every 20 points after an initial 60-point move (e.g., +60 → stop bis +55, +80 → Stopp bis +75, … bis +260). Der Port behält die genaue Rangliste bei, indem er das Instrument PriceStep verwendet, um Punkte in umzuwandeln Preisverrechnungen. For short trades the stop slides downward to lock in profits, guaranteeing the same distance as the original.

Parameter

Name Beschreibung Standard Notizen
NumBars Verschiebung der Kerze, deren Hoch/Tief zum vorübergehenden Widerstand/Unterstützung wird. 3 Entspricht der externen Eingabe numBars; muss größer als Null sein.
MaPeriod Zeitraum des EMA, der für die Trendklassifizierung verwendet wird. 5 Entspricht maPeriod im EA.
TimeFrame Intraday candle timeframe. 1 minute Mirrors the timeFrame extern; akzeptiert alle TimeSpan.
DaysBackForHigh Index der täglichen Kerze, die das Swing-Hoch liefert. 1 Entspricht daysBackForHigh.
DaysBackForLow Index der täglichen Kerze, die das Swing-Tief liefert. 1 Entspricht daysBackForLow.
Volume Größe der Marktorder. 1 Stellt Grundstücke/Aktien dar; validated to stay positive.

Implementierungshinweise

  • Das Original EA erstellte zahlreiche grafische Objekte. Diese Aufrufe werden absichtlich weggelassen, da StockSharp die Diagrammerstellung übernimmt separately and the shapes were purely cosmetic.
  • Instead of querying historical buffers like iLow and iHigh, the port maintains two in-memory lists of finished candles and reads the required shift directly from there.
  • Die Stop-Verwaltung wird im Strategiecode (ManagePosition) und nicht über OrderModify implementiert, wodurch der Verhaltensbroker erhalten bleibt agnostisch unter Beibehaltung des gleichen Entscheidungsbaums.
  • Auftragsablehnungen löschen den ausstehenden Eingabestatus, sodass manuelle Anpassungen keine veralteten internen Flags hinterlassen, die mit der Defensive übereinstimmen Codierung, die in vielen bestehenden API-Strategien vorhanden ist.

Unterschiede zur MetaTrader-Version

  • MetaTrader hat Zugriff auf die Tick-Level Ask und Bid angenommen. StockSharp arbeitet standardmäßig mit Kerzenschlüssen; Es wird der Schlusskurs verwendet als Bid- und Ask-Proxy, was zur Nachbildung der Entscheidungslogik ausreicht.
  • The notion of "which extremum appeared first" cannot rely on MT4's High[]/Low[] series. Der Port nähert sich dem Wert durch Vergleich an Die ausgewählten Tagesindizes liefern identische Ergebnisse für die Standardkonfiguration und behalten das beabsichtigte Verhalten für bei andere Einstellungen.
  • Brokerseitige Stop- und Take-Profit-Orders werden durch virtuelle Exits ersetzt, die pro Kerze ausgewertet werden. Dadurch wird eine steckerspezifische Reihenfolge vermieden Typen und stellen gleichzeitig sicher, dass die gleichen Exit-Bedingungen erfüllt sind.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Profit Hunter strategy with Fibonacci retracement levels.
/// Uses EMA trend filter and enters on pullbacks to Fibonacci levels.
/// </summary>
public class ProfitHunterHsiWithFibonacciStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _lookbackPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private int _barCount;

	public ProfitHunterHsiWithFibonacciStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetDisplay("EMA Period", "Period for trend filter EMA.", "Indicators");

		_lookbackPeriod = Param(nameof(LookbackPeriod), 50)
			.SetDisplay("Lookback Period", "Bars to look back for range high/low.", "Fibonacci");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(2).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for analysis.", "General");
	}

	public int EmaPeriod
	{
		get => _emaPeriod.Value;
		set => _emaPeriod.Value = value;
	}

	public int LookbackPeriod
	{
		get => _lookbackPeriod.Value;
		set => _lookbackPeriod.Value = value;
	}

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

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

		_barCount = 0;
	}

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

		_barCount = 0;

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var highest = new Highest { Length = LookbackPeriod };
		var lowest = new Lowest { Length = LookbackPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, highest, lowest, ProcessCandle)
			.Start();

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

	private void ProcessCandle(ICandleMessage candle, decimal emaValue, decimal highestValue, decimal lowestValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		_barCount++;

		if (_barCount < LookbackPeriod)
			return;

		var range = highestValue - lowestValue;
		if (range <= 0)
			return;

		// Fibonacci levels
		var fib382 = highestValue - range * 0.382m;
		var fib618 = highestValue - range * 0.618m;
		var close = candle.ClosePrice;

		// Manage position
		if (Position > 0)
		{
			// Exit long at 0 fib (range high) or if price drops below 61.8%
			if (close >= highestValue || close < fib618)
			{
				SellMarket();
			}
		}
		else if (Position < 0)
		{
			// Exit short at 100% fib (range low) or if price rises above 38.2%
			if (close <= lowestValue || close > fib382)
			{
				BuyMarket();
			}
		}

		// Entry logic
		if (Position == 0)
		{
			if (close > emaValue && close <= fib382 && close > fib618)
			{
				// Uptrend + pullback to Fib zone -> buy
				BuyMarket();
			}
			else if (close < emaValue && close >= fib618 && close < fib382)
			{
				// Downtrend + pullback to Fib zone -> sell
				SellMarket();
			}
		}
	}
}