RsiBoosterStrategy ist eine StockSharp-Portierung des MetaTrader Expert Advisors RSI booster. Die Strategie vergleicht den schnellen RSI-Wert der aktuellen Kerze mit einem verzögerten RSI, der die vorherige Kerze verwendet. Überschreitet die Differenz ein vom Benutzer festgelegtes Verhältnis, eröffnet die Strategie eine Marktposition und verwaltet den Trade anschließend mit festen Stops, Take-Profit-Zielen, einem optionalen Trailing Stop und einer Kette von Gegenorders zur Verlustaufholung.
Die Strategie basiert auf der High-Level-API von StockSharp. Sie abonniert eine einzelne Kerzenserie, nutzt die integrierten RelativeStrengthIndex-Indikatoren und verwendet das Strategie-Parametersystem, damit alle Eingaben in Designer optimiert werden können.
Handelslogik
Auf jeder abgeschlossenen Kerze werden zwei RSI-Indikatoren berechnet.
Der schnelle RSI verwendet FirstRsiPeriod und FirstRsiPrice und liest die neueste Kerze.
Der verzögerte RSI verwendet SecondRsiPeriod und SecondRsiPrice, die Strategie behält jedoch den vorherigen Wert bei, sodass er als Verzögerung um eine Bar wirkt.
Wenn fast RSI - delayed RSI größer als Ratio ist, kauft die Strategie, sofern keine Long-Position offen ist. Liegt die Differenz unter -Ratio, verkauft sie, sofern keine Short-Position offen ist.
OnlyOnePositionPerBar stellt sicher, dass pro Richtung höchstens ein Einstieg für denselben Kerzenzeitstempel erfolgt.
Nach jeder Kerze bewertet die Strategie Stop-Loss-, Take-Profit- und Trailing-Regeln. Wird eine der Bedingungen ausgelöst, wird die Position sofort geschlossen.
Wird eine Position mit negativem realisiertem PnL geschlossen, kann die optionale Aufhollogik eine Gegenposition (entgegengesetzte Richtung) mit demselben Volumen eröffnen. Die Anzahl verketteter Aufholtrades ist durch ReturnOrdersMax begrenzt.
Risikomanagement
Stop-Loss - über StopLossPips in Instrumentenpunkten ausgedrückt. Die Position wird geschlossen, wenn der Preis das Stop-Niveau kreuzt.
Take-Profit - über TakeProfitPips in Instrumentenpunkten ausgedrückt.
Trailing Stop - wenn über TrailingStopPips aktiviert, beginnt der Stop zu trailen, sobald der Gewinn die konfigurierte Distanz überschreitet. TrailingStepPips definiert die minimale Verbesserung, bevor das Trailing-Niveau verschoben wird.
Return-Order - wird aktiviert, wenn ReturnOrderEnabledtrue ist. Nach einem Verlusttrade eröffnet die Strategie sofort eine Marktorder in die entgegengesetzte Richtung und zählt dabei, wie viele Aufholorders ausgegeben wurden.
Parameter
Parameter
Beschreibung
Volume
Handelsvolumen für jede Marktorder (Lots oder Kontrakte).
Ratio
Minimale RSI-Differenz, die zum Eröffnen einer Position erforderlich ist.
StopLossPips
Stop-Loss-Distanz in Instrumentenpunkten.
TakeProfitPips
Take-Profit-Distanz in Instrumentenpunkten.
TrailingStopPips
Trailing-Stop-Distanz in Instrumentenpunkten.
TrailingStepPips
Minimale Verbesserung vor dem Verschieben des Trailing Stops.
OnlyOnePositionPerBar
Verhindert mehrere Einstiege während derselben Kerze.
Preisquelle für den schnellen RSI (entspricht den angewandten Preis-Modi von MetaTrader).
SecondRsiPeriod
Periode des verzögerten RSI.
SecondRsiPrice
Preisquelle für den verzögerten RSI (entspricht den angewandten Preis-Modi von MetaTrader).
CandleType
Für die Analyse verwendete Kerzenserie.
Hinweise
Die Umrechnung des Preisschritts berücksichtigt den PriceStep des Instruments, sofern verfügbar. Stellt das Instrument keinen Preisschritt bereit, wird als Fallback 0.0001 verwendet.
Der Zähler der Aufholkette wird zurückgesetzt, wenn ein profitabler Trade auftritt oder die konfigurierte Höchstzahl von Aufholorders erreicht ist.
Die Strategie zeichnet beide RSI-Indikatoren zusammen mit den ausgeführten Trades im Chartbereich, damit sie schnell visuell geprüft werden können.
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 RsiBoosterStrategy : 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 RsiBoosterStrategy()
{
_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 rsi_booster_strategy(Strategy):
def __init__(self):
super(rsi_booster_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(rsi_booster_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(rsi_booster_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 rsi_booster_strategy()