RenkoChartStrategy is a direct conversion of the original RenkoChart.mq5 expert. Instead of placing orders, the
strategy focuses on recreating the custom Renko symbol workflow inside StockSharp. It subscribes to tick data, produces
a Renko candle stream with a configurable brick size, and exposes it through the platform so it can be visualized or
forwarded to other components. Every completed brick is logged with the latest tick that triggered it, allowing the
operator to validate the generated series against the MQL implementation.
Mapping from the MQL Expert
StartDateTime → StartTime: the initial timestamp used when seeding the Renko history.
BaseSymbol → Strategy.Security: StockSharp already assigns the base instrument, so the parameter was replaced
by relying on the selected security. The strategy still prefixes the generated stream name with RenkoPrefix to
mimic the "Renko-<symbol>" naming convention.
Mode (Bid/Last) → UseBidTicks: toggles whether bid updates or trade ticks drive the live monitoring feed.
Range → BrickSizeSteps: number of price steps that form a Renko brick. The strategy multiplies the value by the
security's PriceStep to obtain the absolute box size.
Parameters
Name
Type
Default
Description
StartTime
DateTimeOffset
2018‑08‑01 09:00:00 UTC
Bricks with an opening time before this moment are ignored, matching the original warmup behaviour.
BrickSizeSteps
int
5
Renko brick size expressed in price steps. Converted to absolute price when the Renko series is created.
UseBidTicks
bool
false
When false the strategy listens to trade ticks, when true it listens to bid updates to emulate the MQL Bid mode.
RenkoPrefix
string
"Renko-"
Prefix added to the log messages so the stream name matches the custom symbol naming convention.
Note: the calculated BrickSize property exposes the absolute box size and can be useful when wiring the strategy
with other components that expect a price delta rather than step counts.
Data Flow
GetWorkingSecurities configures a Renko candle subscription using RenkoBuildFrom.Points and the computed box size.
OnStarted launches the Renko subscription, subscribes to either trade or bid ticks (depending on UseBidTicks), and
draws the Renko stream on the chart if one is available.
ProcessTrade / ProcessLevel1 store the most recent tick price and timestamp for logging purposes.
ProcessCandle ignores unfinished bricks, filters out data prior to StartTime, and logs each completed brick with
the previous and new close levels alongside the latest tick information.
Usage Tips
Attach the strategy to any instrument that provides either trades or level‑1 updates. The Renko stream will appear in
the standard chart area with the configured prefix.
Because the implementation does not send orders, it can be run in parallel with other trading strategies to provide
a synchronized Renko view of the market.
The log entries contain both the brick direction and the triggering tick. This is handy when comparing the output with
historical data exported from MetaTrader.
Differences vs. the MQL Version
StockSharp already manages symbols, so the explicit custom symbol creation was replaced by logging and chart output.
All calculations use decimal arithmetic instead of arrays, relying on the built-in Renko candle builder.
The strategy embraces StockSharp's subscription model and protection helper, making it ready to be extended with
trading logic if needed.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Renko Chart strategy. Uses WMA crossover for trend detection.
/// </summary>
public class RenkoChartStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast;
private decimal? _prevSlow;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public RenkoChartStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 7)
.SetGreaterThanZero()
.SetDisplay("Fast WMA", "Fast WMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21)
.SetGreaterThanZero()
.SetDisplay("Slow WMA", "Slow WMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null;
_prevSlow = null;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
if (_prevFast == null || _prevSlow == null)
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fastVal > slowVal;
_prevFast = fastVal;
_prevSlow = slowVal;
if (!prevAbove && currAbove && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (prevAbove && !currAbove && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
}
}
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
from StockSharp.Algo.Strategies import Strategy
class renko_chart_strategy(Strategy):
def __init__(self):
super(renko_chart_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 7) \
.SetDisplay("Fast WMA", "Fast WMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 21) \
.SetDisplay("Slow WMA", "Slow WMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(renko_chart_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(renko_chart_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif prev_above and not curr_above and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return renko_chart_strategy()