Ver en GitHub

MultiStrategyEA v1.2 (puerto StockSharp)

Descripción general

Esta estrategia es una versión StockSharp de alto nivel del asesor experto MetaTrader MultiStrategyEA v1.2. El EA original agrega siete osciladores y gestiona múltiples cuadrículas de órdenes. La versión StockSharp se centra en el aspecto de generación de señales y comercializa una única posición neta impulsada por un consenso entre los módulos de indicadores. La gestión de pedidos, los perfiles de gestión de dinero, las cuadrículas y las funciones de recuperación del código MT5 se omiten intencionalmente para mantener la implementación alineada con el nivel alto API de StockSharp y para mantener la claridad.

Módulos

La estrategia evalúa los siguientes módulos de indicadores en el marco temporal seleccionado:

  1. Oscilador de aceleración/deceleración (AC): utiliza la diferencia entre el Awesome Oscillator y su SMA de 5 períodos. Requiere que el valor actual supere el umbral AcLevel y aumente (o disminuya) en relación con la lectura anterior.
  2. Índice direccional promedio (ADX): confirma las tendencias cuando la fuerza de ADX está por encima de AdxTrendLevel y el movimiento direccional que domina también supera AdxDirectionalLevel.
  3. Awesome Oscillator (AO): detecta ráfagas de impulso cuando el oscilador cruza más allá de AoLevel y continúa en la misma dirección.
  4. DeMarker: señala posibles reversiones cuando el oscilador abandona territorios de sobreventa (100 - DeMarkerThreshold) o sobrecompra (DeMarkerThreshold).
  5. Índice de fuerza + Bollinger bandas: requiere que el precio toque una banda Bollinger, mientras que el índice de fuerza (escalado en el puerto exactamente como en el script MT5) confirma el impulso más allá de ForceConfirmationLevel. Un BandDistanceFilter opcional rechaza señales cuando el ancho de banda, medido en pips, es demasiado estrecho o demasiado ancho.
  6. Índice de flujo de dinero (IMF) – Similar a DeMarker; reacciona a las zonas de sobrecompra y sobreventa determinadas por MfiThreshold.
  7. MACD + Stochastic: exige que tanto MACD (MacdLevel) como Stochastic (StochasticLevel) confirmen el mismo sesgo direccional. MACD debe estar por encima/por debajo del nivel y por encima/por debajo de su línea de señal. Stochastic debe estar por encima/por debajo del umbral y por encima/por debajo de la línea de señal.

Cada módulo aporta un voto de compra, venta o neutral según la última vela terminada.

Lógica del consenso

  • Cuando TradeAllStrategies es verdadero (predeterminado), la estrategia espera hasta que aparezcan al menos RequiredConfirmations votos alcistas con cero votos bajistas antes de entrar en largo. La misma lógica se refleja en los pantalones cortos.
  • Cuando TradeAllStrategies es falso, un solo voto alcista o bajista es suficiente para operar.
  • Si CloseInReverse está habilitado, la estrategia cierra inmediatamente una posición opuesta antes de abrir una nueva.

La implementación opera solo una posición agregada y no intenta recrear la contabilidad de pedidos por módulo del EA original.

Gestión del riesgo

  • StopLossPips y TakeProfitPips se traducen en compensaciones de precios utilizando el PriceStep del instrumento. Para símbolos con 3 o 5 dígitos decimales, el tamaño del pip se multiplica automáticamente por 10, imitando el comportamiento de los pips de FX.
  • Las paradas y los objetivos se verifican en cada vela terminada utilizando máximos y mínimos de velas. Cuando se alcanza cualquiera de los umbrales, se cierra toda la posición.

Diferencias con el Asesor Experto MT5

  • Sin funciones de cuadrícula, martingala o recuperación. El tamaño de la posición se fija mediante el parámetro Volume.
  • Las variantes de señal de cierre (opciones CloseOrdersType en MT5) no están implementadas; las salidas se basan en un stop-loss/take-profit global o en el comportamiento opcional de inversión de señal opuesta.
  • La configuración del indicador en StockSharp refleja la idea principal de cada módulo, pero solo admite la interpretación más común en lugar de las muchas enumeraciones de modos que se encuentran en el script original.
  • Los bloques de administración de dinero (lote automático, protección de cuenta, valoración de pips de símbolos específicos) están fuera del alcance de esta portabilidad de alto nivel.

Parámetros

