Ver en GitHub

Exp RJTX Coincidencias Suavizadas Duplex

Descripción general

La estrategia recrea el comportamiento del asesor experto de MetaTrader 5 Exp_RJTX_Matches_Smoothed_Duplex.mq5. Dos bloques de señal RJTX independientes analizan precios de apertura y cierre suavizados en sus respectivos marcos temporales. Cada bloque clasifica cada vela completada como alcista o bajista dependiendo de si el cierre suavizado sube por encima de la apertura suavizada de Period barras atrás. Las "coincidencias" alcistas activan entradas para el módulo largo, mientras que las coincidencias bajistas gestionan el módulo corto.

Generación de señales

  1. Suavizado – ambos bloques alimentan las aperturas y cierres de las velas en el algoritmo de suavizado seleccionado. Se aplica el mismo método a los flujos de apertura y cierre, pero se usan instancias separadas para mantener los búferes internos independientes.
  2. Comparación – una vez que hay suficiente historia disponible, el cierre suavizado actual se compara con la apertura suavizada registrada Period barras antes.
  3. Detección de coincidencia – si el cierre es mayor, la vela recibe una coincidencia alcista; de lo contrario se vuelve bajista. Las señales se evalúan después de desplazarse por SignalBar velas cerradas, igual que el acceso al búfer MT5.

Gestión de posiciones

  • El bloque largo abre una posición larga (cubriendo cualquier corto existente si está permitido) cuando una coincidencia alcista alcanza la ventana de evaluación. Una coincidencia bajista cierra la posición larga si las salidas largas están habilitadas.
  • El bloque corto espeja esta lógica: una coincidencia bajista abre una operación corta (cerrando la exposición larga si está permitido) y una coincidencia alcista cubre el corto.
  • Las estrategias de StockSharp son neteadas. Por lo tanto, los módulos opuestos cierran la posición actual antes de abrir una nueva, en lugar de mantener dos posiciones hedgeadas independientes como la versión MT5. Desactiva el parámetro Allow ... Close correspondiente para prohibir la cobertura automática.

Gestión del riesgo

Los stops y objetivos de ganancia se expresan en pasos de precio (PriceStep × points). Para cada vela terminada, la estrategia verifica si el rango de la barra toca el nivel de stop-loss o take-profit activo y cierra la posición correspondiente inmediatamente. Esto emula el comportamiento de las órdenes de protección MT5 sin depender de órdenes gestionadas por el broker.

Parámetros

Sección Parámetro Predeterminado Descripción
Long LongCandleType H4 Marco temporal usado por el bloque RJTX largo.
Long LongVolume 0.1 Volumen abierto cuando se ejecuta una señal larga.
Long LongAllowOpen true Habilitar apertura de posiciones largas.
Long LongAllowClose true Habilitar cierre de posiciones largas en coincidencias bajistas.
Long LongStopLossPoints 1000 Distancia de stop-loss para operaciones largas en pasos de precio (0 deshabilita la comprobación).
Long LongTakeProfitPoints 2000 Distancia de take-profit para operaciones largas en pasos de precio (0 deshabilita la comprobación).
Long LongSignalBar 1 Desplazamiento aplicado al leer búferes RJTX (0 = vela cerrada actual).
Long LongPeriod 10 Número de barras entre el cierre suavizado actual y la apertura suavizada histórica.
Long LongMethod Sma Algoritmo de suavizado para el bloque largo (Sma, Ema, Smma, Lwma, Jjma, Jurx, Parma, T3, Vidya, Ama).
Long LongLength 12 Longitud del filtro de suavizado aplicado a las series de apertura/cierre.
Long LongPhase 15 Parámetro de fase para filtros de estilo Jurik (mantenido por compatibilidad).
Short ShortCandleType H4 Marco temporal usado por el bloque RJTX corto.
Short ShortVolume 0.1 Volumen abierto cuando se ejecuta una señal corta.
Short ShortAllowOpen true Habilitar apertura de posiciones cortas.
Short ShortAllowClose true Habilitar cierre de posiciones cortas en coincidencias alcistas.
Short ShortStopLossPoints 1000 Distancia de stop-loss para operaciones cortas en pasos de precio (0 deshabilita la comprobación).
Short ShortTakeProfitPoints 2000 Distancia de take-profit para operaciones cortas en pasos de precio (0 deshabilita la comprobación).
Short ShortSignalBar 1 Desplazamiento aplicado al leer búferes RJTX para el bloque corto.
Short ShortPeriod 10 Número de barras entre el cierre suavizado actual y la apertura suavizada histórica.
Short ShortMethod Sma Algoritmo de suavizado para el bloque corto.
Short ShortLength 12 Longitud del filtro de suavizado aplicado a las señales cortas.
Short ShortPhase 15 Parámetro de fase para filtros de estilo Jurik en el bloque corto.

