Ver en GitHub

DeMarker Pendiente 2 Estrategia

Descripción general

La estrategia replica la lógica central del experto MetaTrader "DeMarker Pending 2" utilizando la API de alto nivel de StockSharp. Evalúa un oscilador DeMarker en el marco de tiempo de trabajo y prepara entradas de compra o venta pendientes cuando el indicador cruza umbrales configurables. Las órdenes se pueden crear como solicitudes de parada o límite con una sangría adicional del precio de mercado actual. Un filtro de sesión, una guardia de propagación y controles de distancia mantienen las nuevas entradas bajo control.

Lógica de trading

  1. Suscríbase a la serie de velas configuradas y calcule el indicador DeMarker con el período seleccionado.
  2. Cuando el valor anterior está por encima del nivel inferior y el valor actual cruza por debajo de él, se pone en cola una orden pendiente larga. Cuando el valor anterior está por debajo del nivel superior y el valor actual cruza por encima de él, pone en cola una orden pendiente corta. Sólo se procesa una señal por vela.
  3. Las órdenes pendientes se colocan como órdenes stop o limitadas utilizando la distancia de sangría expresada en puntos. Los pedidos existentes se pueden cancelar antes de la nueva solicitud si la opción de reemplazo está habilitada. La estrategia limita el número total de posiciones abiertas más órdenes pendientes y exige una distancia mínima desde el precio promedio actual de la posición.
  4. Las posiciones largas y cortas utilizan lógica opcional de stop-loss, take-profit y trailing. Los niveles de protección se calculan en puntos de precio y se monitorean en cada vela cerrada. Los topes dinámicos se ajustan una vez que la posición obtiene la ganancia de activación y la distancia adicional del paso final.
  5. Un filtro de diferencial evita nuevos pedidos si el mejor diferencial de oferta/demanda excede el umbral configurado. Los límites de sesión opcionales pueden deshabilitar nuevas entradas fuera de la ventana comercial permitida.

Parámetros

Nombre Descripción
Velas de trabajo Plazo utilizado para señales y controles de protección.
Volumen de pedido Volumen predeterminado para órdenes pendientes.
Stop Loss (pts) Distancia inicial de stop-loss en puntos de precio.
Tomar ganancias (pts) Distancia inicial de obtención de beneficios en puntos de precio.
Activación final (pts) Beneficio necesario antes de que se active el trailing stop.
Trailing Stop (pts) Distancia entre el precio y el trailing stop.
Paso final (pts) Se requiere ganancia adicional para mover el trailing stop.
Sendero en cierre Actualice el trailing stop solo en velas terminadas cuando esté habilitado.
Posiciones máximas Número máximo de posiciones abiertas más órdenes pendientes. Zero desactiva el límite.
Distancia mínima (pts) Distancia mínima desde el precio de la posición actual hasta nuevas entradas pendientes.
Utilice órdenes de parada Coloque órdenes stop cuando sean verdaderas; de lo contrario, se utilizan órdenes limitadas.
Único Pendiente Permita solo una orden pendiente activa a la vez.
Reemplazar Pendientes Cancele las órdenes pendientes pendientes antes de realizar una nueva.
Compensación pendiente (pts) Sangría para nuevos precios pendientes en relación con el mercado.
Spread máximo (pts) Spread máximo permitido antes de omitir la colocación de la orden.
Usar filtro de sesión Habilite o deshabilite el filtro de la ventana comercial.
Hora/minuto de inicio, Hora/minuto de finalización Límites de la sesión cuando el filtro de sesión está activo.
Período de demarcación Período de promediación del oscilador DeMarker.
Nivel superior Umbral que desencadena configuraciones cortas.
Nivel inferior Umbral que desencadena configuraciones largas.

Notas

  • El vencimiento de la orden y el tamaño del riesgo de administración del dinero del experto original no se transfieren. En su lugar, se utiliza un parámetro de volumen fijo.
  • Los niveles de stop-loss y take-profit se evalúan en velas cerradas utilizando precios altos/bajos, que pueden diferir de la ejecución intrabar en MetaTrader.
  • La lógica de seguimiento se evalúa únicamente en velas cerradas. El seguimiento basado en ticks en tiempo real no se reproduce.
  • Las órdenes pendientes se basan en las mejores cotizaciones de oferta y demanda proporcionadas por la fuente de datos. Asegúrese de que las suscripciones de nivel 1 estén disponibles.
namespace StockSharp.Samples.Strategies;

using System;

using Ecng.Common;

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

/// <summary>
/// Pending order strategy driven by the DeMarker oscillator.
/// Simplified from "DeMarker Pending 2" to use market orders on threshold crossovers.
/// </summary>
public class DeMarkerPending2Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _demarkerPeriod;
	private readonly StrategyParam<decimal> _demarkerUpperLevel;
	private readonly StrategyParam<decimal> _demarkerLowerLevel;

	private RelativeStrengthIndex _rsi;
	private decimal? _prevOscillator;

	/// <summary>
	/// Candle type for calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// DeMarker oscillator period.
	/// </summary>
	public int DemarkerPeriod
	{
		get => _demarkerPeriod.Value;
		set => _demarkerPeriod.Value = value;
	}

	/// <summary>
	/// Upper DeMarker threshold for sell signal.
	/// </summary>
	public decimal DemarkerUpperLevel
	{
		get => _demarkerUpperLevel.Value;
		set => _demarkerUpperLevel.Value = value;
	}

	/// <summary>
	/// Lower DeMarker threshold for buy signal.
	/// </summary>
	public decimal DemarkerLowerLevel
	{
		get => _demarkerLowerLevel.Value;
		set => _demarkerLowerLevel.Value = value;
	}

	public DeMarkerPending2Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for calculations", "General");

		_demarkerPeriod = Param(nameof(DemarkerPeriod), 14)
			.SetDisplay("DeMarker Period", "DeMarker oscillator period", "Indicator")
			.SetGreaterThanZero();

		_demarkerUpperLevel = Param(nameof(DemarkerUpperLevel), 0.7m)
			.SetDisplay("Upper Level", "Overbought threshold", "Indicator");

		_demarkerLowerLevel = Param(nameof(DemarkerLowerLevel), 0.3m)
			.SetDisplay("Lower Level", "Oversold threshold", "Indicator");
	}

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

		_prevOscillator = null;
		_rsi = new RelativeStrengthIndex { Length = DemarkerPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(_rsi, ProcessCandle)
			.Start();

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

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

		if (!_rsi.IsFormed)
		{
			_prevOscillator = rsiValue / 100m;
			return;
		}

		if (_prevOscillator is not decimal prev)
		{
			_prevOscillator = rsiValue / 100m;
			return;
		}

		var oscillatorValue = rsiValue / 100m;
		var volume = Volume;
		if (volume <= 0)
			volume = 1;

		// Cross above lower level from below => buy
		if (prev < DemarkerLowerLevel && oscillatorValue >= DemarkerLowerLevel)
		{
			if (Position <= 0)
				BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
		}
		// Cross below upper level from above => sell
		else if (prev > DemarkerUpperLevel && oscillatorValue <= DemarkerUpperLevel)
		{
			if (Position >= 0)
				SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
		}

		_prevOscillator = oscillatorValue;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		_rsi = null;
		_prevOscillator = null;

		base.OnReseted();
	}
}