Parámetro Descripción
CandleType Serie de datos utilizados por cada módulo indicador.
Volume Volumen neto negociado cuando aparece una señal de consenso.
TradeAllStrategies Permite la votación por consenso; de lo contrario, cualquier voto desencadena un intercambio.
RequiredConfirmations Número de votos coincidentes alcistas o bajistas necesarios cuando se habilita el consenso.
CloseInReverse Cierre una posición existente antes de abrir el lado opuesto.
StopLossPips / TakeProfitPips Stop protector y objetivo de ganancias medidos en pips.
UseAcModule, AcLevel Alternancia y umbral para el módulo Accelerator Oscillator.
UseAdxModule, AdxPeriod, AdxTrendLevel, AdxDirectionalLevel Configuración ADX.
UseAoModule, AoLevel Impresionante configuración del oscilador.
UseDeMarkerModule, DeMarkerPeriod, DeMarkerThreshold Configuración del oscilador DeMarker.
UseForceBollingerModule, BollingerPeriod, BollingerDeviation, ForceConfirmationLevel, BandDistanceFilter Índice de fuerza + Bollinger configuración del filtro de banda.
UseMfiModule, MfiPeriod, MfiThreshold Configuración del índice de flujo de dinero.
UseMacdStochasticModule, MacdFastPeriod, MacdSlowPeriod, MacdSignalPeriod, MacdLevel, StochasticPeriod, StochasticSignalPeriod, StochasticSlowing, StochasticLevel Configuración combinada MACD y Stochastic.

Notas de uso

  1. Adjunte la estrategia a un instrumento con suficientes datos históricos para que se formen todos los indicadores.
  2. Configure los umbrales de plazo y módulo para que coincidan con las condiciones de mercado deseadas. Los valores predeterminados replican los valores utilizados en las entradas MT5 EA.
  3. La lógica de consenso es sensible a cuántos módulos están activos. Si desactiva los módulos, considere reducir RequiredConfirmations en consecuencia.
  4. Debido a que la estrategia negocia una única posición neta, es adecuada para su uso dentro de Designer, Runner u otros StockSharp entornos de alto nivel sin enrutamiento de cartera adicional.

Descargo de responsabilidad

Este puerto se centra en la paridad de señales en lugar de reproducir toda la pila de gestión de riesgos y dinero del experto original MetaTrader. La arquitectura simplificada hace que sea más fácil probar, ampliar o integrar en soluciones basadas en StockSharp, pero los resultados diferirán de la versión MT5 cuando las funciones complejas (cuadrículas, lotes de recuperación, cierres parciales) eran el principal impulsor del rendimiento.

namespace StockSharp.Samples.Strategies;

using System;

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

