Strategy that trades based on the Relative Strength Index (RSI) crossing a middle value.
The idea is to watch for the RSI to cross above or below a configurable level (default 50). When the indicator moves from below to above this level a long position is opened. When it crosses back below the level a short position is opened. Existing positions are exited on the opposite cross. Optional stop-loss, take-profit and trailing stop protect the trade.
Details
Entry Criteria: Buy when RSI crosses above the level. Sell when RSI crosses below.
Long/Short: Both directions.
Exit Criteria: Opposite cross or trailing stop.
Stops: Optional fixed stop-loss, take-profit and trailing stop.
Default Values:
RsiPeriod = 14
RsiLevel = 50
StopLoss = 100
TakeProfit = 200
TrailingStop = 0
CandleType = TimeSpan.FromMinutes(5)
Filters:
Category: Oscillator
Direction: Both
Indicators: RSI
Stops: Yes
Complexity: Basic
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;
/// <summary>
/// RSI level crossing strategy.
/// </summary>
public class RsiValueStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _rsiLevel;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevRsi;
private bool _hasPrev;
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal RsiLevel { get => _rsiLevel.Value; set => _rsiLevel.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public RsiValueStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_rsiLevel = Param(nameof(RsiLevel), 50m)
.SetDisplay("RSI Level", "RSI crossing level", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle type", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
SubscribeCandles(CandleType)
.Bind(rsi, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiVal)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev)
{
_prevRsi = rsiVal;
_hasPrev = true;
return;
}
var crossUp = _prevRsi <= RsiLevel && rsiVal > RsiLevel;
var crossDown = _prevRsi >= RsiLevel && rsiVal < RsiLevel;
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevRsi = rsiVal;
}
}