Diese Strategie repliziert den klassischen MetaTrader-Expert-Advisor "BreakOut" von Soubra2003. Sie überwacht das Hoch und Tief
der zuletzt abgeschlossenen Kerze und reagiert, wenn der aktuelle Schlusskurs diese Referenzniveaus durchbricht. Der Ansatz
ist vollständig symmetrisch: Long-Positionen werden bei bullischen Ausbrüchen eröffnet, und Short-Positionen werden bei
bearischen Einbrüchen eröffnet. Optionale Stop-Loss- und Take-Profit-Puffer in Preiseinheiten ermöglichen es dem Benutzer,
das Risiko zu begrenzen oder Gewinne zu sichern.
Überblick
Abonniert eine einzelne Kerzenserie (standardmäßig 1-Stunden-Zeitrahmen).
Speichert Hoch und Tief der vorherigen Kerze als Ausbruchsauslöser.
Handelt nur bei Kerzenschluss, um die ursprüngliche tick-basierte Logik ohne Intrabar-Daten zu spiegeln.
Unterstützt sowohl Long- als auch Short-Trades und bleibt immer flach, wenn keine Ausbruchsbedingung aktiv ist.
Handelsregeln
Ausbruchseinstieg / Umkehr
Wenn der Schlusskurs der aktuellen abgeschlossenen Kerze strikt über dem Hoch der vorherigen Kerze liegt:
Jede offene Short-Position wird zu Marktpreisen geschlossen.
Unmittelbar danach wird eine neue Long-Position eröffnet (die Umkehr erfolgt innerhalb desselben Kerzenverarbeitungsschritts).
Wenn der Schlusskurs strikt unter dem Tief der vorherigen Kerze liegt:
Jede offene Long-Position wird zu Marktpreisen geschlossen.
Anschließend wird eine neue Short-Position eröffnet.
Schützende Ausstiege (optional)
Wenn ein Stop-Loss-Offset konfiguriert ist (> 0), verlässt die Strategie ein Long, wenn der Schlusskurs offset Einheiten
unter den Einstiegspreis fällt, oder verlässt ein Short, wenn der Schlusskurs offset Einheiten über den Einstiegspreis steigt.
Wenn ein Take-Profit-Offset konfiguriert ist (> 0), verlässt die Strategie ein Long, wenn der Schlusskurs offset Einheiten
über den Einstiegspreis steigt, oder verlässt ein Short, wenn der Schlusskurs offset Einheiten unter den Einstiegspreis fällt.
Zustandsreset
Nach jeder verarbeiteten Kerze werden das zuletzt gesehene Hoch und Tief zu den neuen Ausbruchs-Referenzniveaus.
Parameter
Candle Type – Datentyp für das Abonnement (standardmäßig stündlicher Zeitrahmen). Stellen Sie dies auf die Balkengröße ein,
die dem in MetaTrader für den ursprünglichen Expert verwendeten Chart entspricht.
Stop Loss – Abstand in absoluten Preiseinheiten zwischen dem Einstiegspreis und dem Schutz-Stop. Bei 0 belassen, um
die Stop-Loss-Behandlung zu deaktivieren.
Take Profit – Abstand in absoluten Preiseinheiten zwischen dem Einstiegspreis und dem Gewinnziel. Bei 0 belassen, um
die Take-Profit-Behandlung zu deaktivieren.
Hinweise
Die Stop-Loss- und Take-Profit-Berechnungen werden auf Kerzenschlusspreisen durchgeführt. Die ursprüngliche MQL4-Version hängte
statische SL/TP-Niveaus an die Orders; in StockSharp werden die Ausstiege simuliert, indem Marktorders gesendet werden, sobald
die Schwellenwerte erreicht sind.
Verwenden Sie instrumentenspezifische Preiserhöhungen beim Konfigurieren der Offsets. Wenn das Instrument beispielsweise mit
einer Tick-Größe von 0.01 handelt und Sie einen 20-Tick-Stop möchten, setzen Sie den Stop-Loss-Parameter auf 0.20.
Da die Logik immer auf die unmittelbar vorangehende Kerze verweist, funktioniert die Strategie am besten bei Trendingstrumenten
oder während hochvolatiler Sitzungen, bei denen Ausbrüche bedeutungsvoll sind.
Herkunft
Quelle: MQL/17306/BreakOut.mq4 (BreakOut-Expert-Advisor von Soubra2003)
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Breakout strategy that trades when the close crosses the previous candle's high or low.
/// Ported from the BreakOut.mq4 expert by Soubra2003.
/// </summary>
public class PreviousCandleBreakoutStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _stopLossOffset;
private readonly StrategyParam<decimal> _takeProfitOffset;
private decimal? _previousHigh;
private decimal? _previousLow;
private decimal _entryPrice;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public decimal StopLossOffset { get => _stopLossOffset.Value; set => _stopLossOffset.Value = value; }
public decimal TakeProfitOffset { get => _takeProfitOffset.Value; set => _takeProfitOffset.Value = value; }
public PreviousCandleBreakoutStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromDays(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for candle subscription", "General");
_stopLossOffset = Param(nameof(StopLossOffset), 1000m)
.SetDisplay("Stop Loss", "Price distance for the stop-loss. Set 0 to disable.", "Risk")
;
_takeProfitOffset = Param(nameof(TakeProfitOffset), 1500m)
.SetDisplay("Take Profit", "Price distance for the take-profit. Set 0 to disable.", "Risk")
;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_previousHigh = null;
_previousLow = null;
_entryPrice = 0m;
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, CandleType);
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_previousHigh is null || _previousLow is null)
{
// Store the first finished candle to obtain reference high/low levels.
_previousHigh = candle.HighPrice;
_previousLow = candle.LowPrice;
return;
}
var previousHigh = _previousHigh.Value;
var previousLow = _previousLow.Value;
var close = candle.ClosePrice;
var breakoutAbove = close > previousHigh;
var breakoutBelow = close < previousLow;
// Manage protective exits while a position is open.
if (Position > 0)
{
if (StopLossOffset > 0m && close <= _entryPrice - StopLossOffset)
{
if (Position > 0) SellMarket(); else if (Position < 0) BuyMarket();
_entryPrice = 0m;
}
else if (TakeProfitOffset > 0m && close >= _entryPrice + TakeProfitOffset)
{
if (Position > 0) SellMarket(); else if (Position < 0) BuyMarket();
_entryPrice = 0m;
}
}
else if (Position < 0)
{
if (StopLossOffset > 0m && close >= _entryPrice + StopLossOffset)
{
if (Position > 0) SellMarket(); else if (Position < 0) BuyMarket();
_entryPrice = 0m;
}
else if (TakeProfitOffset > 0m && close <= _entryPrice - TakeProfitOffset)
{
if (Position > 0) SellMarket(); else if (Position < 0) BuyMarket();
_entryPrice = 0m;
}
}
// Breakout above the previous high opens or reverses into a long position.
if (breakoutAbove)
{
if (Position < 0)
{
if (Position > 0) SellMarket(); else if (Position < 0) BuyMarket();
_entryPrice = 0m;
}
if (Position <= 0)
{
BuyMarket();
_entryPrice = close;
}
}
else if (breakoutBelow)
{
// Breakout below the previous low opens or reverses into a short position.
if (Position > 0)
{
if (Position > 0) SellMarket(); else if (Position < 0) BuyMarket();
_entryPrice = 0m;
}
if (Position >= 0)
{
SellMarket();
_entryPrice = close;
}
}
_previousHigh = candle.HighPrice;
_previousLow = candle.LowPrice;
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Strategies import Strategy
class previous_candle_breakout_strategy(Strategy):
def __init__(self):
super(previous_candle_breakout_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromDays(1)))
self._stop_loss_offset = self.Param("StopLossOffset", 1000.0)
self._take_profit_offset = self.Param("TakeProfitOffset", 1500.0)
self._previous_high = None
self._previous_low = None
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def StopLossOffset(self):
return self._stop_loss_offset.Value
@StopLossOffset.setter
def StopLossOffset(self, value):
self._stop_loss_offset.Value = value
@property
def TakeProfitOffset(self):
return self._take_profit_offset.Value
@TakeProfitOffset.setter
def TakeProfitOffset(self, value):
self._take_profit_offset.Value = value
def OnStarted2(self, time):
super(previous_candle_breakout_strategy, self).OnStarted2(time)
self._previous_high = None
self._previous_low = None
self._entry_price = 0.0
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self.ProcessCandle).Start()
def ProcessCandle(self, candle):
if candle.State != CandleStates.Finished:
return
high = float(candle.HighPrice)
low = float(candle.LowPrice)
close = float(candle.ClosePrice)
if self._previous_high is None or self._previous_low is None:
self._previous_high = high
self._previous_low = low
return
previous_high = self._previous_high
previous_low = self._previous_low
breakout_above = close > previous_high
breakout_below = close < previous_low
sl = float(self.StopLossOffset)
tp = float(self.TakeProfitOffset)
if self.Position > 0:
if sl > 0.0 and close <= self._entry_price - sl:
self.SellMarket()
self._entry_price = 0.0
elif tp > 0.0 and close >= self._entry_price + tp:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if sl > 0.0 and close >= self._entry_price + sl:
self.BuyMarket()
self._entry_price = 0.0
elif tp > 0.0 and close <= self._entry_price - tp:
self.BuyMarket()
self._entry_price = 0.0
if breakout_above:
if self.Position < 0:
self.BuyMarket()
self._entry_price = 0.0
if self.Position <= 0:
self.BuyMarket()
self._entry_price = close
elif breakout_below:
if self.Position > 0:
self.SellMarket()
self._entry_price = 0.0
if self.Position >= 0:
self.SellMarket()
self._entry_price = close
self._previous_high = high
self._previous_low = low
def OnReseted(self):
super(previous_candle_breakout_strategy, self).OnReseted()
self._previous_high = None
self._previous_low = None
self._entry_price = 0.0
def CreateClone(self):
return previous_candle_breakout_strategy()