Ausbruch-Strategie, die den MetaTrader-Experten "Previous Candle Breakdown 2" nachbildet. Der Algorithmus beobachtet die zuletzt abgeschlossene Kerze auf einem konfigurierbaren Zeitrahmen und löst Trades aus, wenn der Preis ihren Hoch- oder Tiefpunkt um einen benutzerdefinierten Pip-Offset durchbricht. Optionale Filterung durch gleitende Durchschnitte, strikte Handelszeiten, Positionsgrößen durch festes Volumen oder prozentuales Risiko sowie mehrschichtige Schutzausstiege replizieren das Verhalten der originalen MQL-Version innerhalb von StockSharp.
Überblick
Einstiegslogik: Long einsteigen, wenn der Preis den Hoch der vorherigen Kerze plus einem Einzug überschreitet. Short einsteigen, wenn der Preis unter den Tief der vorherigen Kerze minus demselben Einzug bricht.
Filter: Optionale schnelle/langsame gleitende Durchschnitte mit Shift-Parametern erfordern eine Richtungsbestätigung vor dem Handel. Der Handel ist auch auf ein Start-/Endzeitfenster beschränkt.
Positionsgrößen: Wahl zwischen einem festen Ordervolumen oder dynamischer Größenanpassung basierend auf dem Portfoliowert und dem Stop-Loss-Abstand.
Risikokontrollen: Statische Stop-Loss- und Take-Profit-Niveaus in Pips, Trailing Stop mit einem Schrittfilter und ein globales Gewinnziel, das alle Positionen schließt.
Skalierung: Das MaxPositions-Limit begrenzt die absolute Netto-Positionsgröße für jede Richtung.
ProfitClose = 100 (Währungseinheiten aus realisiertem + unrealisiertem PnL)
MaxPositions = 10 (absoluter Kontrakt-/Lotanzahl pro Seite)
OrderVolume = 0 (deaktiviert), RiskPercent = 5 (verwendet wenn OrderVolume null ist und Stop-Loss aktiv ist)
StartTime = 09:09, EndTime = 19:19
CandleType = 4-Stunden-Zeitrahmen
Handelsregeln
Die konfigurierte Kerzenserie abonnieren und jede fertige Kerze aufzeichnen.
Prüfen, ob die aktuelle Zeit in die erlaubte Handelssitzung fällt. Wenn ProfitClose erreicht ist, sofort glätten.
Ausbruchsniveaus berechnen, indem der Pip-Einzug zum Hoch und Tief der vorherigen Kerze addiert/subtrahiert wird.
Wenn der Preis diese Niveaus durchbricht und die MA-Bedingungen (sofern aktiviert) erfüllt sind, Trades unter Einhaltung des MaxPositions-Limits eröffnen.
Anfängliche Stop-Loss- und Take-Profit-Abstände vom Eintrittspreis setzen und Trailing Stops aktivieren, sobald sich der Preis mindestens den Trailing-Abstand plus Schritt zugunsten des Trades bewegt hat.
Kerzen kontinuierlich überwachen: Stop-Loss-/Take-Profit-Ausstiege beim Berühren auslösen, Stops beim Preisfortschritt nachziehen und Schutzlevel zurücksetzen, sobald Positionen geschlossen sind.
Hinweise
Pip-Berechnungen passen sich automatisch für 3 oder 5 Dezimalstellen-Instrumente an, um MetaTraders Punkt-zu-Pip-Konvertierung zu imitieren.
Bei der Verwendung der prozentualen Risikogrößenanpassung schätzt der Algorithmus das Volumen aus dem aktuellen Portfoliowert und dem konfigurierten Stop-Loss.
Die Ausbruchsprüfung verwendet fertige Kerzen, daher werden Intrabar-Spitzen auf Kerzenschluss-/Hoch-/Tiefniveaus bewertet.
MaxPositions arbeitet mit der Netto-Position der Strategie. Bei Verwendung von Bruchvolumina stellt der Parameter die maximal erlaubte absolute Nettogröße pro Richtung dar.
Charts zeigen Kerzen, die aktiven gleitenden Durchschnitte wenn aktiviert und ausgeführte Trades zur visuellen Bestätigung.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Previous candle breakdown strategy v2.
/// Trades breakout of previous candle high/low filtered by EMA crossover.
/// </summary>
public class PreviousCandleBreakdown2Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevHigh;
private decimal? _prevLow;
private decimal? _prevFast;
private decimal? _prevSlow;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public PreviousCandleBreakdown2Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10).SetGreaterThanZero().SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30).SetGreaterThanZero().SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevHigh = null;
_prevLow = null;
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevHigh = null; _prevLow = null; _prevFast = null; _prevSlow = null;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
_prevFast = fast;
_prevSlow = slow;
return;
}
if (_prevHigh == null || _prevLow == null || _prevFast == null || _prevSlow == null)
{
_prevHigh = candle.HighPrice; _prevLow = candle.LowPrice; _prevFast = fast; _prevSlow = slow;
return;
}
var close = candle.ClosePrice;
var bullTrend = fast > slow;
var bearTrend = fast < slow;
if (bullTrend && close > _prevHigh.Value && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (bearTrend && close < _prevLow.Value && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevHigh = candle.HighPrice; _prevLow = candle.LowPrice; _prevFast = fast; _prevSlow = slow;
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class previous_candle_breakdown2_strategy(Strategy):
def __init__(self):
super(previous_candle_breakdown2_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 10) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._prev_high = None
self._prev_low = None
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(previous_candle_breakdown2_strategy, self).OnReseted()
self._prev_high = None
self._prev_low = None
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(previous_candle_breakdown2_strategy, self).OnStarted2(time)
self._prev_high = None
self._prev_low = None
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_high = float(candle.HighPrice)
self._prev_low = float(candle.LowPrice)
self._prev_fast = fv
self._prev_slow = sv
return
if self._prev_high is None or self._prev_low is None or self._prev_fast is None or self._prev_slow is None:
self._prev_high = float(candle.HighPrice)
self._prev_low = float(candle.LowPrice)
self._prev_fast = fv
self._prev_slow = sv
return
close = float(candle.ClosePrice)
bull_trend = fv > sv
bear_trend = fv < sv
if bull_trend and close > self._prev_high and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif bear_trend and close < self._prev_low and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_high = float(candle.HighPrice)
self._prev_low = float(candle.LowPrice)
self._prev_fast = fv
self._prev_slow = sv
def CreateClone(self):
return previous_candle_breakdown2_strategy()