This strategy emulates a classic Renko brick chart and trades on brick direction changes. It was converted from the MetaTrader script RenkoLiveChart_v600.
Logic
The strategy builds Renko bricks using finished time‑based candles. When the price moves by at least the selected box size from the last brick price, a new brick is formed. A long position is opened on an upward brick and a short position on a downward brick.
Parameters
Candle Type – timeframe of the input candles used for brick construction.
Brick Size – price step that defines the height of a Renko brick.
Brick Offset – initial offset in bricks applied to the first brick.
Show Wicks – display wicks on the chart when drawing candles.
Notes
Trades are executed only on completed candles.
Position protection is started automatically on strategy start.
This implementation focuses on core Renko behaviour and ignores advanced features of the original script, such as external file handling.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Renko live chart emulation strategy.
/// </summary>
public class RenkoLiveChartStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _brickSize;
private decimal _renkoPrice;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public decimal BrickSize { get => _brickSize.Value; set => _brickSize.Value = value; }
public RenkoLiveChartStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Working candle timeframe", "General");
_brickSize = Param(nameof(BrickSize), 500m)
.SetGreaterThanZero()
.SetDisplay("Brick Size", "Renko brick size", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_renkoPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
SubscribeCandles(CandleType).Bind(ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
var size = BrickSize;
if (_renkoPrice == 0m)
{
_renkoPrice = close;
return;
}
var diff = close - _renkoPrice;
if (Math.Abs(diff) < size)
return;
var direction = Math.Sign(diff);
_renkoPrice += direction * size;
if (direction > 0 && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (direction < 0 && 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.Strategies import Strategy
class renko_live_chart_strategy(Strategy):
def __init__(self):
super(renko_live_chart_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Working candle timeframe", "General")
self._brick_size = self.Param("BrickSize", 500.0) \
.SetDisplay("Brick Size", "Renko brick size", "General")
self._renko_price = 0.0
@property
def candle_type(self):
return self._candle_type.Value
@property
def brick_size(self):
return self._brick_size.Value
def OnReseted(self):
super(renko_live_chart_strategy, self).OnReseted()
self._renko_price = 0.0
def OnStarted2(self, time):
super(renko_live_chart_strategy, self).OnStarted2(time)
self.SubscribeCandles(self.candle_type).Bind(self.process_candle).Start()
def process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
size = float(self.brick_size)
if self._renko_price == 0.0:
self._renko_price = close
return
diff = close - self._renko_price
if abs(diff) < size:
return
direction = 1 if diff > 0 else -1
self._renko_price += direction * size
if direction > 0 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif direction < 0 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return renko_live_chart_strategy()