Notas

  • Jjma se mapea a Jurik Moving Average. Jurx, Parma y Vidya se aproximan con Zero-Lag EMA, Arnaud Legoux MA y EMA respectivamente, porque StockSharp no expone filtros idénticos de la biblioteca SmoothAlgorithms.
  • La lógica de stop-loss / take-profit se evalúa en los extremos de la vela. Los picos intrabarra más cortos que el máximo/mínimo de la vela no activarán salidas.
  • Las señales se procesan en velas completadas únicamente; las coincidencias intrabarra se ignoran conforme al comportamiento IsNewBar de MT5.
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Exp RJTX Matches Smoothed Duplex strategy using SmoothedMA crossover.
/// Buys when fast SmoothedMA crosses above slow SmoothedMA.
/// Sells on reverse crossover.
/// </summary>
public class ExpRjtxMatchesSmoothedDuplexStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private SmoothedMovingAverage _fast;
	private SmoothedMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	/// <summary>
	/// Fast smoothed MA period.
	/// </summary>
	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	/// <summary>
	/// Slow smoothed MA period.
	/// </summary>
	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	/// <summary>
	/// Stop-loss distance in price steps.
	/// </summary>
	public int StopLossPoints
	{
		get => _stopLossPoints.Value;
		set => _stopLossPoints.Value = value;
	}

	/// <summary>
	/// Take-profit distance in price steps.
	/// </summary>
	public int TakeProfitPoints
	{
		get => _takeProfitPoints.Value;
		set => _takeProfitPoints.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of the <see cref="ExpRjtxMatchesSmoothedDuplexStrategy"/> class.
	/// </summary>
	public ExpRjtxMatchesSmoothedDuplexStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast smoothed MA period", "Indicator");

		_slowPeriod = Param(nameof(SlowPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow smoothed MA period", "Indicator");

		_stopLossPoints = Param(nameof(StopLossPoints), 200)
			.SetNotNegative()
			.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");

		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400)
			.SetNotNegative()
			.SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

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

		_fast = null;
		_slow = null;
		_prevFast = 0;
		_prevSlow = 0;
		_entryPrice = 0;
		_cooldown = 0;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_fast = new SmoothedMovingAverage { Length = FastPeriod };
		_slow = new SmoothedMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!_fast.IsFormed || !_slow.IsFormed)
		{
			_prevFast = fastValue;
			_prevSlow = slowValue;
			return;
		}

		if (_cooldown > 0)
		{
			_cooldown--;
			_prevFast = fastValue;
			_prevSlow = slowValue;
			return;
		}

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		// Check SL/TP
		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step)
			{
				SellMarket();
				_entryPrice = 0;
				_cooldown = 80;
				_prevFast = fastValue;
				_prevSlow = slowValue;
				return;
			}

			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step)
			{
				SellMarket();
				_entryPrice = 0;
				_cooldown = 80;
				_prevFast = fastValue;
				_prevSlow = slowValue;
				return;
			}
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step)
			{
				BuyMarket();
				_entryPrice = 0;
				_cooldown = 80;
				_prevFast = fastValue;
				_prevSlow = slowValue;
				return;
			}

			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step)
			{
				BuyMarket();
				_entryPrice = 0;
				_cooldown = 80;
				_prevFast = fastValue;
				_prevSlow = slowValue;
				return;
			}
		}

		// SmoothedMA crossover
		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();

			BuyMarket();
			_entryPrice = close;
			_cooldown = 80;
		}
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{
			if (Position > 0)
				SellMarket();

			SellMarket();
			_entryPrice = close;
			_cooldown = 80;
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
	}
}