Auf GitHub ansehen

Nextbar-Strategie

Überblick

Die Nextbar-Strategie ist eine direkte Übersetzung des MetaTrader 4 Expertenberaters nextbar.mq4. Der ursprüngliche EA wertet den Abstand zwischen der letzten abgeschlossenen Kerze und einer Kerze aus, die mehrere Balken älter ist. Wenn sich der Preis weit genug in eine Richtung bewegt, folgt er je nach konfiguriertem Richtungsflag entweder dem Impuls oder handelt dagegen. Die Positionen werden dann durch symmetrische Take-Profit-/Stop-Loss-Levels geschützt und nach einer festgelegten Anzahl von Balken zwangsweise geschlossen.

Diese StockSharp-Version behält das gleiche Verhalten bei, wenn die High-Level-Strategie API verwendet wird. Es verarbeitet nur abgeschlossene Kerzen und stellt so sicher, dass alle Berechnungen der Bar-on-Close-Logik des MT4-Skripts entsprechen.

Ursprüngliche MQL-Logik

  • Impulsentfernung – vergleiche Close[1] mit Close[bars2check+1]. Wenn die Differenz mindestens minbar * Point beträgt, behandeln Sie es als gültiges Signal.
  • Richtungsflagge – die MQL-Eingabe direction entspricht 1 für Trendfolge (Kauf nach einer Rallye, Verkauf nach einem Rückgang) und 2 für konträren Handel (Kauf nach einem Rückgang, Verkauf nach einer Rallye).
  • Eingabebeschränkung – es kann jeweils nur eine Bestellung geöffnet sein. Nach dem Signal wird am Anfang des Balkens ein neuer Trade gesendet.
  • Ausstiegsregeln – Schließen Sie eine Long-Position, wenn der letzte Schlusskurs die Gewinndistanz über dem Einstiegspunkt oder die Verlustdistanz darunter erreicht; Für Shorts gilt das Umgekehrte. Wenn keines der beiden Niveaus erreicht wird, schließen Sie den Handel nach bars2hold abgeschlossenen Kerzen.

StockSharp Implementierungshighlights

  • Verwendet SubscribeCandles() und Bind, um abgeschlossene Kerzen im konfigurierten Zeitrahmen zu erhalten.
  • Speichert eine kurze rollierende Historie der Schlusskurse, um auf die Kerze zu verweisen, die dem Offset MQL bars2check + 1 entspricht.
  • Konvertiert alle punktbasierten Parameter mit Security.PriceStep und ahmt die Konstante MetaTrader Point nach.
  • Platziert Marktaufträge mit der Strategie Volume und unterstützt über den Parameter Direction entweder Momentum-folgende oder konträre Einstiege.
  • Implementiert Gewinn-, Verlust- und Haltezeitraum-Exits genau einmal pro fertiger Kerze, um mit dem ursprünglichen Arbeitsablauf in Einklang zu bleiben.

Parameter

Parameter Beschreibung Standard Notizen
CandleType Zeitrahmen, der für die Signalauswertung verwendet wird. 1-stündiger Zeitrahmen Hängen Sie die Strategie an ein Wertpapier an, das diesen Kerzentyp bereitstellen kann.
BarsToCheck Anzahl der abgeschlossenen Kerzen zwischen dem Referenzschluss und dem letzten Schluss. 8 Entspricht bars2check aus EA.
BarsToHold Maximale Anzahl abgeschlossener Kerzen, um eine Position offen zu halten. 10 Entspricht bars2hold. Die Position wird auf dem Balken geschlossen, bei dem der Zähler diese Zahl erreicht.
MinMovePoints Mindestabstand (in MetaTrader Punkten) zwischen den beiden verglichenen Schlusskursen. 77 Entspricht minbar. Konvertiert mit Security.PriceStep.
TakeProfitPoints Gewinnzielentfernung in MetaTrader Punkten. 115 Entspricht der Eingabe profit. Zum Deaktivieren auf Null setzen, falls gewünscht.
StopLossPoints Stop-Loss-Distanz in MetaTrader Punkten. 115 Entspricht der Eingabe loss. Zum Deaktivieren auf Null setzen, falls gewünscht.
Direction Handelsmodus: Follow (Trend) oder Reverse (Contrarian). Follow Spiegelt die direction-Eingabe (1 = folgen, 2 = umkehren).
Volume Handelsvolumen, das für Marktaufträge verwendet wird. Strategievolumen Konfigurieren Sie über die Standardeigenschaft Strategy.Volume.

