Ver en GitHub

Robot ADX + 2 Estrategia MA

Descripción general

La estrategia Robot ADX + 2 MA es una adaptación StockSharp del MetaTrader experto Robot_ADX+2MA. El sistema combina una velocidad rápida y una lenta. media móvil exponencial con los componentes +DI/-DI del índice direccional medio (ADX). Las órdenes sólo se abren cuando el La vela anterior muestra una separación EMA suficientemente amplia y la vela actual confirma el impulso a través del índice direccional. el La conversión mantiene el comportamiento original de abrir como máximo una posición de mercado a la vez y delegar las salidas a stop-loss y protecciones para la toma de ganancias.

Lógica comercial

  1. Suscríbase a la serie de velas principal configurada a través de CandleType y procese solo velas terminadas.
  2. Alimente dos promedios móviles exponenciales (períodos 5 y 12) con los precios de cierre de las velas. Sus valores de la vela anterior. emular el lookback shift = 1 usado en MetaTrader.
  3. Alimente un indicador AverageDirectionalIndex (período 6) con las mismas velas. Almacena el +DI/-DI actual y el anterior. lecturas para replicar los filtros EA.
  4. Calcule la distancia absoluta EMA de la vela anterior y compárela con DifferenceThreshold convertida de puntos a unidades de precio (Point en MetaTrader es igual a Security.PriceStep en StockSharp).
  5. Entrada alcista: permitida sólo si no hay ninguna posición abierta y se cumplen las siguientes condiciones:
    • El rápido anterior EMA está por debajo del lento anterior EMA.
    • El +DI anterior está por debajo de 5, el +DI actual está por encima de 10 y +DI es más fuerte que -DI.
    • La distancia EMA está por encima del umbral configurado.
  6. Entrada bajista: simétrica a las reglas largas, requiere que el EMA rápido anterior esté por encima del EMA lento, los filtros -DI deben ser satisfecho, y -DI para dominar +DI.
  7. Cuando se abre una operación, confíe en el módulo de riesgo iniciado por StartProtection para salir mediante toma de ganancias o parada de pérdidas. Sin manual Se agregan reglas de salida, que coinciden con el experto original.

Parámetros

Nombre Tipo Predeterminado Descripción
CandleType DataType plazo de 1 minuto Serie de velas primarias procesadas por la estrategia.
TakeProfitPoints int 4700 Distancia del objetivo de obtención de beneficios expresada en pasos de precio. Establezca en cero para desactivar.
StopLossPoints int 2400 Distancia del objetivo de stop-loss en pasos de precio. Establezca en cero para desactivar.
TradeVolume decimal 0.1 Volumen neto utilizado para cada orden de mercado.
DifferenceThreshold int 10 Se requiere una distancia mínima de EMA (en pasos de precio) antes de que se acepte una señal.

Gestión de riesgos

  • La versión StockSharp llama a StartProtection con UnitTypes.Step, por lo que las distancias de stop-loss y take-profit configuradas son convertido al paso de precio del corredor automáticamente.
  • Las órdenes de protección se generan como salidas del mercado (useMarketOrders = true), replicando el comportamiento de cierre inmediato del MQL función auxiliar.

Detalles de implementación

  • Los enlaces de indicadores utilizan el SubscribeCandles(...).Bind(...).BindEx(...) API de alto nivel, por lo que no se requieren bucles de datos manuales.
  • Los valores EMA de la vela anterior se almacenan en caché para reproducir las llamadas iMA(..., shift = 1) en el EA original.
  • Los datos ADX se consumen a través de AverageDirectionalIndexValue, lo que brinda acceso directo a los componentes +DI y -DI sin necesidad de llamar GetValue ayudantes prohibidos.
  • Una protección por vela (_lastProcessedTime) garantiza que las señales se evalúen solo una vez, aunque se activen los enlaces EMA y ADX devoluciones de llamada para la misma vela.

Diferencias con el experto MetaTrader

  • Se elimina la llamada directa redundante OrderSend presente en la rama de venta del código MQL; ambas direcciones utilizan un solo BuyMarket/SellMarket ayudante.
  • MetaTrader comprueba el margen libre antes de enviar pedidos. El puerto StockSharp delega controles de riesgo al entorno de alojamiento y supone un equilibrio suficiente.
  • La lógica de protección se implementa a través del administrador de riesgos de StockSharp en lugar de bucles personalizados que llaman repetidamente a OrderSend.

Consejos de uso

  • Ajuste TradeVolume para respetar el paso del lote del valor seleccionado antes de comenzar a operar en vivo.
  • Si el mercado utiliza una escala de precios diferente, modifique DifferenceThreshold junto con las distancias de parada/objetivo para que el EMA La separación es comparable a la configuración MetaTrader.
  • El período de tiempo predeterminado es un minuto, pero el parámetro CandleType permite cambiar a cualquier otra serie respaldada por los datos. fuente.

Indicadores

  • ExponentialMovingAverage(5) calculado sobre precios de cierre.
  • ExponentialMovingAverage(12) calculado sobre precios de cierre.
  • AverageDirectionalIndex(6) proporciona filtros de fuerza +DI/-DI y ADX.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RobotADX2MA: Dual EMA crossover with RSI confirmation and ATR stops.
/// </summary>
public class RobotAdxTwoMaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastEmaLength;
	private readonly StrategyParam<int> _slowEmaLength;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _atrLength;

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

	public RobotAdxTwoMaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");
		_fastEmaLength = Param(nameof(FastEmaLength), 5)
			.SetDisplay("Fast EMA Length", "Fast EMA period.", "Indicators");
		_slowEmaLength = Param(nameof(SlowEmaLength), 12)
			.SetDisplay("Slow EMA Length", "Slow EMA period.", "Indicators");
		_rsiLength = Param(nameof(RsiLength), 14)
			.SetDisplay("RSI Length", "RSI period.", "Indicators");
		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int FastEmaLength { get => _fastEmaLength.Value; set => _fastEmaLength.Value = value; }
	public int SlowEmaLength { get => _slowEmaLength.Value; set => _slowEmaLength.Value = value; }
	public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
	public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }

	/// <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 fastEma = new ExponentialMovingAverage { Length = FastEmaLength };
		var slowEma = new ExponentialMovingAverage { Length = SlowEmaLength };
		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		var atr = new AverageTrueRange { Length = AtrLength };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fastEma, slowEma, rsi, atr, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fastEma); DrawIndicator(area, slowEma); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal, decimal rsiVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished) return;
		if (_prevFast == 0 || _prevSlow == 0 || atrVal <= 0) { _prevFast = fastVal; _prevSlow = slowVal; return; }
		var close = candle.ClosePrice;

		if (Position > 0)
		{
			if ((fastVal < slowVal && _prevFast >= _prevSlow) || close <= _entryPrice - atrVal * 2m) { SellMarket(); _entryPrice = 0; }
		}
		else if (Position < 0)
		{
			if ((fastVal > slowVal && _prevFast <= _prevSlow) || close >= _entryPrice + atrVal * 2m) { BuyMarket(); _entryPrice = 0; }
		}

		if (Position == 0)
		{
			if (fastVal > slowVal && _prevFast <= _prevSlow && rsiVal > 50) { _entryPrice = close; BuyMarket(); }
			else if (fastVal < slowVal && _prevFast >= _prevSlow && rsiVal < 50) { _entryPrice = close; SellMarket(); }
		}
		_prevFast = fastVal; _prevSlow = slowVal;
	}
}