Ver en GitHub

Estrategia RobotPowerM5 Meta4 V12

Descripción general

La estrategia RobotPowerM5 Meta4 V12 es una versión C# del asesor experto MetaTrader 4 RobotPowerM5_meta4V12.mq4. El EA original fue diseñado para gráficos Forex de cinco minutos y evalúa el equilibrio entre Bulls Power y Bears Power para decidir si un nuevo Se debe abrir una posición larga o corta. La versión StockSharp mantiene el comportamiento de una posición a la vez, reproduce el punto ajustes basados en stop-loss/take-profit, y reimplementa la lógica de trailing-stop que bloquea gradualmente las ganancias una vez que el mercado se mueve a favor del comercio.

Lógica de trading

  1. Motor indicador
    • Las velas de cinco minutos están suscritas de forma predeterminada (el período de tiempo se puede configurar a través del parámetro CandleType).
    • Un par de indicadores StockSharp, BullsPower y BearsPower, se actualizan en cada vela terminada usando el configurado período de promediación.
    • El valor combinado BullsPower + BearsPower se almacena con un retraso de una barra para imitar las llamadas shift=1 del Código MQL, que siempre opera en la última barra completamente cerrada.
  2. Reglas de entrada
    • Cuando no hay ninguna posición abierta y la suma retrasada de Bulls/Bears Power es positiva, se emite una orden de compra de mercado.
    • Cuando no hay ninguna posición abierta y la suma retrasada es negativa, se emite una orden de venta de mercado.
    • Las señales se ignoran mientras una posición está activa; el comercio se gestiona exclusivamente a través de salidas protectoras.
  3. Manejo de volumen
    • El parámetro Volume representa el tamaño de lote solicitado. Se pasa directamente a BuyMarket / SellMarket, lo que permite conector para redondear al paso del lote del instrumento si es necesario.

Gestión del riesgo

  • Stop-loss: el stop inicial se coloca a StopLossPoints MetaTrader puntos del precio de ejecución promedio. El nivel es monitoreado con mínimos de velas (para largos) o máximos (para cortos); Una vez tocada la estrategia de salidas al mercado.
  • Take-profit: el objetivo de ganancias es TakeProfitPoints puntos desde la entrada y se evalúa según los máximos y mínimos de las velas, coincidiendo cómo MT4 cierra posiciones cuando se golpea un objetivo dentro de la barra.
  • Trailing stop: después de que el precio se mueve a favor de la operación en más de TrailingStopPoints, se activa un trailing stop. Para posiciones largas, el stop se desplaza a referencePrice - trailingDistance, donde la referencia es el máximo de la vela. cerca y alto. Para cortos, el stop sigue referencePrice + trailingDistance, utilizando el mínimo del cierre y el mínimo de la vela. Esto reproduce el comportamiento de seguimiento de EA que se implementó originalmente con OrderModify.

Parámetros

Nombre Descripción Predeterminado Notas
BullBearPeriod Período promedio proporcionado a los indicadores Bulls Power y Bears Power. 5 Aumentar el valor suaviza el filtro de impulso.
Volume Tamaño de lote solicitado para cada entrada. 1 El volumen real negociado depende del paso del lote y de los límites del corredor.
StopLossPoints Distancia de parada de protección inicial en MetaTrader puntos. 45 Establezca en 0 para desactivar el stop-loss duro.
TakeProfitPoints Distancia de obtención de beneficios en MetaTrader puntos. 150 Establezca en 0 para operar sin un objetivo de ganancias fijo.
TrailingStopPoints Distancia utilizada por el trailing stop una vez que la operación es rentable. 15 Establezca en 0 para deshabilitar el seguimiento.
CandleType Plazo utilizado para los cálculos de los indicadores. 5m time frame Se puede seleccionar cualquier otro DataType si es necesario.

Notas de implementación

  • La estrategia almacena todos los niveles de riesgo (stop-loss, take-profit, trailing stop) internamente y emite salidas de mercado cuando las velas confirmar que se superó un umbral de precio. Esto refleja el enfoque MT4 donde las órdenes se modificaban paso a paso.
  • Las suscripciones a indicadores se cablean a través de Subscription.Bind, que alimenta tanto Bulls Power como Bears Power en una única devolución de llamada.
  • El tamaño en puntos se deriva de Security.PriceStep, manteniendo los parámetros compatibles con instrumentos que cotizan en ticks, pips o centavos.
  • Las comprobaciones de entrada siempre utilizan los valores del indicador anterior, lo que garantiza que las velas parcialmente formadas nunca activen órdenes.

Diferencias frente a la versión MQL

  • La gestión comercial utiliza salidas explícitas del mercado en lugar de modificar la orden de límite de pérdidas vigente; esto es más robusto en diferentes conectores StockSharp y producir el mismo resultado.
  • Los rangos de parámetros se validan a través de StrategyParam ayudantes para que los valores no válidos (por ejemplo, paradas finales negativas) sean rechazado en el momento de la configuración.
  • Los enlaces de registro detallados, la salida de gráficos y las suscripciones de velas aprovechan el API de alto nivel de StockSharp en lugar de los bucles de ticks manuales.
  • La cadena de identificador de experto presente en el script MT4 no es necesaria en StockSharp y, por lo tanto, se ha omitido.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RobotPowerM5: RSI momentum with EMA filter and ATR stops.
/// </summary>
public class RobotPowerM5Meta4V12Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevRsi;
	private decimal _entryPrice;
	private int _cooldown;

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

		_rsiLength = Param(nameof(RsiLength), 14)
			.SetDisplay("RSI Length", "RSI period.", "Indicators");

		_emaLength = Param(nameof(EmaLength), 50)
			.SetDisplay("EMA Length", "Trend filter.", "Indicators");

		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int RsiLength
	{
		get => _rsiLength.Value;
		set => _rsiLength.Value = value;
	}

	public int EmaLength
	{
		get => _emaLength.Value;
		set => _emaLength.Value = value;
	}

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

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

		_prevRsi = 0;
		_entryPrice = 0;
		_cooldown = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevRsi = 0;
		_entryPrice = 0;
		_cooldown = 0;

		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var atr = new AverageTrueRange { Length = AtrLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(rsi, ema, atr, ProcessCandle)
			.Start();

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

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

		if (_prevRsi == 0 || atrVal <= 0)
		{
			_prevRsi = rsiVal;
			return;
		}

		if (_cooldown > 0) { _cooldown--; _prevRsi = rsiVal; return; }

		var close = candle.ClosePrice;

		if (Position > 0)
		{
			if (close >= _entryPrice + atrVal * 2.5m || close <= _entryPrice - atrVal * 1.5m || rsiVal > 80)
			{
				SellMarket();
				_entryPrice = 0;
				_cooldown = 10;
			}
		}
		else if (Position < 0)
		{
			if (close <= _entryPrice - atrVal * 2.5m || close >= _entryPrice + atrVal * 1.5m || rsiVal < 20)
			{
				BuyMarket();
				_entryPrice = 0;
				_cooldown = 10;
			}
		}

		if (Position == 0)
		{
			if (rsiVal > 65 && _prevRsi <= 65 && close > emaVal)
			{
				_entryPrice = close;
				BuyMarket();
				_cooldown = 10;
			}
			else if (rsiVal < 35 && _prevRsi >= 35 && close < emaVal)
			{
				_entryPrice = close;
				SellMarket();
				_cooldown = 10;
			}
		}

		_prevRsi = rsiVal;
	}
}