Auf GitHub ansehen

Nirvaman Imax-Strategie

Überblick

Die Nirvaman Imax-Strategie ist eine direkte Umsetzung des MetaTrader 4 Expert Advisors NirvamanImax.mq4 gebündelt mit den benutzerdefinierten Indikatoren HA, Moving Averages2 und iMAX3alert. Die StockSharp-Implementierung behält die ursprüngliche Idee der Kombination von Heikin-Ashi-Kerzen mit einem zweiphasigen Trenddetektor und einem EMA-Basislinienfilter bei und übernimmt gleichzeitig das High-Level-API. Die Strategie funktioniert auf einem einzigen Instrument und Zeitrahmen und schließt Geschäfte automatisch nach einer konfigurierbaren Haltedauer.

Indikatoren und Filter

  • Heikin-Ashi Kerzen – Reproduzieren Sie den ursprünglichen HA-Indikator und klassifizieren Sie Kerzen als bullisch oder bärisch, indem Sie die Heikin-Eröffnungs- und Schlusswerte vergleichen.
  • Schnelle/langsame EMA-Frequenzweiche – ersetzt den MT4 iMAX3alert1-Zweiphasenausgang. Ein bullisches Signal erscheint, wenn der schnelle EMA den langsamen EMA überschreitet; Beim gegenüberliegenden Crossover tritt ein rückläufiges Signal auf.
  • EMA-Trendfilter – spiegelt den Moving Averages2 EMA-Puffer wider und fungiert als Basislinie. Es sind nur Long-Trades oberhalb des Filters und Short-Trades darunter zulässig.
  • Zeitfilter – überspringt jede Kerze, deren Stunde innerhalb des verbotenen Fensters liegt, das durch NoTradeStartHour und NoTradeEndHour definiert ist (das Fenster unterstützt um Mitternacht und eine Broker-Zeitzonenverschiebung).
  • Zeitgesteuerter Ausstieg – jede Position wird nach Ablauf von CloseAfter zwangsweise geschlossen, wodurch die tiempoCierre-Logik der MQL-Version reproduziert wird.
  • Stops und Ziele – Stop-Loss und Take-Profit werden in Preisschritten angewendet, die von der Tick-Größe des Instruments abgeleitet werden. Wenn Sie entweder 0 festlegen, wird der entsprechende Schutz deaktiviert.

Handelsregeln

  1. Warten Sie, bis Heikin-Ashi, schneller EMA, langsamer EMA und Filter EMA gebildet sind und ein früherer Kerzenschluss verfügbar ist.
  2. Lehnen Sie das Signal ab, wenn die Kerzenzeit innerhalb des eingeschränkten Handelsfensters liegt.
  3. Langer Eintrag:
    • Der schnelle EMA kreuzt den langsamen EMA der aktuellen Kerze.
    • Der Heikin-Ashi-Schlusskurs liegt über seinem Eröffnungskurs (bullischer Körper).
    • Der vorherige Kerzenschluss liegt über dem EMA-Filter.
  4. Kurzer Eintrag:
    • Der schnelle EMA kreuzt den langsamen EMA der aktuellen Kerze.
    • Der Schlusskurs von Heikin-Ashi liegt unter seinem Eröffnungskurs (bärischer Körper).
    • Der vorherige Kerzenschluss liegt unter dem EMA-Filter.
  5. Ausgangsregeln:
    • Stop-Loss- oder Take-Profit-Level werden durch die Kerzenspanne berührt.
    • Die maximale Positionslebensdauer CloseAfter ist überschritten.
    • Der über StartProtection() ausgelöste manuelle Schutz schließt die Position, wenn die Engine dies anfordert.

Parameter

