AbsolutelyNoLagLWMA Kanalbereich TM Plus Strategie
Übersicht
Diese Strategie ist ein direkter Port des MetaTrader-Experten "Exp_AbsolutelyNoLagLwma_Range_Channel_Tm_Plus". Sie handelt einen Preiskanal, der aus einem doppelt geglätteten linearen gewichteten gleitenden Durchschnitt (LWMA) der Kerzenhochs und -tiefs abgeleitet wird. Die StockSharp-Version behält das ursprüngliche Verhalten bei: Signale werden auf abgeschlossenen Kerzen eines auswählbaren Zeitrahmens ausgewertet, der Kanalzustand wird auf dieselbe Weise wie der MQL-Indikator kodiert, und das Positionsmanagement folgt derselben Prioritätsreihenfolge (Zeitausstieg zuerst, Indikatorausstiege zweite, neue Einstiege zuletzt).
Indikatoraufbau
Für jede abgeschlossene Kerze werden die Hoch- und Tiefreihen in einen ersten LWMA eingespeist. Der Längenparameter wird zwischen den Hoch- und Tiefströmen geteilt.
Der Ausgang des ersten LWMA wird erneut mit einem weiteren LWMA gleicher Länge geglättet. Dies recreiert die "AbsolutelyNoLagLWMA"-Glättung des ursprünglichen Indikators.
Die endgültigen oberen und unteren Kanalwerte werden mit dem Kerzenschlusskurs verglichen:
Schluss über der oberen Linie → bullischer Ausbruchszustand.
Schluss unter der unteren Linie → bärischer Ausbruchszustand.
Schluss innerhalb des Kanals → neutraler Zustand.
Die Strategie speichert die jüngsten Kanalzustände. Der Parameter SignalBar steuert, welcher Balkenindex für die Signalgenerierung geprüft wird (0 = letzte geschlossene Kerze, 1 = ein Balken zurück usw.), entsprechend der SignalBar-Eingabe des MQL-Programms.
Signalinterpretation
Long-Einstieg – aktiviert durch EnableBuyEntries. Die Strategie sucht nach einem bullischen Ausbruch auf dem durch SignalBar + 1 indizierten Balken, während der Balken bei SignalBar bereits in den Kanal zurückgekehrt ist. Das Verhalten repliziert den ursprünglichen "vorheriger Balken-Ausbruch"-Test.
Short-Einstieg – aktiviert durch EnableSellEntries. Spiegelt die Long-Logik für bärische Ausbrüche.
Long-Ausstieg – aktiviert durch EnableBuyExits. Ein bärischer Ausbruch auf dem Referenzbalken schließt bestehende Long-Positionen, sofern sie nicht bereits durch den zeitbasierten Ausstieg auf der aktuellen Kerze geschlossen wurden.
Short-Ausstieg – aktiviert durch EnableSellExits. Ein bullischer Ausbruch auf dem Referenzbalken schließt offene Shorts, sofern der zeitbasierte Ausstieg das Schließen noch nicht angefordert hat.
Trade-Management
Auftragsvolumen – entnommen aus dem Parameter OrderVolume. Umkehrorders addieren automatisch den Absolutwert der aktuellen Position, um Restexposure zu vermeiden.
Stop Loss / Take Profit – optionale absolute Offsets definiert in Instrumentenpunkten (StopLossPoints, TakeProfitPoints). Wenn positiv, werden sie in Preisoffsets unter Verwendung des Instruments PriceStep umgerechnet und an StartProtection übergeben.
Zeitbasierter Ausstieg – der ursprüngliche EA schließt Positionen, die eine Haltezeit überschreiten (TimeTrade, nTime). In StockSharp wird dies durch UseTimeExit und HoldingLimit gehandhabt. Der Ausstieg wird vor Indikatorsignalen auf jeder abgeschlossenen Kerze ausgewertet.
Positionszeitplanung – die Strategie zeichnet den Zeitstempel des letzten Trades auf, der zu einer Long- oder Short-Position führte. Diese Zeitstempel werden für den zeitbasierten Ausstieg verwendet.
Parameter
Parameter
Beschreibung
Length
Länge beider LWMA-Durchläufe, die den Kanal formen.
SignalBar
Verschiebung des für Signale untersuchten Balkens (0 = letzte geschlossene Kerze).
CandleType
Zeitrahmen für Indikator und Trade-Auswertung.
OrderVolume
Volumen bei Einreichung neuer Eingangsorders.
StopLossPoints
Stop-Loss-Distanz in Instrumentenpunkten (0 deaktiviert den Stop).
TakeProfitPoints
Take-Profit-Distanz in Instrumentenpunkten (0 deaktiviert das Ziel).
EnableBuyEntries
Neue Long-Positionen erlauben oder verbieten.
EnableSellEntries
Neue Short-Positionen erlauben oder verbieten.
EnableBuyExits
Dem Indikator erlauben, Long-Positionen zu schließen.
EnableSellExits
Dem Indikator erlauben, Short-Positionen zu schließen.
UseTimeExit
Schließen von Positionen nach Ablauf von HoldingLimit aktivieren.
HoldingLimit
Maximale Haltezeit, bevor der Zeitausstieg ausgelöst wird.
Hinweise
Der Kanal wird aus Kerzenhochs und -tiefs genau wie der beigefügte MQL-Indikator AbsolutelyNoLagLwma_Range_Channel berechnet.
Die Strategie ignoriert unvollständige Kerzen und arbeitet nur mit abgeschlossenen Daten, um vorzeitige Signale zu vermeiden.
SignalBar auf 0 zu setzen entspricht der typischen MT5-Konfiguration, bei der die letzte geschlossene Kerze analysiert wird. Höhere Werte reproduzieren die verzögerte Bestätigung des Standard-EA (SignalBar = 1).
Wenn PriceStep für das ausgewählte Instrument nicht verfügbar ist, werden die Stop-Loss- und Take-Profit-Offsets ignoriert, was das Verhalten von Null-Eingaben im ursprünglichen Skript beibehält.
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>
/// LWMA range channel breakout strategy.
/// Uses fast/slow WMA crossover with mid-channel exit logic.
/// </summary>
public class AbsolutelyNoLagLwmaRangeChannelTmPlusStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
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 AbsolutelyNoLagLwmaRangeChannelTmPlusStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast WMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow WMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null;
_prevSlow = null;
var fastWma = new WeightedMovingAverage { Length = FastPeriod };
var slowWma = new WeightedMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastWma, slowWma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastWma);
DrawIndicator(area, slowWma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fast;
_prevSlow = slow;
return;
}
if (_prevFast == null || _prevSlow == null)
{
_prevFast = fast;
_prevSlow = slow;
return;
}
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fast > slow;
_prevFast = fast;
_prevSlow = slow;
// Crossover: fast crosses above slow → buy
if (!prevAbove && currAbove)
{
if (Position < 0)
BuyMarket();
if (Position <= 0)
BuyMarket();
}
// Crossover: fast crosses below slow → sell
else if (prevAbove && !currAbove)
{
if (Position > 0)
SellMarket();
if (Position >= 0)
SellMarket();
}
}
}
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 WeightedMovingAverage
from StockSharp.Algo.Strategies import Strategy
class absolutely_no_lag_lwma_range_channel_tm_plus_strategy(Strategy):
def __init__(self):
super(absolutely_no_lag_lwma_range_channel_tm_plus_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 10) \
.SetDisplay("Fast Period", "Fast WMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetDisplay("Slow Period", "Slow WMA period", "Indicators")
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(absolutely_no_lag_lwma_range_channel_tm_plus_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(absolutely_no_lag_lwma_range_channel_tm_plus_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast_wma = WeightedMovingAverage()
fast_wma.Length = self.FastPeriod
slow_wma = WeightedMovingAverage()
slow_wma.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_wma, slow_wma, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_wma)
self.DrawIndicator(area, slow_wma)
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 self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
elif prev_above and not curr_above:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return absolutely_no_lag_lwma_range_channel_tm_plus_strategy()