Ausbruchsstrategie, die auf dem benutzerdefinierten Kanalindikator CandleStop aufgebaut ist. Das System berechnet kontinuierlich verzögerte Highest-High- und Lowest-Low-Bänder, wartet auf eine abgeschlossene Kerze, die jenseits dieser Bänder schließt, und reagiert dann auf dem folgenden Balken. Es erzwingt optional eine maximale Positionslebensdauer und verwendet punktbasierte Schutzstops.
Details
Einstiegskriterien: Die vorherige abgeschlossene Kerze schließt über dem verzögerten oberen Kanal (für Longs) oder unter dem verzögerten unteren Kanal (für Shorts), während der aktuelle Balken wieder innerhalb des Kanals bleibt, um Doppelauslöser zu vermeiden.
Long/Short: Symmetrische Logik für Long- und Short-Trades mit unabhängigen Aktivierungs-Flags.
Ausstiegskriterien: Gegenläufige CandleStop-Ausbrüche schließen bestehende Positionen; ein optionaler zeitbasierter Ausstieg schließt Trades, die über die konfigurierte Minutenanzahl hinaus offen bleiben.
Stops: Verwendet börsenschrittbasierte Stop-Loss- und Take-Profit-Level über StartProtection.
Standardwerte:
OrderVolume = 1
UpTrailPeriods = 5, UpTrailShift = 5
DownTrailPeriods = 5, DownTrailShift = 5
SignalBar = 1
StopLossPoints = 1000, TakeProfitPoints = 2000
MaxPositionMinutes = 1920
CandleType = 8-Stunden-Zeitrahmen
Filter:
Kategorie: Ausbruch
Richtung: Beide
Indikatoren: Verzögerte CandleStop-Kanäle
Stops: Ja
Komplexität: Mittel
Zeitrahmen: Mehrstündig
Saisonalität: Nein
Neuronale Netze: Nein
Divergenz: Nein
Risikolevel: Mittel
Parameter
OrderVolume: Menge für jeden Markteinstieg, wenn eine neue Position geöffnet wird.
EnableLongEntry / EnableShortEntry: Schalter, die das unabhängige Deaktivieren neuer Longs oder Shorts ermöglichen.
CloseLongOnBearishBreak / CloseShortOnBullishBreak: Ob bestehende Positionen geschlossen werden sollen, wenn die entgegengesetzte CandleStop-Ausbruchsfarbe erscheint.
EnableTimeExit: Aktiviert den Filter für die maximale Haltezeit.
MaxPositionMinutes: Anzahl der Minuten, bevor ein offener Trade zwangsweise geschlossen wird; auf null setzen, um auch bei aktiviertem EnableTimeExit zu deaktivieren.
UpTrailPeriods und UpTrailShift: Lookback-Länge und Rückverschiebung für den bullischen CandleStop-Kanal. Die Verschiebung verzögert das Donchian-Band um mehrere Balken, um das ursprüngliche Indikator-Timing nachzuahmen.
DownTrailPeriods und DownTrailShift: Entsprechende Parameter für den bärischen Kanal.
SignalBar: Index des Balkens, der auf Ausbruchsfarbe geprüft wird (1 = vorherige abgeschlossene Kerze). Der nächst ältere Balken wird zur Bestätigung verwendet, wie in der MQL-Version.
StopLossPoints / TakeProfitPoints: Schutzstop-Abstände in Preisschritten. An StartProtection übergeben, um Ausstiege automatisch zu verwalten.
CandleType: Primäre Kerzenreihe für die Strategie. Standardmäßig 8 Stunden, um dem Quellskript zu entsprechen.
Implementierungshinweise
Die Kanalwerte werden mit Highest- und Lowest-Indikatoren kombiniert mit Shift berechnet, um die verzögerten Bänder des ursprünglichen CandleStop-Indikators zu reproduzieren.
Signalfarben werden in einem Rolling-Buffer gespeichert, um die CopyBuffer-Aufrufe der MQL-Strategie nachzuahmen und doppelte Einstiege auf aufeinanderfolgenden Kerzen zu vermeiden.
Vor der Orderplatzierung prüft die Strategie auf zeitbasierte Ausstiege, schließt gegenläufige Positionen falls erforderlich und gibt dann neue Marktorders mit dem konfigurierten Volumen aus.
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>
/// CandleStop channel breakout strategy.
/// Uses Highest/Lowest channel to detect breakouts and trades on direction changes.
/// </summary>
public class CandleStopSystemTmPlusStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _period;
private decimal? _prevUpper;
private decimal? _prevLower;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int Period
{
get => _period.Value;
set => _period.Value = value;
}
public CandleStopSystemTmPlusStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_period = Param(nameof(Period), 10)
.SetGreaterThanZero()
.SetDisplay("Period", "Channel lookback period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevUpper = null;
_prevLower = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevUpper = null;
_prevLower = null;
var highest = new Highest { Length = Period };
var lowest = new Lowest { Length = Period };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(highest, lowest, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, highest);
DrawIndicator(area, lowest);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal upper, decimal lower)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevUpper = upper;
_prevLower = lower;
return;
}
var close = candle.ClosePrice;
if (_prevUpper == null || _prevLower == null)
{
_prevUpper = upper;
_prevLower = lower;
return;
}
// Breakout above previous upper channel
if (close > _prevUpper.Value && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Breakdown below previous lower channel
else if (close < _prevLower.Value && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevUpper = upper;
_prevLower = lower;
}
}
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 Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class candle_stop_system_tm_plus_strategy(Strategy):
def __init__(self):
super(candle_stop_system_tm_plus_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._period = self.Param("Period", 10) \
.SetDisplay("Period", "Channel lookback period", "Indicators")
self._prev_upper = None
self._prev_lower = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def Period(self):
return self._period.Value
def OnReseted(self):
super(candle_stop_system_tm_plus_strategy, self).OnReseted()
self._prev_upper = None
self._prev_lower = None
def OnStarted2(self, time):
super(candle_stop_system_tm_plus_strategy, self).OnStarted2(time)
self._prev_upper = None
self._prev_lower = None
highest = Highest()
highest.Length = self.Period
lowest = Lowest()
lowest.Length = self.Period
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(highest, lowest, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, highest)
self.DrawIndicator(area, lowest)
self.DrawOwnTrades(area)
def _on_process(self, candle, upper_value, lower_value):
if candle.State != CandleStates.Finished:
return
uv = float(upper_value)
lv = float(lower_value)
close = float(candle.ClosePrice)
if self._prev_upper is None or self._prev_lower is None:
self._prev_upper = uv
self._prev_lower = lv
return
# Breakout above previous upper channel
if close > self._prev_upper and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Breakdown below previous lower channel
elif close < self._prev_lower and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_upper = uv
self._prev_lower = lv
def CreateClone(self):
return candle_stop_system_tm_plus_strategy()