Ver en GitHub

Estrategia Nirvaman Imax

Descripción general

La estrategia Nirvaman Imax es una conversión directa del MetaTrader 4 asesor experto NirvamanImax.mq4 incluido con los indicadores personalizados HA, Moving Averages2 e iMAX3alert. La implementación StockSharp mantiene la idea original de combinar Heikin-Ashi velas con un detector de tendencias de dos fases y un filtro de línea base EMA mientras adopta el nivel alto API. La estrategia funciona con un único instrumento y marco de tiempo y cierra operaciones automáticamente después de un período de tenencia configurable.

Indicadores y filtros

  • Heikin-Ashi velas: reproduce el indicador HA original y clasifica las velas como alcistas o bajistas comparando los valores de apertura y cierre de Heikin.
  • Cruce rápido/EMA lenta: reemplaza la salida bifásica MT4 iMAX3alert1. Aparece una señal alcista cuando el EMA rápido cruza por encima del EMA lento; se produce una señal bajista en el cruce opuesto.
  • EMA filtro de tendencias: refleja el búfer Moving Averages2 EMA y actúa como línea de base. Sólo se permiten operaciones largas por encima del filtro y operaciones cortas por debajo del mismo.
  • Filtro de tiempo: omite cualquier vela cuya hora se encuentre dentro de la ventana prohibida definida por NoTradeStartHour y NoTradeEndHour (la ventana admite un cambio de zona horaria alrededor de la medianoche y un cambio de zona horaria del corredor).
  • Salida programada: cada posición se fuerza a cerrar después de que transcurra CloseAfter, reproduciendo la lógica tiempoCierre de la versión MQL.
  • Paradas y objetivos: el límite de pérdidas y la toma de ganancias se aplican en incrementos de precio derivados del tamaño del tick del instrumento. Establecer cualquiera de ellos en 0 deshabilita la protección correspondiente.

Reglas comerciales

  1. Espere hasta que se formen Heikin-Ashi, EMA rápida, EMA lenta y el filtro EMA y esté disponible un cierre de vela anterior.
  2. Rechace la señal si el tiempo de la vela está dentro de la ventana comercial restringida.
  3. Entrada larga:
    • El EMA rápido cruza por encima del EMA lento en la vela actual.
    • El cierre de Heikin-Ashi está por encima de su apertura (cuerpo alcista).
    • El cierre de la vela anterior está por encima del filtro EMA.
  4. Entrada corta:
    • El EMA rápida cruza por debajo del EMA lenta en la vela actual.
    • El cierre de Heikin-Ashi está por debajo de su apertura (cuerpo bajista).
    • El cierre de la vela anterior está por debajo del filtro EMA.
  5. Reglas de salida:
    • Los niveles de stop loss o takeprofit se ven afectados por el rango de velas.
    • Se superó la duración máxima de la posición CloseAfter.
    • La protección manual activada mediante StartProtection() cierra la posición cuando el motor lo solicita.

Parámetros

Nombre Descripción Predeterminado
TradeVolume Volumen de orden de mercado base. 0.1
CandleType Marco de tiempo de vela utilizado para cada indicador y señal. 30m período de tiempo
FastTrendLength Duración del EMA rápida que emula la fase azul del iMAX. 10
SlowTrendLength Duración del EMA lenta que emula la fase roja del iMAX. 21
FilterLength EMA período para el filtro de referencia (equivalente a medias móviles2). 13
StopLoss Distancia de parada protectora en pasos de precios; 0 desactiva la parada. 50
TakeProfit Distancia objetivo de beneficios en pasos de precios; 0 desactiva el objetivo. 100
CloseAfter Tiempo máximo de espera antes de que se fuerce el cierre de la posición. 15000 s
NoTradeStartHour Hora (0–23) que marca el comienzo de la ventana de no comercio. 22
NoTradeEndHour Hora (0–23) que marca el final de la ventana de no comercio. 2
BrokerTimeOffset Desplazamiento de zona horaria del agente (horas) aplicado antes del filtro de hora. 0

Notas de conversión

  • El indicador MT4 iMAX3alert1 expone dos buffers codificados por colores. Su cruce se traduce en un cruce EMA rápido/lento, que conserva la lógica de entrada original basada en eventos.
  • El indicador Moving Averages2 se ejecutó en modo EMA con una longitud predeterminada de 13. La versión StockSharp reutiliza un estándar ExponentialMovingAverage con el mismo valor predeterminado.
  • La gestión del ciclo de vida de la posición refleja el script MQL: la posición se cierra en el tiempo de espera antes de que se puedan evaluar nuevas entradas y no se agregó ninguna lógica de trailing stop adicional.

Consejos de uso

  1. Adjunte la estrategia a un tablero/seguridad y establezca el CandleType deseado antes de iniciarla.
  2. Ajuste TradeVolume, StopLoss, TakeProfit y CloseAfter para que coincidan con la volatilidad y la tolerancia al riesgo del instrumento.
  3. Optimice los períodos EMA si necesita aproximarse al comportamiento del ajuste del iMAX original para un nuevo mercado.
  4. Combínelo con controles de riesgo de nivel superior (protección de cartera, control de sesión) cuando ejecute múltiples instancias.
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;
	}
}