Ver en GitHub

Estrategia aleatoria

Descripción general

Esta estrategia es una versión StockSharp del MetaTrader 4 asesores expertos "RandomT". El EA original espera una oscilación en ZigZag que coincida con un fractal confirmado y luego filtra la entrada con una comparación MACD. La versión StockSharp mantiene el mismo proceso de decisión: observa un número configurable de velas (BarWatch), confirma que un fractal de cinco barras marca el extremo de oscilación más reciente y solo opera cuando la línea principal MACD está por encima o por debajo de la línea de señal en la misma barra histórica.

Lógica comercial

  • Cree buffers de velas móviles y calcule la señal MACD en cada barra terminada del período de tiempo seleccionado (CandleType).
  • Mire Shift barras hacia el pasado y compruebe si esa barra forma un fractal hacia arriba o hacia abajo (dos velas a cada lado).
  • Valide el fractal frente a la acción del precio circundante: el máximo debe ser el valor más grande, o el mínimo, el valor más pequeño, dentro de la ventana retrospectiva BarWatch. Esto refleja la confirmación de swing en ZigZag utilizada por la versión MetaTrader.
  • Para una configuración breve, el valor principal MACD debe ser mayor que el valor de la señal en la barra desplazada. Para una configuración larga, la comparación opuesta debe ser cierta.
  • Cuando aparece una señal, la estrategia utiliza una orden de mercado única cuyo volumen neutraliza cualquier posición opuesta antes de abrir la nueva operación.

Gestión de trailing stop

  • El bloque final se activa solo cuando UseTrailingProfit está habilitado y la ganancia flotante (convertida a través de PriceStep y StepPrice) excede MinProfit.
  • La distancia de seguimiento se mide en puntos de precio. Cuando AutoStopLevel es true, el motor usa StartStopLevelPoints; de lo contrario utiliza StopLevelPoints.
  • Para posiciones largas, la parada sigue a ClosePrice - distance, para posiciones cortas sigue a ClosePrice + distance. Si la vela atraviesa el nivel de stop, la estrategia cierra la operación con una orden de mercado.

Parámetros

Parámetro Descripción
TradeVolume Tamaño comercial base en lotes utilizados para cada entrada.
BarWatch Número de barras utilizadas para validar que un fractal es también un extremo de oscilación en ZigZag.
Shift Número de barras en el historial que se evalúan en busca de señales. Debería permanecer en 2 para los fractales clásicos.
UseTrailingProfit Habilita la lógica del trailing stop.
AutoStopLevel Cambia la distancia de seguimiento a StartStopLevelPoints.
StartStopLevelPoints Distancia de seguimiento alternativa (puntos).
StopLevelPoints Distancia de seguimiento primaria (puntos).
MinProfit Se requiere un beneficio flotante mínimo (moneda de la cuenta) antes de aplicar el seguimiento.
CandleType Marco de tiempo utilizado para velas y cálculos de indicadores.
MacdFastLength Período EMA rápida para el filtro MACD.
MacdSlowLength Período EMA lento para el filtro MACD.
MacdSignalLength Periodo de señal EMA para el filtro MACD.

Notas

  • La estrategia calcula fractales internamente (dos barras en cada lado) y reutiliza el resultado para la validación de ZigZag, coincidiendo estrechamente con los buffers a los que se accede en el código MQL.
  • La confirmación del ZigZag se aproxima comprobando las velas BarWatch circundantes en lugar de volver a ejecutar el indicador MetaTrader completo, lo que mantiene el comportamiento determinista dentro de StockSharp.
  • El beneficio del trailing-stop se deriva de los PriceStep y StepPrice del instrumento. Verifique estos valores para su instrumento antes de ejecutar la estrategia.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RandomT: EMA crossover with RSI filter and ATR stops.
/// </summary>
public class RandomTStrategy : 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 RandomTStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");
		_fastEmaLength = Param(nameof(FastEmaLength), 12)
			.SetDisplay("Fast EMA Length", "Fast EMA period.", "Indicators");
		_slowEmaLength = Param(nameof(SlowEmaLength), 26)
			.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;
	}
}