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
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.
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.
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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Strategies import Strategy
from StockSharp.Algo.Indicators import RelativeStrengthIndex, ExponentialMovingAverage, AverageTrueRange
class robot_power_m5_meta4_v12_strategy(Strategy):
def __init__(self):
super(robot_power_m5_meta4_v12_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI period.", "Indicators")
self._ema_length = self.Param("EmaLength", 50) \
.SetDisplay("EMA Length", "Trend filter.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period.", "Indicators")
self._prev_rsi = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def CandleType(self):
return self._candle_type.Value
@property
def RsiLength(self):
return self._rsi_length.Value
@property
def EmaLength(self):
return self._ema_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
def OnStarted2(self, time):
super(robot_power_m5_meta4_v12_strategy, self).OnStarted2(time)
self._prev_rsi = 0.0
self._entry_price = 0.0
self._cooldown = 0
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.RsiLength
self._ema = ExponentialMovingAverage()
self._ema.Length = self.EmaLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._rsi, self._ema, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, rsi_val, ema_val, atr_val):
if candle.State != CandleStates.Finished:
return
rv = float(rsi_val)
ev = float(ema_val)
av = float(atr_val)
if self._prev_rsi == 0 or av <= 0:
self._prev_rsi = rv
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_rsi = rv
return
close = float(candle.ClosePrice)
if self.Position > 0:
if close >= self._entry_price + av * 2.5 or close <= self._entry_price - av * 1.5 or rv > 80:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 10
elif self.Position < 0:
if close <= self._entry_price - av * 2.5 or close >= self._entry_price + av * 1.5 or rv < 20:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 10
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_rsi = rv
return
if self.Position == 0:
if rv > 65 and self._prev_rsi <= 65 and close > ev:
self._entry_price = close
self.BuyMarket()
self._cooldown = 10
elif rv < 35 and self._prev_rsi >= 35 and close < ev:
self._entry_price = close
self.SellMarket()
self._cooldown = 10
self._prev_rsi = rv
def OnReseted(self):
super(robot_power_m5_meta4_v12_strategy, self).OnReseted()
self._prev_rsi = 0.0
self._entry_price = 0.0
self._cooldown = 0
def CreateClone(self):
return robot_power_m5_meta4_v12_strategy()