Exp Rj SlidingRangeRj Digit System Tm Plus Strategie
Übersicht
Diese StockSharp-Strategie ist ein Port des MetaTrader-Expertenberaters Exp_Rj_SlidingRangeRj_Digit_System_Tm_Plus. Sie recreiert die ursprüngliche Handelslogik basierend auf dem benutzerdefinierten Kanalindikator Rj_SlidingRangeRj_Digit und bewahrt die konfigurierbaren Trade-Management-Optionen. Die Strategie überwacht abgeschlossene Kerzen auf einem konfigurierbaren Zeitrahmen, erkennt Ausbrüche jenseits des Kanals und reagiert auf diese Ereignisse mit verzögerten Einstiegen, optionalen zeitgesteuerten Ausstiegen und preisbasiertem Stop/Ziel-Management.
Indikatorlogik
Der Rj_SlidingRangeRj_Digit-Indikator baut einen adaptiven Preiskanal durch einen mehrstufigen Mittelungsprozess auf:
Für das obere Band wird das Highest-High innerhalb von UpCalcPeriodRange Balken für jedes der letzten UpCalcPeriodRange gleitenden Fenster berechnet, verschoben um UpCalcPeriodShift Balken. Der Durchschnitt dieser Maxima wird auf die durch UpDigit angegebene Präzision gerundet.
Das untere Band wiederholt die gleiche Logik für Tiefs mit DnCalcPeriodRange, DnCalcPeriodShift und DnDigit.
Eine Kerze wird als Ausbruch markiert, wenn ihr Schlusskurs über dem oberen Band (Farben 2 / 3) oder unter dem unteren Band (Farben 0 / 1) liegt. Kerzen innerhalb des Kanals erzeugen eine neutrale Farbe (4).
Die Strategie streamt abgeschlossene Kerzen, baut die Bänder bei jedem Update neu auf und speichert die jüngsten Farbcodes, um das CopyBuffer/SignalBar-Verhalten der MQL-Implementierung nachzuahmen.
Handelsregeln
Eintrittsverzögerung: Signale werden auf dem durch SignalBar definierten Balken ausgewertet (Standard: ein Balken zurück). Die Strategie wartet, bis eine Ausbruchsfarbe erscheint und der vorherige Balken nicht dieselbe Ausbruchsfarbe hatte. Dies reproduziert die ursprüngliche Ein-Balken-Verzögerung vor der Trade-Ausführung.
Long-Einstiege: Aktiviert durch EnableBuyEntries. Ein bullischer Ausbruch (Farbe 2 oder 3) löst einen Marktkauf aus, wenn keine Long-Position offen ist (Short-Exposure wird automatisch verrechnet).
Short-Einstiege: Aktiviert durch EnableSellEntries. Ein bärischer Ausbruch (Farbe 0 oder 1) löst einen Marktverkauf aus, wenn keine Short-Position offen ist.
Ausstiegssignale:
Longs schließen bei bärischen Ausbruchsfarben, wenn EnableBuyExits true ist.
Shorts schließen bei bullischen Ausbruchsfarben, wenn EnableSellExits true ist.
Optionaler zeitbasierter Ausstieg (UseTimeExit) schließt jede offene Position, sobald sie länger als ExitMinutes gehalten wurde.
Optionale Stop-Loss- und Take-Profit-Level in Punkten (StopLossPoints, TakeProfitPoints) werden in Preisoffsets unter Verwendung des Instruments PriceStep umgerechnet.
Alle Aktionen verwenden BuyMarket / SellMarket, sodass die Strategie Positionen bei Bedarf automatisch umkehrt.
Parameter
Parameter
Beschreibung
Standardwert
CandleType
Kerzentyp (Zeitrahmen) für die Signalerkennung.
8-Stunden-Kerzen
EnableBuyEntries / EnableSellEntries
Long/Short-Ausbruchseinstiege erlauben.
true
EnableBuyExits / EnableSellExits
Indikatorbasierte Ausstiege für Longs/Shorts erlauben.
true
UseTimeExit
Trades nach einer festen Haltezeit schließen.
true
ExitMinutes
Haltezeitlimit in Minuten.
1920
UpCalcPeriodRange, UpCalcPeriodShift, UpDigit
Parameter des oberen Kanalbands.
5, 0, 2
DnCalcPeriodRange, DnCalcPeriodShift, DnDigit
Parameter des unteren Kanalbands.
5, 0, 2
SignalBar
Balkenversatz für die Auswertung von Ausbruchssignalen.
1
StopLossPoints, TakeProfitPoints
Stop-Loss / Take-Profit in Preispunkten (konvertiert mit PriceStep).
1000, 2000
Setzen Sie die Volume-Eigenschaft der Strategie, um die Positionsgröße zu steuern. Die Stop-Loss- und Take-Profit-Parameter sind optional; setzen Sie sie auf 0, um einen der Schutzniveaus zu deaktivieren.
Hinweise
Die Strategie erwartet ausreichend Geschichte, um den gleitenden Kanal zu bilden (ungefähr max(shift + 2 × range) Kerzen). Sie verwaltet automatisch die internen Buffer und ignoriert Signale, bis genügend Daten verfügbar sind.
Preisrundung wird mit Dezimalstellen durchgeführt, was das MQL-Indikator-Rundungsverhalten widerspiegelt.
Die Python-Implementierung ist absichtlich ausgelassen gemäß den Projektanweisungen; nur die C#-Version wird bereitgestellt.
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>
/// Sliding range breakout strategy using Highest/Lowest channel.
/// Enters on breakout above/below the channel, exits on opposite breakout.
/// </summary>
public class ExpRjSlidingRangeRjDigitSystemTmPlusStrategy : 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 ExpRjSlidingRangeRjDigitSystemTmPlusStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_period = Param(nameof(Period), 10)
.SetGreaterThanZero()
.SetDisplay("Period", "Channel lookback", "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 → buy
if (close > _prevUpper.Value && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Breakdown below previous lower → sell
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 exp_rj_sliding_range_rj_digit_system_tm_plus_strategy(Strategy):
def __init__(self):
super(exp_rj_sliding_range_rj_digit_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", "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(exp_rj_sliding_range_rj_digit_system_tm_plus_strategy, self).OnReseted()
self._prev_upper = None
self._prev_lower = None
def OnStarted2(self, time):
super(exp_rj_sliding_range_rj_digit_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
if close > self._prev_upper and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Breakdown below previous lower
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 exp_rj_sliding_range_rj_digit_system_tm_plus_strategy()