FiveMinuteRsiCciStrategy is a StockSharp port of the MetaTrader 4 expert advisor 5Mins Rsi Cci EA.mq4. The original script trades five-minute candles by combining an RSI threshold cross with a smoothed/EMA moving-average filter and the polarity of two CCI indicators. The C# version keeps the same decision logic while using StockSharp's high-level API for data subscriptions, indicator binding, and risk management.
Trading logic
Subscribe to the configured candle type (five-minute timeframe by default) and update five indicators in real time: RSI, a smoothed MA of the open price, an EMA of the open price, plus fast and slow CCIs calculated from typical prices.
Each finished candle is evaluated only when no position is open and the current bid/ask spread is below MaxSpreadPoints (converted to price units).
A long signal requires:
the smoothed MA above the EMA,
the RSI crossing upward through BullishRsiLevel between the previous and current candle,
both CCI values above zero.
A short signal requires the inverse conditions (smoothed MA below EMA, RSI crossing downward through BearishRsiLevel, both CCIs below zero).
Order volume reproduces the EA's dynamic position sizing: LotCoefficient × sqrt(Equity / EquityDivisor) rounded to the instrument's volume step and constrained by VolumeMin/VolumeMax.
Protective logic is handled by StartProtection, which attaches stop-loss, take-profit, and trailing-stop distances converted from MetaTrader points to absolute price offsets.
Parameters
Parameter
Default
Description
CandleType
TimeSpan.FromMinutes(5).TimeFrame()
Timeframe used for indicator updates and signal evaluation.
RsiPeriod
14
Number of candles used in the RSI calculation.
FastSmmaPeriod
2
Period of the fast smoothed moving average applied to open prices.
SlowEmaPeriod
6
Period of the slow EMA applied to open prices.
FastCciPeriod
34
Period of the fast CCI computed from the typical price (H+L+C)/3.
SlowCciPeriod
175
Period of the slow CCI computed from the typical price.
BullishRsiLevel
55
RSI threshold that must be crossed upward to arm a long entry.
BearishRsiLevel
45
RSI threshold that must be crossed downward to arm a short entry.
StopLossPoints
60
Stop-loss distance in MetaTrader points (converted to absolute price). Set to 0 to disable.
TakeProfitPoints
0
Take-profit distance in MetaTrader points. Zero keeps the original EA behaviour (no TP).
TrailingStopPoints
20
Trailing-stop distance in MetaTrader points. Zero disables trailing.
LotCoefficient
0.01
Base coefficient used in the dynamic position sizing formula.
EquityDivisor
10
Divisor inside the square root for equity-based sizing (sqrt(Equity / EquityDivisor)).
MaxSpreadPoints
18
Maximum allowed spread (in MetaTrader points). Orders are skipped until the spread narrows.
Notes
The spread filter relies on level-1 data; if best bid/ask quotes are unavailable the strategy waits before opening new positions.
Point-to-price conversion automatically scales by PriceStep and the instrument precision (5/3 decimal instruments multiply the step by 10) to mirror MetaTrader's Point value.
Stops and trailing are managed through StockSharp's built-in protection engine with market exits, matching the EA's use of market orders for trailing-stop updates.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Five Minute RSI CCI strategy: RSI momentum with CCI trend confirmation.
/// Buys when RSI above level and CCI positive, sells when RSI below level and CCI negative.
/// </summary>
public class FiveMinuteRsiCciStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<decimal> _bullishLevel;
private readonly StrategyParam<decimal> _bearishLevel;
private bool _wasBullish;
private bool _hasPrevSignal;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public decimal BullishLevel { get => _bullishLevel.Value; set => _bullishLevel.Value = value; }
public decimal BearishLevel { get => _bearishLevel.Value; set => _bearishLevel.Value = value; }
public FiveMinuteRsiCciStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "CCI period", "Indicators");
_bullishLevel = Param(nameof(BullishLevel), 55m)
.SetDisplay("Bullish RSI Level", "RSI above this for buy", "Signals");
_bearishLevel = Param(nameof(BearishLevel), 45m)
.SetDisplay("Bearish RSI Level", "RSI below this for sell", "Signals");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_wasBullish = false;
_hasPrevSignal = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrevSignal = false;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, cci, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue, decimal cciValue)
{
if (candle.State != CandleStates.Finished) return;
var isBullish = rsiValue > BullishLevel && cciValue > 0;
if (_hasPrevSignal && isBullish != _wasBullish)
{
if (isBullish && Position <= 0)
BuyMarket();
else if (!isBullish && rsiValue < BearishLevel && cciValue < 0 && Position >= 0)
SellMarket();
}
_wasBullish = isBullish;
_hasPrevSignal = true;
}
}
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 RelativeStrengthIndex, CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class five_minute_rsi_cci_strategy(Strategy):
def __init__(self):
super(five_minute_rsi_cci_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30)))
self._rsi_period = self.Param("RsiPeriod", 14)
self._cci_period = self.Param("CciPeriod", 14)
self._bullish_level = self.Param("BullishLevel", 55.0)
self._bearish_level = self.Param("BearishLevel", 45.0)
self._was_bullish = False
self._has_prev_signal = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
@property
def CciPeriod(self):
return self._cci_period.Value
@CciPeriod.setter
def CciPeriod(self, value):
self._cci_period.Value = value
@property
def BullishLevel(self):
return self._bullish_level.Value
@BullishLevel.setter
def BullishLevel(self, value):
self._bullish_level.Value = value
@property
def BearishLevel(self):
return self._bearish_level.Value
@BearishLevel.setter
def BearishLevel(self, value):
self._bearish_level.Value = value
def OnReseted(self):
super(five_minute_rsi_cci_strategy, self).OnReseted()
self._was_bullish = False
self._has_prev_signal = False
def OnStarted2(self, time):
super(five_minute_rsi_cci_strategy, self).OnStarted2(time)
self._has_prev_signal = False
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
cci = CommodityChannelIndex()
cci.Length = self.CciPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, cci, self._process_candle).Start()
def _process_candle(self, candle, rsi_value, cci_value):
if candle.State != CandleStates.Finished:
return
is_bullish = float(rsi_value) > self.BullishLevel and float(cci_value) > 0
if self._has_prev_signal and is_bullish != self._was_bullish:
if is_bullish and self.Position <= 0:
self.BuyMarket()
elif not is_bullish and float(rsi_value) < self.BearishLevel and float(cci_value) < 0 and self.Position >= 0:
self.SellMarket()
self._was_bullish = is_bullish
self._has_prev_signal = True
def CreateClone(self):
return five_minute_rsi_cci_strategy()