Auf GitHub ansehen

RSI-Verlangsamungs-Strategie

Die RSI-Verlangsamungs-Strategie reagiert auf extreme Messwerte des Relative Strength Index, die Anzeichen nachlassenden Momentums zeigen. Wenn sich RSI den überkauften oder überverkauften Zonen nähert und seine Veränderung zwischen den Bars unter einen Punkt fällt, geht die Strategie davon aus, dass der Markt für eine Umkehr bereit ist.

Eine Long-Position wird eröffnet, wenn RSI das obere Niveau erreicht oder überschreitet und das Wachstum des Indikators nachlässt. Eine Short-Position wird eröffnet, wenn RSI auf das untere Niveau fällt, mit einer ähnlichen Verlangsamung. Jede bestehende entgegengesetzte Position wird geschlossen, bevor ein neuer Trade eingegangen wird.

Die Standardkonfiguration verwendet 6-Stunden-Kerzen und einen 2-Perioden-RSI mit Schwellenwerten von 90 und 10. Diese Werte imitieren die ursprüngliche MetaTrader-Implementierung.

Details

  • Einstiegskriterien:
    • Long: RSI >= LevelMax und |RSI - prev RSI| < 1 (wenn Verlangsamung aktiviert ist)
    • Short: RSI <= LevelMin und |RSI - prev RSI| < 1 (wenn Verlangsamung aktiviert ist)
  • Long/Short: Beide Richtungen.
  • Ausstiegskriterien:
    • Long: Gegenteiliges Signal oder Short-Einstieg.
    • Short: Gegenteiliges Signal oder Long-Einstieg.
  • Stops: Keine automatischen Stops.
  • Standardwerte:
    • RsiPeriod = 2
    • LevelMax = 90
    • LevelMin = 10
    • SeekSlowdown = true
    • CandleType = TimeSpan.FromHours(6)
  • Filter:
    • Kategorie: Umkehr
    • Richtung: Beide
    • Indikatoren: RSI
    • Stops: Nein
    • Komplexität: Grundlegend
    • Zeitrahmen: Intraday bis Swing
    • Saisonalität: Nein
    • Neuronale Netze: Nein
    • Divergenz: Ja (Verlangsamung)
    • Risikolevel: Mittel
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;

/// <summary>
/// RSI slowdown strategy.
/// Opens long when RSI reaches the upper level and slows down.
/// Opens short when RSI reaches the lower level and slows down.
/// </summary>
public class RsiSlowdownStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _levelMax;
	private readonly StrategyParam<decimal> _levelMin;
	private readonly StrategyParam<bool> _seekSlowdown;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _previousRsi;

	/// <summary>
	/// RSI period length.
	/// </summary>
	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	/// <summary>
	/// Upper RSI level.
	/// </summary>
	public decimal LevelMax
	{
		get => _levelMax.Value;
		set => _levelMax.Value = value;
	}

	/// <summary>
	/// Lower RSI level.
	/// </summary>
	public decimal LevelMin
	{
		get => _levelMin.Value;
		set => _levelMin.Value = value;
	}

	/// <summary>
	/// Enable slowdown condition.
	/// </summary>
	public bool SeekSlowdown
	{
		get => _seekSlowdown.Value;
		set => _seekSlowdown.Value = value;
	}

	/// <summary>
	/// The type of candles to use for calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Constructor.
	/// </summary>
	public RsiSlowdownStrategy()
	{
		_rsiPeriod = Param(nameof(RsiPeriod), 2)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI calculation period", "RSI")
			
			.SetOptimize(2, 14, 1);

		_levelMax = Param(nameof(LevelMax), 90m)
			.SetDisplay("Upper Level", "Overbought RSI level", "RSI")
			
			.SetOptimize(50m, 100m, 5m);

		_levelMin = Param(nameof(LevelMin), 10m)
			.SetDisplay("Lower Level", "Oversold RSI level", "RSI")
			
			.SetOptimize(0m, 50m, 5m);

		_seekSlowdown = Param(nameof(SeekSlowdown), true)
			.SetDisplay("Seek Slowdown", "Check RSI change below 1", "RSI");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(6).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles for the strategy", "General");

		_previousRsi = decimal.MinValue;
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_previousRsi = decimal.MinValue;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_previousRsi = decimal.MinValue;

		var rsi = new RelativeStrengthIndex
		{
			Length = RsiPeriod
		};

		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
	{
		if (candle.State != CandleStates.Finished)
		return;

		if (_previousRsi == decimal.MinValue)
		{
			_previousRsi = rsiValue;
			return;
		}

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_previousRsi = rsiValue;
			return;
		}

		var isSlowdown = !SeekSlowdown || Math.Abs(_previousRsi - rsiValue) < 1m;

		if (isSlowdown)
		{
		if (rsiValue >= LevelMax && Position <= 0)
		{
		BuyMarket();
		}
		else if (rsiValue <= LevelMin && Position >= 0)
		{
		SellMarket();
		}
		}

		_previousRsi = rsiValue;
	}
}