Die Donchian-Kanalbreiten-Ausbruch-Strategie beobachtet den Donchian auf starke Expansionen. Wenn die Werte über ihren durchschnittlichen Bereich hinausspringen, beginnt der Kurs oft eine neue Bewegung.
Tests zeigen eine durchschnittliche jährliche Rendite von etwa 61%. Am besten funktioniert sie auf dem Kryptomarkt.
Eine Position wird eröffnet, sobald der Indikator ein Band durchbricht, das aus aktuellen Daten und einem Abweichungsmultiplikator abgeleitet wird. Long- und Short-Trades sind mit einem Stop möglich.
Dieses System eignet sich für Momentum-Trader, die frühe Ausbrüche suchen. Trades werden geschlossen, wenn der Donchian zur Mitte zurückkehrt. Die Standardwerte beginnen mit DonchianPeriod = 20.
Details
Einstiegskriterien: Indikator überschreitet den Durchschnitt um den Abweichungsmultiplikator.
Long/Short: Beide Richtungen.
Ausstiegskriterien: Indikator kehrt zum Durchschnitt zurück.
Stops: Ja.
Standardwerte:
DonchianPeriod = 20
AvgPeriod = 20
Multiplier = 2.0m
CandleType = TimeSpan.FromMinutes(5)
StopLoss = 2.0m
Filter:
Kategorie: Ausbruch
Richtung: Beide
Indikatoren: Donchian
Stops: Ja
Komplexität: Mittel
Zeitrahmen: Kurzfristig
Saisonalität: Nein
Neuronale Netze: Nein
Divergenz: Nein
Risikolevel: Mittel
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// Strategy that trades on Donchian Channel width breakouts.
/// When Donchian Channel width increases significantly above its average,
/// it enters position in the direction determined by price movement.
/// </summary>
public class DonchianWidthBreakoutStrategy : Strategy
{
private readonly StrategyParam<int> _donchianPeriod;
private readonly StrategyParam<decimal> _widthThreshold;
private readonly StrategyParam<DataType> _candleType;
/// <summary>
/// Donchian Channel period.
/// </summary>
public int DonchianPeriod
{
get => _donchianPeriod.Value;
set => _donchianPeriod.Value = value;
}
/// <summary>
/// Width threshold multiplier for breakout detection.
/// </summary>
public decimal WidthThreshold
{
get => _widthThreshold.Value;
set => _widthThreshold.Value = value;
}
/// <summary>
/// Candle type for strategy.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initialize <see cref="DonchianWidthBreakoutStrategy"/>.
/// </summary>
public DonchianWidthBreakoutStrategy()
{
_donchianPeriod = Param(nameof(DonchianPeriod), 20)
.SetDisplay("Donchian Period", "Period for the Donchian Channel", "Indicators");
_widthThreshold = Param(nameof(WidthThreshold), 1.2m)
.SetDisplay("Width Threshold", "Threshold multiplier for width breakout", "Trading");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var highest = new Highest { Length = DonchianPeriod };
var lowest = new Lowest { Length = DonchianPeriod };
var widthAverage = new SimpleMovingAverage { Length = Math.Max(5, DonchianPeriod / 2) };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(highest, lowest, (candle, highestValue, lowestValue) =>
{
if (candle.State != CandleStates.Finished)
return;
var width = highestValue - lowestValue;
if (width <= 0)
return;
var avgWidthValue = widthAverage.Process(new DecimalIndicatorValue(widthAverage, width, candle.ServerTime) { IsFinal = true });
if (!widthAverage.IsFormed)
return;
var avgWidth = avgWidthValue.ToDecimal();
if (avgWidth <= 0)
return;
var middleChannel = (highestValue + lowestValue) / 2m;
// Width breakout detection
if (width > avgWidth * WidthThreshold && Position == 0)
{
if (candle.ClosePrice > middleChannel)
BuyMarket();
else if (candle.ClosePrice < middleChannel)
SellMarket();
}
})
.Start();
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(1, UnitTypes.Percent)
);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, Unit, UnitTypes, CandleStates
from StockSharp.Algo.Indicators import Highest, Lowest, SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
from indicator_extensions import *
class donchian_width_breakout_strategy(Strategy):
"""
Strategy that trades on Donchian Channel width breakouts.
When Donchian Channel width increases significantly above its average,
it enters position in the direction determined by price movement.
"""
def __init__(self):
super(donchian_width_breakout_strategy, self).__init__()
self._donchianPeriod = self.Param("DonchianPeriod", 20) \
.SetDisplay("Donchian Period", "Period for the Donchian Channel", "Indicators")
self._widthThreshold = self.Param("WidthThreshold", 1.2) \
.SetDisplay("Width Threshold", "Threshold multiplier for width breakout", "Trading")
self._candleType = self.Param("CandleType", tf(5)) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._widthAverage = None
@property
def DonchianPeriod(self):
return self._donchianPeriod.Value
@DonchianPeriod.setter
def DonchianPeriod(self, value):
self._donchianPeriod.Value = value
@property
def WidthThreshold(self):
return self._widthThreshold.Value
@WidthThreshold.setter
def WidthThreshold(self, value):
self._widthThreshold.Value = value
@property
def CandleType(self):
return self._candleType.Value
@CandleType.setter
def CandleType(self, value):
self._candleType.Value = value
def OnReseted(self):
super(donchian_width_breakout_strategy, self).OnReseted()
def OnStarted2(self, time):
super(donchian_width_breakout_strategy, self).OnStarted2(time)
highest = Highest()
highest.Length = self.DonchianPeriod
lowest = Lowest()
lowest.Length = self.DonchianPeriod
donchian_period = self.DonchianPeriod
self._widthAverage = SimpleMovingAverage()
self._widthAverage.Length = max(5, donchian_period // 2)
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(highest, lowest, self.ProcessCandle).Start()
self.StartProtection(
takeProfit=Unit(2, UnitTypes.Percent),
stopLoss=Unit(1, UnitTypes.Percent)
)
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def ProcessCandle(self, candle, highest_value, lowest_value):
if candle.State != CandleStates.Finished:
return
width = float(highest_value) - float(lowest_value)
if width <= 0:
return
avg_result = process_float(self._widthAverage, width, candle.ServerTime, True)
if not self._widthAverage.IsFormed:
return
avg_width = float(avg_result)
if avg_width <= 0:
return
middle_channel = (float(highest_value) + float(lowest_value)) / 2.0
# Width breakout detection
if width > avg_width * self.WidthThreshold and self.Position == 0:
if float(candle.ClosePrice) > middle_channel:
self.BuyMarket()
elif float(candle.ClosePrice) < middle_channel:
self.SellMarket()
def CreateClone(self):
return donchian_width_breakout_strategy()