Die MelBar EuroSwiss-Strategie reproduziert die Logik des Expertenberaters „MelBar EuroSwiss M30 500 1,85x 2Y“. Es kombiniert Bollinger Band-Breakout-Einträge mit einem Ausstiegsfilter basierend auf dem Relative Vigor Index (RVI). Die Standardvorlage ist auf das EUR/CHF-Paar im M30-Zeitrahmen abgestimmt, die Parameter können jedoch für andere Symbole optimiert werden.
Zu Beginn jeder fertigen Kerze liest die Strategie die Bollinger-Bänder und die auf Schlusskursen berechneten RVI-Werte. Neue Positionen werden eröffnet, wenn der aktuelle Balken über die Hüllkurve hinaus öffnet, während der vorherige Balken wieder innerhalb des Kanals geöffnet hat. Dieses Verhalten imitiert die Gap-Style-Breakout-Logik des ursprünglichen MQL5-Roboters. Long-Trades nutzen das untere Band als Auslöser, während Short-Trades auf das obere Band reagieren. Bestehende Positionen werden geschlossen, wenn der verzögerte RVI ein absolutes Niveau überschreitet oder unterschreitet, was auf eine Erschöpfung des Momentums in Richtung des Handels hinweist. Optionale Schutzbefehle werden anhand fester Pip-Abstände festgelegt.
Das Standardvolumen beträgt 0,2 Lots, aber der Parameter TradeVolume ermöglicht eine feine Steuerung der Positionsgröße. Sowohl Stop-Loss als auch Take-Profit werden in Pips ausgedrückt und über den konfigurierbaren Parameter PipSize in Preis-Offsets umgewandelt. Die gleiche Pip-Größe wird wiederverwendet, um das Schutzmodul beim Start zu aktivieren. Alle Berechnungen basieren auf fertigen Kerzen, um eine Voreingenommenheit zu vermeiden.
Einzelheiten
Eintrittskriterien:
Long: Aktuelle Kerzenöffnung < vorheriges unteres Bollinger-Band UND vorheriges Kerzenöffnungsband > unteres Band von vor zwei Kerzen.
Short: Aktuelle Kerzenöffnung > vorheriges oberes Bollinger-Band UND vorherige Kerzenöffnung < oberes Band von vor zwei Kerzen.
Ausstiegskriterien:
Long: Schließen, wenn der historische RVI-Wert +RviLevel überschreitet.
Short: Schließen, wenn der historische RVI-Wert unter -RviLevel fällt.
Stops: Optionale feste Stop-Loss- und Take-Profit-Abstände in Pips.
Indikatoren: Bollinger-Bänder (Zeitraum BollingerPeriod, Abweichung BollingerDeviation) und Relative Vigor Index (RviPeriod).
Standardwerte:
TradeVolume = 0,2 Lose
BollingerPeriod = 18
BollingerDeviation = 2,75
RviPeriod = 15
RviLevel = 0,30
StopLossPips = 13
TakeProfitPips = 61
PipSize = 0,0001
CandleType = TimeSpan.FromMinutes(30)
Andere Hinweise:
Kategorie: Ausbruchsumkehr
Richtung: Sowohl lang als auch kurz
Zeitrahmen: Intraday (standardmäßig M30)
Risikostufe: Mittel aufgrund fester Pip-basierter Risikokontrollen
Trailing Stop: Standardmäßig nicht aktiviert (kann extern implementiert werden)
Die bereitgestellten Parameter spiegeln die ursprüngliche Konfiguration wider und dienen als solider Ausgangspunkt für Walk-Forward-Tests oder Optimierungsläufe in 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()