Multi-Timeframe RSI Grid Strategy with Arrows
This strategy trades when RSI on the current timeframe and two higher timeframes reach overbought or oversold levels. The first position is opened when all RSIs align, then additional positions are added using an ATR based grid with an increasing lot multiplier. The strategy targets a daily profit percentage, resets each day, and closes on reverse signals or drawdown.
Parameters
- Candle Type
- RSI Length
- Oversold Level
- Overbought Level
- Higher Timeframe 1
- Higher Timeframe 2
- Grid Multiplication Factor
- Lot Multiplication Factor
- Maximum Grid Levels
- Daily Profit Target %
- ATR Length
using System;
using System.Linq;
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 MultiTimeframeRsiGridWithArrowsStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<DataType> _candleType;
public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MultiTimeframeRsiGridWithArrowsStrategy()
{
_fastLength = Param(nameof(FastLength), 10).SetGreaterThanZero();
_slowLength = Param(nameof(SlowLength), 30).SetGreaterThanZero();
_rsiLength = Param(nameof(RsiLength), 14).SetGreaterThanZero();
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame());
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = FastLength };
var slow = new ExponentialMovingAverage { Length = SlowLength };
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var prevFast = 0m; var prevSlow = 0m; var init = false;
var sub = SubscribeCandles(CandleType);
sub.Bind(fast, slow, rsi, (c, f, s, r) =>
{
if (c.State != CandleStates.Finished || !fast.IsFormed || !slow.IsFormed || !rsi.IsFormed) return;
if (!init) { prevFast = f; prevSlow = s; init = true; return; }
if (prevFast <= prevSlow && f > s && r > 45 && Position <= 0) BuyMarket();
else if (prevFast >= prevSlow && f < s && r < 55 && Position > 0) SellMarket();
prevFast = f; prevSlow = s;
}).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, sub); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
}
}
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, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class multi_timeframe_rsi_grid_with_arrows_strategy(Strategy):
def __init__(self):
super(multi_timeframe_rsi_grid_with_arrows_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 10) \
.SetGreaterThanZero()
self._slow_length = self.Param("SlowLength", 30) \
.SetGreaterThanZero()
self._rsi_length = self.Param("RsiLength", 14) \
.SetGreaterThanZero()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1)))
self._prev_fast = 0.0
self._prev_slow = 0.0
self._initialized = False
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(multi_timeframe_rsi_grid_with_arrows_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._initialized = False
def OnStarted2(self, time):
super(multi_timeframe_rsi_grid_with_arrows_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._initialized = False
self._fast = ExponentialMovingAverage()
self._fast.Length = self._fast_length.Value
self._slow = ExponentialMovingAverage()
self._slow.Length = self._slow_length.Value
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self._rsi_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast, self._slow, self._rsi, self.OnProcess).Start()
def OnProcess(self, candle, f, s, r):
if candle.State != CandleStates.Finished:
return
if not self._fast.IsFormed or not self._slow.IsFormed or not self._rsi.IsFormed:
return
fv = float(f)
sv = float(s)
rv = float(r)
if not self._initialized:
self._prev_fast = fv
self._prev_slow = sv
self._initialized = True
return
if self._prev_fast <= self._prev_slow and fv > sv and rv > 45.0 and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fv < sv and rv < 55.0 and self.Position > 0:
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def CreateClone(self):
return multi_timeframe_rsi_grid_with_arrows_strategy()