Die CDC PL RSI-Strategie repliziert den MQL Expert Advisor Expert_ADC_PL_RSI innerhalb des StockSharp-Ökosystems. Das System durchsucht fertige Kerzen nach japanischen Candlestick-Umkehrmustern und bestätigt Eingaben mit dem Relative Strength Index (RSI). Long-Trades basieren auf dem Piercing Line-Muster bei überverkauften RSI-Bedingungen, während Short-Trades das Dark Cloud Cover-Muster in Kombination mit überkauften RSI-Werten erfordern. Der Ansatz hält das ursprüngliche Money-Management-Konzept einfach, indem er das Strategievolumen verwendet und StockSharp die Positionsgrößenbestimmung überlässt.
Muster- und Indikatorlogik
Kerzenmuster: Die Strategie rekonstruiert die MetaTrader-Logik durch die Analyse zweier zuletzt abgeschlossener Kerzen. Die Regeln für Piercing Line und Dark Cloud Cover spiegeln den ursprünglichen Code wider, einschließlich Prüfungen auf Lücken, lange Körper im Verhältnis zu einem adaptiven Körperdurchschnitt und die zugrunde liegende Trendrichtung.
RSI-Filter: Ein 20-Perioden-RSI (optimierbar) bestätigt die Dynamik. Überverkaufte Werte (RSI < 40) schalten Long-Einträge frei, und überkaufte Werte (RSI > 60) schalten Short-Einträge frei. Der RSI-Verlauf wird auch verwendet, um Ausgänge zu erkennen, wenn der Oszillator die 30- oder 70-Ebenen in die entgegengesetzte Richtung überschreitet.
Körperdurchschnitt und Trendfilter: Ein einfacher gleitender Durchschnitt der Kerzenkörpergrößen und weitere SMA der Schlusskurse replizieren die MetaTrader-Hilfsfunktionen (AvgBody und CloseAvg). Diese Durchschnittswerte verhindern Signale während des Rauschens und sorgen dafür, dass die Muster nach einer klaren Bewegung erscheinen.
Handelsregeln
Lange Einrichtung
Erkennen Sie ein Piercing-Line-Muster bei den letzten beiden abgeschlossenen Kerzen.
Erfordern, dass RSI von der vorherigen fertigen Kerze unter 40 liegt.
Wenn die Bedingungen bestehen, kaufen Sie zum Marktpreis. Wenn eine Gegenposition vorhanden ist, kehrt sich die Strategie um, indem die absolute Positionsgröße plus das konfigurierte Volumen gekauft wird.
Kurze Einrichtung
Erkennen Sie bei den beiden letzten Kerzen ein Muster einer dunklen Wolkendecke.
Erfordern, dass RSI von der vorherigen fertigen Kerze über 60 liegt.
Wenn die Bedingungen bestehen, verkaufen Sie zum Marktpreis. Eine entgegengesetzte Position wird mit derselben Volumenlogik geschlossen und umgekehrt.
Ausstiegsbedingungen
Schließen Sie Long-Positionen, wenn RSI 70 nach unten oder 30 nach oben kreuzt, was signalisiert, dass die Dynamik nachgelassen hat oder umgekehrt ist.
Schließen Sie Short-Positionen, wenn RSI 30 nach oben oder 70 nach unten überschreitet, was der MetaTrader-Implementierung entspricht.
Parameter
Name
Standard
Beschreibung
RsiPeriod
20
RSI Lookback-Länge. Optimierbar zwischen 10 und 40 in 5er-Schritten.
BodyAveragePeriod
14
Zeitraum sowohl für die durchschnittliche Kerzenkörpergröße als auch für den Schlusspreistrendfilter. Optimierbar zwischen 10 und 30 in 5er-Schritten.
CandleType
1-stündiger Zeitrahmen
Für Berechnungen verwendete Kerzenreihe. Jeder von StockSharp unterstützte Kerzentyp kann ausgewählt werden.
Volume (Basisklasse)
—
Handelsvolumen, das vor dem Start für die Strategieinstanz festgelegt wird.
Nutzung
Fügen Sie die Strategie einem Portfolio und einer Sicherheit in StockSharp Designer, Shell oder Runner hinzu.
Konfigurieren Sie Kerzentyp und -volumen entsprechend dem gehandelten Markt.
Passen Sie optional die Perioden RSI und Körperdurchschnitt an, um sie an die Volatilität des Instruments anzupassen, oder führen Sie Optimierungen mit dem StockSharp-Optimierer durch.
Starten Sie die Strategie und überwachen Sie die Diagrammüberlagerungen (Kerzen, RSI und Schlussdurchschnittslinie), um Musterbestätigungen und ausgeführte Trades zu überprüfen.
Notizen
Die Strategie ruft StartProtection() auf, sodass bei Bedarf integrierte Schutzroutinen konfiguriert werden können (Stop-Loss, Take-Profit, Trailing usw.).
Es werden nur abgeschlossene Kerzen verarbeitet, wobei die Logik mit dem MQL Expert Advisor konsistent bleibt.
Es werden keine zusätzlichen Sammlungen gespeichert; Indikatorinstanzen enthalten die für die Musterprüfungen erforderlichen Schiebefensterberechnungen.
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// CDC PL RSI strategy: Dark Cloud Cover and Piercing Line candlestick patterns
/// confirmed by RSI levels.
/// </summary>
public class CdcPlRsiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _oversoldLevel;
private readonly StrategyParam<decimal> _overboughtLevel;
private readonly StrategyParam<int> _signalCooldownCandles;
private readonly List<ICandleMessage> _candles = new();
private decimal _prevRsi;
private bool _hasPrevRsi;
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal OversoldLevel { get => _oversoldLevel.Value; set => _oversoldLevel.Value = value; }
public decimal OverboughtLevel { get => _overboughtLevel.Value; set => _overboughtLevel.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public CdcPlRsiStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_oversoldLevel = Param(nameof(OversoldLevel), 40m)
.SetDisplay("Oversold Level", "RSI below this for long entry", "Signals");
_overboughtLevel = Param(nameof(OverboughtLevel), 60m)
.SetDisplay("Overbought Level", "RSI above this for short entry", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_candles.Clear();
_prevRsi = 0m;
_hasPrevRsi = false;
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_candles.Clear();
_hasPrevRsi = false;
_candlesSinceTrade = SignalCooldownCandles;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ProcessCandle).Start();
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(1, UnitTypes.Percent)
);
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
_candles.Add(candle);
if (_candles.Count > 5)
_candles.RemoveAt(0);
if (_candles.Count >= 2 && _hasPrevRsi)
{
var curr = _candles[^1];
var prev = _candles[^2];
// Piercing Line
var isPiercing = prev.OpenPrice > prev.ClosePrice
&& curr.ClosePrice > curr.OpenPrice
&& curr.OpenPrice < prev.LowPrice
&& curr.ClosePrice > (prev.OpenPrice + prev.ClosePrice) / 2m;
// Dark Cloud Cover
var isDarkCloud = prev.ClosePrice > prev.OpenPrice
&& curr.OpenPrice > curr.ClosePrice
&& curr.OpenPrice > prev.HighPrice
&& curr.ClosePrice < (prev.OpenPrice + prev.ClosePrice) / 2m;
if (isPiercing && rsiValue < OversoldLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (isDarkCloud && rsiValue > OverboughtLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
_prevRsi = rsiValue;
_hasPrevRsi = true;
}
}
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 RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class cdc_pl_rsi_strategy(Strategy):
def __init__(self):
super(cdc_pl_rsi_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI period", "Indicators")
self._oversold_level = self.Param("OversoldLevel", 40.0) \
.SetDisplay("Oversold Level", "RSI below this for long entry", "Signals")
self._overbought_level = self.Param("OverboughtLevel", 60.0) \
.SetDisplay("Overbought Level", "RSI above this for short entry", "Signals")
self._signal_cooldown = self.Param("SignalCooldownCandles", 6) \
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading")
self._rsi = None
self._candles = []
self._has_prev_rsi = False
self._candles_since_trade = 0
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def oversold_level(self):
return self._oversold_level.Value
@property
def overbought_level(self):
return self._overbought_level.Value
@property
def signal_cooldown(self):
return self._signal_cooldown.Value
def OnReseted(self):
super(cdc_pl_rsi_strategy, self).OnReseted()
self._rsi = None
self._candles = []
self._has_prev_rsi = False
self._candles_since_trade = self.signal_cooldown
def OnStarted2(self, time):
super(cdc_pl_rsi_strategy, self).OnStarted2(time)
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.rsi_period
self._candles = []
self._has_prev_rsi = False
self._candles_since_trade = self.signal_cooldown
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._rsi, self._process_candle)
subscription.Start()
self.StartProtection(takeProfit=Unit(2, UnitTypes.Percent), stopLoss=Unit(1, UnitTypes.Percent), useMarketOrders=True)
def _process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
if not self._rsi.IsFormed:
return
rsi_val = float(rsi_value)
if self._candles_since_trade < self.signal_cooldown:
self._candles_since_trade += 1
self._candles.append(candle)
if len(self._candles) > 5:
self._candles.pop(0)
if len(self._candles) >= 2 and self._has_prev_rsi:
curr = self._candles[-1]
prev = self._candles[-2]
is_piercing = (float(prev.OpenPrice) > float(prev.ClosePrice)
and float(curr.ClosePrice) > float(curr.OpenPrice)
and float(curr.OpenPrice) < float(prev.LowPrice)
and float(curr.ClosePrice) > (float(prev.OpenPrice) + float(prev.ClosePrice)) / 2.0)
is_dark_cloud = (float(prev.ClosePrice) > float(prev.OpenPrice)
and float(curr.OpenPrice) > float(curr.ClosePrice)
and float(curr.OpenPrice) > float(prev.HighPrice)
and float(curr.ClosePrice) < (float(prev.OpenPrice) + float(prev.ClosePrice)) / 2.0)
if is_piercing and rsi_val < self.oversold_level and self.Position == 0 and self._candles_since_trade >= self.signal_cooldown:
self.BuyMarket()
self._candles_since_trade = 0
elif is_dark_cloud and rsi_val > self.overbought_level and self.Position == 0 and self._candles_since_trade >= self.signal_cooldown:
self.SellMarket()
self._candles_since_trade = 0
self._has_prev_rsi = True
def CreateClone(self):
return cdc_pl_rsi_strategy()