Auf GitHub ansehen

RRS Impulse Strategy

The RRS Impulse Strategy is a high level StockSharp port of the MetaTrader expert advisor "RRS Impulse". The original robot combined RSI, Stochastic and Bollinger Bands filters, rotated between several signal-strength modes and used protective stops and virtual trailing exits. This C# version keeps the same behaviour but relies purely on the StockSharp high level API: candle subscriptions feed the indicators, while BuyMarket, SellMarket and ClosePosition execute the orders.

Trading Logic

  1. Indicator Modes – Choose between four options:
    • Rsi: trade the oscillator when it leaves the overbought/oversold zone.
    • Stochastic: require both %K and %D to be above/below the configured levels.
    • BollingerBands: react to closes above the upper band or below the lower band.
    • RsiStochasticBollinger: fire only when all three filters confirm the same direction.
  2. Trade DirectionTrend follows the indicator (overbought leads to shorts, oversold to longs). CounterTrend fades the move (overbought triggers longs, oversold triggers shorts).
  3. Signal Strength – Controls how many timeframes must agree before entering a trade:
    • SingleTimeFrame: use only the base timeframe provided by CandleType.
    • MultiTimeFrame: require alignment across M1, M5, M15, M30, H1 and H4 candles.
    • Strong: focus on intraday momentum by checking M1, M5, M15 and M30.
    • VeryStrong: demand confirmation from the full M1 … H4 ladder. When the combined indicator mode is enabled every timeframe must satisfy all three filters.
  4. Risk Management – Each position tracks the average fill price and monitors three exit conditions:
    • fixed stop-loss distance in pips;
    • fixed take-profit distance in pips;
    • trailing stop activated once profit exceeds TrailingStartPips and maintained by TrailingGapPips. Whenever the direction flips the strategy calls ClosePosition() first to flatten and only opens the opposite trade after the next confirmation tick.

Parameters

Group Name Description
Data CandleType Base candle series processed for trading decisions.
Orders TradeVolume Volume used when sending market orders.
Risk StopLossPips, TakeProfitPips, TrailingStartPips, TrailingGapPips Virtual protective exits expressed in pips.
Signals IndicatorMode, TradeDirection, SignalStrength Behaviour switches copied from the MQL input block.
RSI RsiPeriod, RsiUpperLevel, RsiLowerLevel RSI configuration for overbought/oversold detection.
Stochastic StochasticKPeriod, StochasticDPeriod, StochasticSlowing, StochasticUpperLevel, StochasticLowerLevel Slow stochastic oscillator settings.
Bollinger BollingerPeriod, BollingerDeviation Bollinger Bands look-back and deviation multiplier.

All parameters support optimisation ranges identical to the MetaTrader version where it made sense (e.g. stop and take distances or oscillator thresholds).

Data Requirements

The strategy needs minute candles for the confirmation ladder. When SignalStrength requests additional timeframes the strategy automatically adds the required subscriptions (GetWorkingSecurities advertises them to the engine). Level1 quotes are not used; only close prices from finished candles drive entries and exits. Protective logic therefore reproduces the "virtual" stop/target behaviour of the original robot.

Notes on the Conversion

  • Random symbol rotation from the EA was intentionally removed. StockSharp strategies work with a single Security, so the port concentrates on matching the indicator logic and risk management while leaving instrument rotation to the user.
  • Order management is market-based: when the direction changes or a protective condition triggers, ClosePosition() is called, mirroring the MetaTrader loops that iterated through tickets.
  • The conversion keeps all comments in English and uses tabs for indentation to comply with the repository guidelines.
namespace StockSharp.Samples.Strategies;

using System;
using System.Collections.Generic;

using StockSharp.Algo;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