Handelsablauf

  1. Warten Sie auf eine fertige Kerze und speichern Sie ihren Schlusskurs.
  2. Rufen Sie den Schlusskurs von BarsToCheck Kerzen ab und berechnen Sie die Differenz.
  3. Wenn die absolute Bewegung unter MinMovePoints * PriceStep liegt, unternehmen Sie nichts.
  4. Ansonsten:
    • Im Folgen-Modus kaufen Sie, wenn der Preis steigt, und verkaufen, wenn der Preis fällt.
    • Im Reverse-Modus kaufen Sie, wenn der Preis fällt, und verkaufen, wenn der Preis steigt.
  5. Bei jeder weiteren fertigen Kerze, während die Position offen ist:
    • Schließen Sie Long-Positionen, wenn der Schlusskurs TakeProfitPoints über oder StopLossPoints unter dem gespeicherten Einstiegspreis liegt.
    • Schließen Sie Short-Positionen, wenn der Schlusskurs TakeProfitPoints unter oder StopLossPoints über dem Einstiegspunkt liegt.
    • Erzwingen Sie das Schließen, sobald seit dem Eintritt BarsToHold Kerzen verstrichen sind.

Nutzungshinweise

  • Die Umrechnung von Punkten in den absoluten Preis erfordert Security.PriceStep. Stellen Sie die richtigen Instrument-Metadaten (Preisschritt, Schrittpreis, Volumenregeln) bereit, bevor Sie die Strategie ausführen.
  • Die Strategie verwaltet nicht mehrere gleichzeitige Positionen; Stellen Sie sicher, dass Volume der Größe entspricht, die Sie für eine einzelne MT4-Bestellung erwarten.
  • Da Entscheidungen nur anhand abgeschlossener Kerzen bewertet werden, sollte die Strategie mit historischen und Echtzeitdaten ausgeführt werden, die fertige Balken liefern.
using System;

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

namespace StockSharp.Samples.Strategies;

public class NextbarStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _cooldownCandles;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevOpen;
	private decimal _prevClose;
	private bool _hasPrev;
	private int _cooldownRemaining;

	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public NextbarStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 50).SetDisplay("EMA Period", "EMA filter", "Indicators");
		_cooldownCandles = Param(nameof(CooldownCandles), 200).SetDisplay("Cooldown", "Candles between signals", "General");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevOpen = default;
		_prevClose = default;
		_hasPrev = default;
		_cooldownRemaining = default;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevOpen = 0;
		_prevClose = 0;
		_hasPrev = false;
		_cooldownRemaining = 0;

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal ema)
	{
		if (candle.State != CandleStates.Finished) return;
		var close = candle.ClosePrice;
		if (!_hasPrev) { _prevOpen = candle.OpenPrice; _prevClose = close; _hasPrev = true; return; }

		if (_cooldownRemaining > 0)
		{
			_cooldownRemaining--;
			_prevOpen = candle.OpenPrice;
			_prevClose = close;
			return;
		}

		var prevBullish = _prevClose > _prevOpen;
		var prevBearish = _prevClose < _prevOpen;

		if (prevBullish && close > ema && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
			_cooldownRemaining = CooldownCandles;
		}
		else if (prevBearish && close < ema && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
			_cooldownRemaining = CooldownCandles;
		}
		_prevOpen = candle.OpenPrice;
		_prevClose = close;
	}
}