La estrategia MelBar EuroSwiss reproduce la lógica del asesor experto "MelBar EuroSwiss M30 500 1.85x 2Y". Combina Bollinger entradas de ruptura de banda con un filtro de salida basado en el índice de vigor relativo (RVI). La plantilla predeterminada está ajustada para el par EUR/CHF en el marco temporal M30, pero los parámetros se pueden optimizar para otros símbolos.
Al comienzo de cada vela terminada, la estrategia lee las bandas Bollinger y los valores RVI calculados sobre los precios de cierre. Las nuevas posiciones se abren cuando la barra actual se abre más allá de la envolvente mientras que la barra anterior se abre dentro del canal. Este comportamiento imita la lógica de ruptura estilo espacio del robot MQL5 original. Las operaciones largas utilizan la banda inferior como disparador, mientras que las operaciones cortas reaccionan a la banda superior. Las posiciones existentes se cierran cuando el RVI retrasado cruza por encima o por debajo de un nivel absoluto, lo que indica el agotamiento del impulso en la dirección de la operación. Las órdenes de protección opcionales se establecen utilizando distancias de puntos fijas.
El volumen predeterminado es 0,2 lotes, pero el parámetro TradeVolume permite un control preciso sobre el tamaño de la posición. Tanto el stop loss como el takeprofit se expresan en pips y se convierten en compensaciones de precios a través del parámetro configurable PipSize. El mismo tamaño de pipa se reutiliza para armar el módulo de protección en el arranque. Todos los cálculos se basan en velas terminadas para evitar el sesgo de anticipación.
Detalles
Criterios de entrada:
Largo: Vela actual abierta < banda inferior anterior Bollinger Y vela anterior abierta > banda inferior de hace dos velas.
Corto: Vela actual abierta > banda superior anterior Bollinger Y vela anterior abierta <banda superior de hace dos velas.
Criterios de salida:
Largo: Cerrar cuando el valor histórico de RVI excede +RviLevel.
Corto: Cerrar cuando el valor histórico de RVI cae por debajo de -RviLevel.
Stops: Distancias de stop loss fijas opcionales y toma de ganancias en pips.
Indicadores: Bollinger Bandas (período BollingerPeriod, desviación BollingerDeviation) e Índice de Vigor Relativo (RviPeriod).
Valores predeterminados:
TradeVolume = 0,2 lotes
BollingerPeriod = 18
BollingerDeviation = 2,75
RviPeriod = 15
RviLevel = 0,30
StopLossPips = 13
TakeProfitPips = 61
PipSize = 0,0001
CandleType = Intervalo de tiempo.DesdeMinutos(30)
Otras notas:
Categoría: Reversión de ruptura
Dirección: tanto larga como corta.
Plazo: Intradiario (M30 por defecto)
Nivel de riesgo: Medio debido a controles de riesgo fijos basados en pips
Trailing stop: no habilitado de forma predeterminada (se puede implementar externamente)
Los parámetros proporcionados reflejan la configuración original y sirven como un sólido punto de partida para pruebas de avance o ejecuciones de optimización en StockSharp.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// MelBar EuroSwiss strategy: Bollinger Bands breakout with RSI confirmation.
/// Buys when close breaks below lower band with oversold RSI.
/// Sells when close breaks above upper band with overbought RSI.
/// </summary>
public class MelBarEuroSwissStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _bbPeriod;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _signalCooldownCandles;
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int BbPeriod { get => _bbPeriod.Value; set => _bbPeriod.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public MelBarEuroSwissStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_bbPeriod = Param(nameof(BbPeriod), 18)
.SetGreaterThanZero()
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 12)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_candlesSinceTrade = SignalCooldownCandles;
var sma = new SimpleMovingAverage { Length = BbPeriod };
var atr = new AverageTrueRange { Length = BbPeriod };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(sma, atr, rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal sma, decimal atr, decimal rsi)
{
if (candle.State != CandleStates.Finished)
return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
var close = candle.ClosePrice;
var bandDistance = atr * 4m;
if (_candlesSinceTrade >= SignalCooldownCandles && close <= sma - bandDistance && rsi < 25 && Position <= 0)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (_candlesSinceTrade >= SignalCooldownCandles && close >= sma + bandDistance && rsi > 75 && Position >= 0)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
}
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.Indicators import SimpleMovingAverage, AverageTrueRange, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class mel_bar_euro_swiss_strategy(Strategy):
def __init__(self):
super(mel_bar_euro_swiss_strategy, self).__init__()
self._bb_period = self.Param("BbPeriod", 18) \
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI period", "Indicators")
self._signal_cooldown = self.Param("SignalCooldownCandles", 12) \
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading")
self._sma = None
self._atr = None
self._rsi = None
self._candles_since_trade = 0
@property
def bb_period(self):
return self._bb_period.Value
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def signal_cooldown(self):
return self._signal_cooldown.Value
def OnReseted(self):
super(mel_bar_euro_swiss_strategy, self).OnReseted()
self._sma = None
self._atr = None
self._rsi = None
self._candles_since_trade = self.signal_cooldown
def OnStarted2(self, time):
super(mel_bar_euro_swiss_strategy, self).OnStarted2(time)
self._sma = SimpleMovingAverage()
self._sma.Length = self.bb_period
self._atr = AverageTrueRange()
self._atr.Length = self.bb_period
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.rsi_period
self._candles_since_trade = self.signal_cooldown
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(60)))
subscription.Bind(self._sma, self._atr, self._rsi, self._process_candle)
subscription.Start()
def _process_candle(self, candle, sma_value, atr_value, rsi_value):
if candle.State != CandleStates.Finished:
return
if not self._sma.IsFormed or not self._atr.IsFormed or not self._rsi.IsFormed:
return
if self._candles_since_trade < self.signal_cooldown:
self._candles_since_trade += 1
close = float(candle.ClosePrice)
sma_val = float(sma_value)
atr_val = float(atr_value)
rsi_val = float(rsi_value)
band_distance = atr_val * 4.0
if self._candles_since_trade >= self.signal_cooldown and close <= sma_val - band_distance and rsi_val < 25.0 and self.Position <= 0:
self.BuyMarket()
self._candles_since_trade = 0
elif self._candles_since_trade >= self.signal_cooldown and close >= sma_val + band_distance and rsi_val > 75.0 and self.Position >= 0:
self.SellMarket()
self._candles_since_trade = 0
def CreateClone(self):
return mel_bar_euro_swiss_strategy()