Ver en GitHub

Hybrid RSI Breakout Dashboard

Strategy combines RSI mean reversion with breakout entries filtered by ADX and a 200 EMA.

The system buys when the market is ranging and RSI drops below RsiBuy in bullish EMA trend. It sells short when RSI rises above RsiSell in bearish trend. In trending regime, it enters breakouts above/below recent closes and trails the position using ATR.

Includes a start date filter and simple dashboard variables for last trade type and direction.

Details

  • Entry Criteria: RSI signals in ranging regime with EMA bias, or breakouts above/below previous BreakoutLength closes when ADX > AdxThreshold.
  • Long/Short: Both.
  • Exit Criteria: RSI trades exit on RsiExit. Breakout trades use ATR trailing stop.
  • Stops: ATR trailing stop for breakout trades.
  • Default Values:
    • AdxLength = 14
    • AdxThreshold = 20m
    • EmaLength = 200
    • RsiLength = 14
    • RsiBuy = 40m
    • RsiSell = 60m
    • RsiExit = 50m
    • BreakoutLength = 20
    • AtrLength = 14
    • AtrMultiplier = 2m
    • StartDate = 2017-01-01
    • CandleType = TimeSpan.FromMinutes(5)
  • Filters:
    • Category: Trend, Mean Reversion
    • Direction: Both
    • Indicators: ADX, EMA, RSI, ATR, Highest/Lowest
    • Stops: Trailing
    • Complexity: Medium
    • Timeframe: Intraday (5m)
    • Seasonality: No
    • Neural Networks: No
    • Divergence: No
    • Risk Level: Medium
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 HybridRsiBreakoutDashboardStrategy : Strategy
{
	private readonly StrategyParam<int> _fastEmaPeriod;
	private readonly StrategyParam<int> _slowEmaPeriod;
	private readonly StrategyParam<DataType> _candleType;
	private decimal _prevFastEma;
	private decimal _prevSlowEma;

	public int FastEmaPeriod { get => _fastEmaPeriod.Value; set => _fastEmaPeriod.Value = value; }
	public int SlowEmaPeriod { get => _slowEmaPeriod.Value; set => _slowEmaPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public HybridRsiBreakoutDashboardStrategy()
	{
		_fastEmaPeriod = Param(nameof(FastEmaPeriod), 120)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
		_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 450)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles to use", "General");
	}

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFastEma = 0m;
		_prevSlowEma = 0m;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		var fastEma = new ExponentialMovingAverage { Length = FastEmaPeriod };
		var slowEma = new ExponentialMovingAverage { Length = SlowEmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fastEma, slowEma, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, fastEma);
			DrawIndicator(area, slowEma);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastEmaValue, decimal slowEmaValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (_prevFastEma == 0m || _prevSlowEma == 0m)
		{
			_prevFastEma = fastEmaValue;
			_prevSlowEma = slowEmaValue;
			return;
		}
		if (_prevFastEma <= _prevSlowEma && fastEmaValue > slowEmaValue && Position <= 0)
			BuyMarket();
		else if (_prevFastEma >= _prevSlowEma && fastEmaValue < slowEmaValue && Position >= 0)
			SellMarket();
		_prevFastEma = fastEmaValue;
		_prevSlowEma = slowEmaValue;
	}
}