/// <summary>
/// Simplified port of the MetaTrader expert advisor "MultiStrategyEA v1.2".
/// Combines multiple oscillators (RSI, Stochastic, MACD, Bollinger, ADX)
/// and requires a configurable number of bullish or bearish confirmations before entering a trade.
/// </summary>
public class MultiEaV12Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _requiredConfirmations;

	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _rsiUpper;
	private readonly StrategyParam<decimal> _rsiLower;

	private readonly StrategyParam<int> _stochKPeriod;
	private readonly StrategyParam<int> _stochDPeriod;
	private readonly StrategyParam<decimal> _stochUpper;
	private readonly StrategyParam<decimal> _stochLower;

	private readonly StrategyParam<int> _bollingerPeriod;
	private readonly StrategyParam<decimal> _bollingerDeviation;

	private readonly StrategyParam<int> _adxPeriod;
	private readonly StrategyParam<decimal> _adxTrendLevel;

	private readonly StrategyParam<int> _macdFast;
	private readonly StrategyParam<int> _macdSlow;
	private readonly StrategyParam<int> _macdSignal;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int RequiredConfirmations { get => _requiredConfirmations.Value; set => _requiredConfirmations.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public decimal RsiUpper { get => _rsiUpper.Value; set => _rsiUpper.Value = value; }
	public decimal RsiLower { get => _rsiLower.Value; set => _rsiLower.Value = value; }
	public int StochKPeriod { get => _stochKPeriod.Value; set => _stochKPeriod.Value = value; }
	public int StochDPeriod { get => _stochDPeriod.Value; set => _stochDPeriod.Value = value; }
	public decimal StochUpper { get => _stochUpper.Value; set => _stochUpper.Value = value; }
	public decimal StochLower { get => _stochLower.Value; set => _stochLower.Value = value; }
	public int BollingerPeriod { get => _bollingerPeriod.Value; set => _bollingerPeriod.Value = value; }
	public decimal BollingerDeviation { get => _bollingerDeviation.Value; set => _bollingerDeviation.Value = value; }
	public int AdxPeriod { get => _adxPeriod.Value; set => _adxPeriod.Value = value; }
	public decimal AdxTrendLevel { get => _adxTrendLevel.Value; set => _adxTrendLevel.Value = value; }
	public int MacdFast { get => _macdFast.Value; set => _macdFast.Value = value; }
	public int MacdSlow { get => _macdSlow.Value; set => _macdSlow.Value = value; }
	public int MacdSignal { get => _macdSignal.Value; set => _macdSignal.Value = value; }

	public MultiEaV12Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_requiredConfirmations = Param(nameof(RequiredConfirmations), 3)
			.SetDisplay("Required Confirmations", "Number of modules required for entry", "Consensus");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetDisplay("RSI Period", "RSI length", "RSI");

		_rsiUpper = Param(nameof(RsiUpper), 65m)
			.SetDisplay("RSI Upper", "Overbought level", "RSI");

		_rsiLower = Param(nameof(RsiLower), 35m)
			.SetDisplay("RSI Lower", "Oversold level", "RSI");

		_stochKPeriod = Param(nameof(StochKPeriod), 10)
			.SetDisplay("Stochastic %K", "%K period", "Stochastic");

		_stochDPeriod = Param(nameof(StochDPeriod), 3)
			.SetDisplay("Stochastic %D", "%D period", "Stochastic");

		_stochUpper = Param(nameof(StochUpper), 70m)
			.SetDisplay("Stoch Upper", "Overbought", "Stochastic");

		_stochLower = Param(nameof(StochLower), 30m)
			.SetDisplay("Stoch Lower", "Oversold", "Stochastic");

		_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
			.SetDisplay("Bollinger Period", "BB length", "Bollinger");

		_bollingerDeviation = Param(nameof(BollingerDeviation), 2m)
			.SetDisplay("Bollinger Deviation", "BB width", "Bollinger");

		_adxPeriod = Param(nameof(AdxPeriod), 14)
			.SetDisplay("ADX Period", "ADX length", "ADX");

		_adxTrendLevel = Param(nameof(AdxTrendLevel), 20m)
			.SetDisplay("ADX Trend Level", "Min ADX for trend", "ADX");

		_macdFast = Param(nameof(MacdFast), 12)
			.SetDisplay("MACD Fast", "Fast EMA period", "MACD");

		_macdSlow = Param(nameof(MacdSlow), 26)
			.SetDisplay("MACD Slow", "Slow EMA period", "MACD");

		_macdSignal = Param(nameof(MacdSignal), 9)
			.SetDisplay("MACD Signal", "Signal line period", "MACD");
	}

	/// <inheritdoc />
	public override System.Collections.Generic.IEnumerable<(StockSharp.BusinessEntities.Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

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

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		var stochastic = new StochasticOscillator();
		stochastic.K.Length = StochKPeriod;
		stochastic.D.Length = StochDPeriod;

		var bollinger = new BollingerBands { Length = BollingerPeriod, Width = BollingerDeviation };

		var adx = new AverageDirectionalIndex { Length = AdxPeriod };

		var macd = new MovingAverageConvergenceDivergenceSignal();
		macd.Macd.ShortMa.Length = MacdFast;
		macd.Macd.LongMa.Length = MacdSlow;
		macd.SignalMa.Length = MacdSignal;

		var subscription = SubscribeCandles(CandleType);

		subscription
			.BindEx(rsi, stochastic, bollinger, adx, macd, ProcessCandle)
			.Start();

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

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue rsiVal, IIndicatorValue stochVal, IIndicatorValue bbVal, IIndicatorValue adxVal, IIndicatorValue macdVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!rsiVal.IsFinal || !stochVal.IsFinal || !bbVal.IsFinal || !adxVal.IsFinal || !macdVal.IsFinal)
			return;

		if (!rsiVal.IsFormed || !stochVal.IsFormed || !bbVal.IsFormed || !adxVal.IsFormed || !macdVal.IsFormed)
			return;

		var rsi = rsiVal.GetValue<decimal>();
		var stoch = (StochasticOscillatorValue)stochVal;
		var stochK = stoch.K ?? 50m;
		var bb = (BollingerBandsValue)bbVal;
		var bbUpper = bb.UpBand ?? candle.ClosePrice;
		var bbLower = bb.LowBand ?? candle.ClosePrice;
		var adxTyped = (AverageDirectionalIndexValue)adxVal;
		var adxMain = adxTyped.MovingAverage ?? 0m;
		var adxPlus = adxTyped.Dx.Plus ?? 0m;
		var adxMinus = adxTyped.Dx.Minus ?? 0m;
		var macdTyped = (MovingAverageConvergenceDivergenceSignalValue)macdVal;
		var macdLine = macdTyped.Macd ?? 0m;
		var macdSignalLine = macdTyped.Signal ?? 0m;

		var close = candle.ClosePrice;

		// Count bullish and bearish signals from each module
		var bullish = 0;
		var bearish = 0;

		// Module 1: RSI
		if (rsi < RsiLower) bullish++;
		else if (rsi > RsiUpper) bearish++;

		// Module 2: Stochastic
		if (stochK < StochLower) bullish++;
		else if (stochK > StochUpper) bearish++;

		// Module 3: Bollinger Bands
		if (close <= bbLower) bullish++;
		else if (close >= bbUpper) bearish++;

		// Module 4: ADX directional
		if (adxMain >= AdxTrendLevel)
		{
			if (adxPlus > adxMinus) bullish++;
			else if (adxMinus > adxPlus) bearish++;
		}

		// Module 5: MACD
		if (macdLine > macdSignalLine && macdLine > 0) bullish++;
		else if (macdLine < macdSignalLine && macdLine < 0) bearish++;

		var minConfirmations = RequiredConfirmations;

		// Enter on consensus
		if (bullish >= minConfirmations && bearish == 0 && Position <= 0)
		{
			BuyMarket();
		}
		else if (bearish >= minConfirmations && bullish == 0 && Position >= 0)
		{
			SellMarket();
		}
		// Exit when consensus breaks
		else if (Position > 0 && bearish >= 2)
		{
			SellMarket();
		}
		else if (Position < 0 && bullish >= 2)
		{
			BuyMarket();
		}
	}
}