Name Beschreibung Standard
TradeVolume Basis-Market-Order-Volumen. 0.1
CandleType Kerzenzeitrahmen, der für jeden Indikator und jedes Signal verwendet wird. 30m Zeitrahmen
FastTrendLength Länge des schnellen EMA, der die blaue iMAX-Phase emuliert. 10
SlowTrendLength Länge des langsamen EMA, der die rote iMAX-Phase emuliert. 21
FilterLength EMA Zeitraum für den Basisfilter (Äquivalent zu gleitenden Durchschnitten2). 13
StopLoss Schutzanschlagabstand in Preisschritten; 0 deaktiviert den Stopp. 50
TakeProfit Gewinnzielentfernung in Preisschritten; 0 deaktiviert das Ziel. 100
CloseAfter Maximale Haltezeit, bevor die Position zwangsweise geschlossen wird. 15000 s
NoTradeStartHour Stunde (0–23), die den Beginn des No-Trade-Fensters markiert. 22
NoTradeEndHour Stunde (0–23), die das Ende des No-Trade-Fensters markiert. 2
BrokerTimeOffset Der Zeitzonenversatz des Brokers (Stunden), der vor dem Zeitfilter angewendet wird. 0

Konvertierungshinweise

  • Der MT4-Indikator iMAX3alert1 stellt zwei farbcodierte Puffer bereit. Ihr Crossover wird in einen Fast/Slow-EMA-Crossover übersetzt, der die ursprüngliche ereignisgesteuerte Eintrittslogik beibehält.
  • Der Moving Averages2-Indikator wurde im Modus EMA mit einer Standardlänge von 13 ausgeführt. Die Version StockSharp verwendet einen Standard-ExponentialMovingAverage mit demselben Standardwert wieder.
  • Die Verwaltung des Positionslebenszyklus spiegelt das Skript MQL wider: Die Position wird nach einer Zeitüberschreitung geschlossen, bevor neue Einträge ausgewertet werden können, und es wurde keine zusätzliche Trailing-Stop-Logik hinzugefügt.

Anwendungstipps

  1. Befestigen Sie die Strategie an einem Board/Wertpapier und stellen Sie den gewünschten CandleType ein, bevor Sie damit beginnen.
  2. Passen Sie TradeVolume, StopLoss, TakeProfit und CloseAfter an die Volatilität und Risikotoleranz des Instruments an.
  3. Optimieren Sie die EMA-Zeiträume, wenn Sie das Verhalten des ursprünglichen iMAX-Tunings für einen neuen Markt annähern müssen.
  4. Kombinieren Sie es mit Risikokontrollen auf höherer Ebene (Portfolioschutz, Sitzungskontrolle), wenn Sie mehrere Instanzen ausführen.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Nirvaman Imax: Dual EMA crossover with trend filter and timed exit.
/// Fast EMA crosses slow EMA for direction, filter EMA confirms trend.
/// </summary>
public class NirvamanImaxStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<int> _filterLength;
	private readonly StrategyParam<int> _atrLength;

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

	public NirvamanImaxStrategy()
	{
		_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), 21)
			.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators");

		_filterLength = Param(nameof(FilterLength), 50)
			.SetDisplay("Filter EMA", "Trend filter 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 FilterLength
	{
		get => _filterLength.Value;
		set => _filterLength.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 filter = new ExponentialMovingAverage { Length = FilterLength };
		var atr = new AverageTrueRange { Length = AtrLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, filter, 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 filterVal, 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 management
		if (Position > 0)
		{
			if (close <= _entryPrice - atrVal * 2m || close >= _entryPrice + atrVal * 3m)
			{
				SellMarket();
				_entryPrice = 0;
			}
			else if (_prevFast >= _prevSlow && fastVal < slowVal)
			{
				SellMarket();
				_entryPrice = 0;
			}
		}
		else if (Position < 0)
		{
			if (close >= _entryPrice + atrVal * 2m || close <= _entryPrice - atrVal * 3m)
			{
				BuyMarket();
				_entryPrice = 0;
			}
			else if (_prevFast <= _prevSlow && fastVal > slowVal)
			{
				BuyMarket();
				_entryPrice = 0;
			}
		}

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

		_prevFast = fastVal;
		_prevSlow = slowVal;
	}
}