/// <summary>
/// RRS Impulse strategy.
/// Combines RSI, Stochastic and Bollinger Bands for counter-trend entries.
/// </summary>
public class RrsImpulseStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _rsiUpperLevel;
	private readonly StrategyParam<decimal> _rsiLowerLevel;
	private readonly StrategyParam<int> _stochasticKPeriod;
	private readonly StrategyParam<int> _stochasticDPeriod;
	private readonly StrategyParam<decimal> _stochasticUpperLevel;
	private readonly StrategyParam<decimal> _stochasticLowerLevel;
	private readonly StrategyParam<int> _bollingerPeriod;
	private readonly StrategyParam<decimal> _bollingerDeviation;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public decimal RsiUpperLevel { get => _rsiUpperLevel.Value; set => _rsiUpperLevel.Value = value; }
	public decimal RsiLowerLevel { get => _rsiLowerLevel.Value; set => _rsiLowerLevel.Value = value; }
	public int StochasticKPeriod { get => _stochasticKPeriod.Value; set => _stochasticKPeriod.Value = value; }
	public int StochasticDPeriod { get => _stochasticDPeriod.Value; set => _stochasticDPeriod.Value = value; }
	public decimal StochasticUpperLevel { get => _stochasticUpperLevel.Value; set => _stochasticUpperLevel.Value = value; }
	public decimal StochasticLowerLevel { get => _stochasticLowerLevel.Value; set => _stochasticLowerLevel.Value = value; }
	public int BollingerPeriod { get => _bollingerPeriod.Value; set => _bollingerPeriod.Value = value; }
	public decimal BollingerDeviation { get => _bollingerDeviation.Value; set => _bollingerDeviation.Value = value; }

	public RrsImpulseStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetDisplay("RSI Period", "RSI length", "RSI");

		_rsiUpperLevel = Param(nameof(RsiUpperLevel), 65m)
			.SetDisplay("RSI Upper", "Overbought", "RSI");

		_rsiLowerLevel = Param(nameof(RsiLowerLevel), 35m)
			.SetDisplay("RSI Lower", "Oversold", "RSI");

		_stochasticKPeriod = Param(nameof(StochasticKPeriod), 10)
			.SetDisplay("Stochastic %K", "%K period", "Stochastic");

		_stochasticDPeriod = Param(nameof(StochasticDPeriod), 3)
			.SetDisplay("Stochastic %D", "%D period", "Stochastic");

		_stochasticUpperLevel = Param(nameof(StochasticUpperLevel), 70m)
			.SetDisplay("Stochastic Upper", "Overbought", "Stochastic");

		_stochasticLowerLevel = Param(nameof(StochasticLowerLevel), 30m)
			.SetDisplay("Stochastic Lower", "Oversold", "Stochastic");

		_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
			.SetDisplay("Bollinger Period", "BB length", "Bollinger");

		_bollingerDeviation = Param(nameof(BollingerDeviation), 2m)
			.SetDisplay("Bollinger Deviation", "BB deviation", "Bollinger");
	}

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

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

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var stochastic = new StochasticOscillator();
		stochastic.K.Length = StochasticKPeriod;
		stochastic.D.Length = StochasticDPeriod;
		var bollinger = new BollingerBands { Length = BollingerPeriod, Width = BollingerDeviation };

		var subscription = SubscribeCandles(CandleType);

		subscription
			.BindEx(rsi, stochastic, bollinger, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, bollinger);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue rsiVal, IIndicatorValue stochVal, IIndicatorValue bbVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!rsiVal.IsFinal || !stochVal.IsFinal || !bbVal.IsFinal)
			return;

		if (!rsiVal.IsFormed || !stochVal.IsFormed || !bbVal.IsFormed)
			return;

		var rsi = rsiVal.GetValue<decimal>();
		var stoch = (StochasticOscillatorValue)stochVal;
		var stochK = stoch.K ?? 50m;
		var bb = (BollingerBandsValue)bbVal;
		var bbUpper = bb.UpBand ?? candle.ClosePrice;
		var bbLower = bb.LowBand ?? candle.ClosePrice;

		var close = candle.ClosePrice;

		// Count how many indicators signal overbought/oversold
		var obSignals = 0;
		var osSignals = 0;

		if (rsi >= RsiUpperLevel) obSignals++;
		if (rsi <= RsiLowerLevel) osSignals++;

		if (stochK >= StochasticUpperLevel) obSignals++;
		if (stochK <= StochasticLowerLevel) osSignals++;

		if (close >= bbUpper) obSignals++;
		if (close <= bbLower) osSignals++;

		// Counter-trend: need at least 2 of 3 indicators confirming
		if (osSignals >= 2 && Position <= 0)
		{
			BuyMarket();
		}
		else if (obSignals >= 2 && Position >= 0)
		{
			SellMarket();
		}
		// Exit long when RSI and stoch neutralize
		else if (Position > 0 && rsi > 50m && stochK > 50m)
		{
			SellMarket();
		}
		// Exit short when RSI and stoch neutralize
		else if (Position < 0 && rsi < 50m && stochK < 50m)
		{
			BuyMarket();
		}
	}
}