Donchian Scalper ist eine StockSharp-Portierung des MetaTrader 4-Expertenberaters DonchianScalperEA. Die Strategie überwacht Donchian Kanalgrenzen und den exponentiellen gleitenden Durchschnitt (EMA) derselben Länge. Eine ausstehende Stop-Order wird erst aktiviert, wenn der Preis wieder unter EMA fällt, was signalisiert, dass die Dynamik vor einem möglichen Ausbruch zurückgesetzt wurde. Einträge werden mit Stop-Orders ausgeführt, die an den aktuellen Donchian-Extremen platziert und durch das entgegengesetzte Band geschützt sind. Gewinne werden entweder durch eine feste Take-Profit-Distanz oder durch adaptive Trailing-Stops gesteuert, die die gewählte Marktstruktur verfolgen.
Strategielogik
Einreisevorbereitung
Pullback-Validierung – die Strategie wartet, bis eine der beiden zuvor geschlossenen Kerzen unter EMA (für Long-Positionen) oder über EMA (für Short-Positionen) fällt. Die Kreuzungsebene wird um den konfigurierbaren Cross Anchor-Abstand versetzt, um sicherzustellen, dass der Rückzug sinnvoll ist.
Breakout-Aktivierung – Sobald die Pullback-Bedingung erfüllt ist und der Cooldown-Timer abgelaufen ist, wird eine Stop-Order an der aktuellsten Donchian-Grenze übermittelt (oberes Band für Long-Positionen, unteres Band für Short-Positionen). Das gegenüberliegende Band definiert den anfänglichen Schutzstopp. Bestehende ausstehende Aufträge werden automatisch neu ausgerichtet, wenn die Donchian-Niveaus für mindestens zwei Kerzen abflachen.
Handelsmanagement
Anfänglicher Schutz – Wenn eine Breakout-Order ausgeführt wird, platziert die Strategie eine schützende Stop-Order unter Verwendung des vorberechneten Stop-Preises. Das Stop-Level entspricht dem gegenüberliegenden Donchian-Band und kann durch die Einstellung Stop Loss (Punkte) nach innen verschoben werden.
Gewinnkontrolle – zwei Verwaltungsmodi stehen zur Verfügung:
Close At Profit – schließt die Position, sobald die Nettobewegung vom durchschnittlichen Einstiegspreis die konfigurierte Take-Profit-Distanz überschreitet.
Trailing – hält den Handel offen und verschärft regelmäßig den Schutzstopp. Die nachfolgende Engine kann der Donchian-Grenze, der EMA oder einem ATR-basierten Volatilitätsband folgen.
Abklingzeit – nachdem alle Positionen geschlossen sind, wartet die Strategie auf die angegebene Anzahl abgeschlossener Kerzen, bevor sie neue Breakout-Orders aktiviert. Dies reproduziert die MetaTrader-Logik, die mindestens drei Balken zwischen den Trades erfordert.
Parameter
Volumen – Ordervolumen, das für Stop-Einstiege und Marktausstiege verwendet wird.
Kanalzeitraum – Donchian Kanallänge, wird auch für den EMA-Filter verwendet.
Kreuzanker – zusätzliche Distanz (in Punkten), die der Rückzug überschreiten muss, bevor der Ausbruchsbefehl aktiviert wird.
Stop-Loss (Punkte) – Distanz, die zum gegenüberliegenden Donchian-Band für den anfänglichen Schutzstopp addiert wird; auf 0 setzen, um den Anschlag direkt auf dem Band zu platzieren.
Take Profit (Punkte) – Gewinnziel, das vom Modus Close At Profit verwendet wird. Wird ignoriert, wenn der Trailing-Modus aktiv ist.
Kerzentyp – Berechnungen von Zeitrahmen-Fahrindikatoren.
Profit-Modus – wählt zwischen dem festen Take-Profit-Exit und adaptiven Trailing-Stops.
Trailing-Modus – Trailing-Engine, die im Trailing-Gewinnmodus verwendet wird. Zur Auswahl stehen Donchian-Grenze, EMA oder ATR-basiertes Nachstellen.
Abklingzeitbalken – Mindestanzahl fertiger Kerzen, die vergehen müssen, nachdem die Position flach geworden ist, bevor neue Aufträge erteilt werden können.
ATR-Periode / ATR-Multiplikator – Parameter für die ATR-Trailing-Engine. Der Multiplikator definiert, wie viele ATRs subtrahiert (Long) oder addiert (Short) werden, um den Trailing Stop zu berechnen.
Zusätzliche Hinweise
Die Strategie richtet jeden Stop- und Einstiegspreis an der Preisstufe des Instruments aus, um die Börsenkonformität sicherzustellen.
Wenn sowohl Long- als auch Short-Stop-Orders aktiv sind, wird durch die Ausführung einer Seite automatisch die gegenüberliegende Pending-Order storniert, um eine Absicherung zu vermeiden.
Wenn Take Profit (Punkte) auf Null gesetzt ist, während der Gewinnmodus bei Close At Profit bleibt, hält die Strategie die Positionen offen, bis der Schutzstopp erreicht wird.
Die Konvertierung konzentriert sich auf die übergeordnete StockSharp API: Indikatorbindung, Kerzenabonnements und Hilfsmethoden (BuyStop, SellStop, SellMarket usw.). Die Python-Implementierung ist in diesem Paket nicht enthalten.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Donchian Channel scalper with EMA filter.
/// Buys on upper channel breakout above EMA, sells on lower breakout below EMA.
/// Exits at middle band.
/// </summary>
public class DonchianScalperStrategy : Strategy
{
private readonly StrategyParam<int> _channelPeriod;
private readonly StrategyParam<DataType> _candleType;
public int ChannelPeriod
{
get => _channelPeriod.Value;
set => _channelPeriod.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public DonchianScalperStrategy()
{
_channelPeriod = Param(nameof(ChannelPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("Channel Period", "Donchian channel lookback", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var donchian = new DonchianChannels { Length = ChannelPeriod };
var ema = new ExponentialMovingAverage { Length = ChannelPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(donchian, ema, (candle, donchianVal, emaVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (donchianVal is not DonchianChannelsValue dcValue)
return;
if (dcValue.UpperBand is not decimal upper ||
dcValue.LowerBand is not decimal lower ||
dcValue.Middle is not decimal middle)
return;
if (emaVal.IsEmpty)
return;
var emaValue = emaVal.GetValue<decimal>();
var close = candle.ClosePrice;
// Long: close breaks above upper Donchian and is above EMA
if (Position == 0 && close >= upper && close > emaValue)
BuyMarket();
// Short: close breaks below lower Donchian and is below EMA
else if (Position == 0 && close <= lower && close < emaValue)
SellMarket();
})
.Start();
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(1, UnitTypes.Percent)
);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, donchian);
DrawIndicator(area, ema);
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
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class donchian_scalper_strategy(Strategy):
def __init__(self):
super(donchian_scalper_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._channel_period = self.Param("ChannelPeriod", 50)
self._highs = []
self._lows = []
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def ChannelPeriod(self):
return self._channel_period.Value
@ChannelPeriod.setter
def ChannelPeriod(self, value):
self._channel_period.Value = value
def OnReseted(self):
super(donchian_scalper_strategy, self).OnReseted()
self._highs = []
self._lows = []
def OnStarted2(self, time):
super(donchian_scalper_strategy, self).OnStarted2(time)
self._highs = []
self._lows = []
ema = ExponentialMovingAverage()
ema.Length = self.ChannelPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, self._process_candle).Start()
self.StartProtection(
takeProfit=Unit(2, UnitTypes.Percent),
stopLoss=Unit(1, UnitTypes.Percent))
def _process_candle(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
high = float(candle.HighPrice)
low = float(candle.LowPrice)
close = float(candle.ClosePrice)
ema_val = float(ema_value)
period = self.ChannelPeriod
self._highs.append(high)
self._lows.append(low)
while len(self._highs) > period:
self._highs.pop(0)
self._lows.pop(0)
if len(self._highs) < period:
return
upper = max(self._highs)
lower = min(self._lows)
# Long: close breaks above upper Donchian and is above EMA
if self.Position == 0 and close >= upper and close > ema_val:
self.BuyMarket()
# Short: close breaks below lower Donchian and is below EMA
elif self.Position == 0 and close <= lower and close < ema_val:
self.SellMarket()
def CreateClone(self):
return donchian_scalper_strategy()