Diese Strategie ist ein StockSharp-Port des MetaTrader-Experten Standard Deviation Channel. Sie zeichnet einen Volatilitätskanal auf Basis eines linearen gewichteten gleitenden Durchschnitts (LWMA) und handelt Ausbrüche, die mit dem vorherrschenden Trend übereinstimmen. Einstiege werden durch Momentum-Stärke und eine MACD-Bestätigung gefiltert, während Ausstiege feste Ziele, Break-Even-Sprünge und Trailing-Schutz kombinieren.
Indikatoren und Signale
Standard Deviation-Kanal aus einer LWMA-Basislinie und einem konfigurierbaren Abweichungsmultiplikator. Long-Setups erfordern eine steigende obere Bande; Short-Setups erfordern eine fallende untere Bande.
Trendfilter: Schnelle und langsame LWMA auf denselben Kerzen. Longs erfordern LWMA_fast > LWMA_slow; Shorts erfordern das Gegenteil.
Momentum-Filter: Ein 14-Perioden-Momentum-Indikator. Mindestens eine der letzten drei Messwerte muss vom neutralen Niveau 100 um den konfigurierten Schwellenwert abweichen.
MACD-Filter: Klassische 12/26/9-Konfiguration. Long-Einstiege benötigen MACD ≥ signal, während Short-Einstiege MACD ≤ signal erfordern.
Trade-Management
Positionsgrößenbestimmung: Verwendet den Parameter TradeVolume. Umkehrungen schließen automatisch das entgegengesetzte Exposure, bevor die neue Seite eröffnet wird.
Take-Profit & Stop-Loss: In Pips ausgedrückt und gegen den PriceStep des Instruments bewertet. Die Strategie gibt Marktausstiege aus, sobald die Kerzenspanne das Ziel- oder Stop-Preisniveau berührt.
Break-Even-Sprung: Sobald der unrealisierte Gewinn BreakEvenTriggerPips erreicht, wird der Stop auf Einstieg plus BreakEvenOffsetPips verschoben (oder minus bei Shorts).
Trailing Stop: Nach Erreichen von TrailingStartPips folgt der Stop dem Preis um TrailingStepPips und sichert Gewinne auf beiden Seiten.
Kanalablehnungsausstieg: Wenn der Preis zurück in den Kanal schließt und die Neigung gegen die Position abflacht, wird der Trade frühzeitig geschlossen.
Parameter
Name
Beschreibung
CandleType
Primärer Zeitrahmen für alle Berechnungen.
TradeVolume
Basis-Auftragsgröße.
TrendLength
LWMA-Rückblickperiode, die die Kanal-Basislinie definiert.
DeviationMultiplier
Standardabweichungsmultiplikator für die Kanalbreite.
FastMaLength / SlowMaLength
LWMA-Längen für den Trendfilter.
MomentumPeriod
Rückblickperiode für den Momentum-Filter.
MomentumThreshold
Mindestabweichung von 100 in einem der letzten drei Momentum-Werte.
TakeProfitPips / StopLossPips
Abstände der festen Ausstiegsniveaus (umgerechnet mit PriceStep).
BreakEvenTriggerPips / BreakEvenOffsetPips
Steuert wann und wie der Break-Even-Stop aktiviert wird.
Fügen Sie die Strategie einem Wertpapier hinzu, das einen gültigen PriceStep aufweist. Pips werden durch Multiplikation dieses Schrittwerts umgerechnet.
Verwenden Sie TrendLength und DeviationMultiplier, um den Kanal an verschiedene Märkte anzupassen.
Momentum- und MACD-Filter können gelockert werden (niedrigerer Schwellenwert, kürzere Perioden), um die Handelsfrequenz zu erhöhen.
Die Trailing-Logik funktioniert bei Kerzenschlusskursen; Intrabar-Spitzen, die nicht über die Schwellenwerte hinausgehen, werden ignoriert.
Unterschiede zum originalen Expert Advisor
Die MetaTrader-Version verwendet grafische Objekte zur Ablesung der Kanalneigung und nutzt mehrere Money-Management-Zweige (Martingale-Sizing, Eigenkapitalschutz). Dieser Port behält die Neigungsprüfung bei, vereinfacht aber die Risikokontrolle auf Trades fester Größe, begrenzt durch MaxPositionUnits.
Alle Ausstiege werden mit Marktorders beim Kerzenabschluss abgewickelt, da StockSharp-Strategien die MT4-Ordermodifikations-APIs nicht direkt spiegeln.
E-Mail- und Push-Benachrichtigungen werden durch AddInfoLog-Nachrichten ersetzt, um die Konvertierung eigenständig zu halten.
Kapitalbasierte Konto-Stopp-Outs wurden weggelassen; stattdessen liegt der Fokus auf positionsbezogenen Schutzfunktionen.
Haftungsausschluss
Dieses Beispiel ist für Bildungszwecke bestimmt. Führen Sie immer Vorwärtstests durch und validieren Sie die Konfiguration, bevor Sie sie auf einem Live-Konto einsetzen.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class StandardDeviationChannelStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public StandardDeviationChannelStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 standard_deviation_channel_strategy(Strategy):
def __init__(self):
super(standard_deviation_channel_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(standard_deviation_channel_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(standard_deviation_channel_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return standard_deviation_channel_strategy()