Renko

by Jiri Beloch in category Trend at 24/01/2016
Description

Description

A type of chart, developed by the Japanese, that is only concerned with price movement - time and volume are not included. A renko chart is constructed by placing a brick in the next column once the price surpasses the top or bottom of the previous brick by a predefined amount. Green bricks are used when the direction of the trend is up, while red bricks are used when the trend is down.

Updates

  • 24/01/2016
    • Released.
  • 25/01/2016
    • Added live forming brick.
    • Added option to plot defined number of bricks.
    • Added option to choose colors for bricks.
    • Updated reference mode for better performance.
  • 27/01/2016
    • Changed charting method.
    • Overlay set to true by default.
    • Deleted reference mode. (Check reference sample to update your cBot / Indicator!)
  • 29/01/2016
    • Added LastValue (live forming brick) into outputs.
  • 31/01/2016
    • Added High and Low values into outputs.
  • 01/02/2016
    • Fixed live brick not drawing when BricksToShow was set too high.
    • Improved performance.

 

Inputs

  • Renko (Pips) - Defines height of one brick in pips.
  • Bricks To Show - Defines how many bricks will be plotted.
  • Zoom Level - Adjusts width of bricks for defined zoom level.
  • Bullish Color - Sets color of bullish bricks.
  • Bearish Color - Sets color of bearish bricks.

 

Screenshot

 

Notes

  • Overlay - Indicator can be set not to overlay at line 11.
    [Indicator("Renko", IsOverlay = false, ...)]
  • Referencing - Indicator can be used in other indicators or cBots. Sample below.
    public double RenkoPips = 10;
    public int BricksToShow = 10;
    
    private Renko renko;
    
    protected override void OnStart()
    {
        renko = Indicators.GetIndicator<Renko>(RenkoPips, BricksToShow, 3, "SeaGreen", "Tomato");
    }
    
    protected override void OnTick()
    {
        bool isLastBrickBullish = renko.Open.Last(1) < renko.Close.Last(1);
    
        if (isLastBrickBullish)
        {
            ExecuteMarketOrder(TradeType.Buy, Symbol, 1000);
        }
    }
  • Accuracy
    • When the indicator is loaded it can access only OHLC values of historical data. For better accuracy of historical chart I highly recommend using lower timeframe and scroll back for more data.
    • When the indicator is running it's fed by live data (each tick) so it's 100% accurate no matter what timeframe it's loaded up on.

 

Make a Donation

  • If you like my work and effort then please consider to make a kind donation thru PayPal or any Credit Card at this link.

 

 

Download
6066 downloads
How to install
Notification Publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section you may use the Copyright Infringement Notification form to submit a claim.
Formula / Source Code
Language: C#
Trading Platform: cAlgocTrader
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System;
using System.Collections.Generic;
using System.Linq;

namespace cAlgo
{
    [Indicator("Renko", IsOverlay = true, AutoRescale = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Renko : Indicator
    {
        [Parameter("Renko (Pips)", DefaultValue = 10, MinValue = 0.1, Step = 1)]
        public double RenkoPips { get; set; }

        [Parameter("Bricks To Show", DefaultValue = 100, MinValue = 1)]
        public int BricksToShow { get; set; }

        [Parameter("Zoom Level", DefaultValue = 3, MinValue = 0, MaxValue = 5, Step = 1)]
        public double ZoomLevel { get; set; }

        [Parameter("Bullish Color", DefaultValue = "SeaGreen")]
        public string ColorBull { get; set; }

        [Parameter("Bearish Color", DefaultValue = "Tomato")]
        public string ColorBear { get; set; }

        [Output("Open", Color = Colors.DimGray, Thickness = 1, PlotType = PlotType.Points)]
        public IndicatorDataSeries Open { get; set; }

        [Output("High", Color = Colors.DimGray, Thickness = 1, PlotType = PlotType.Points)]
        public IndicatorDataSeries High { get; set; }

        [Output("Low", Color = Colors.DimGray, Thickness = 1, PlotType = PlotType.Points)]
        public IndicatorDataSeries Low { get; set; }

        [Output("Close", Color = Colors.DimGray, Thickness = 1, PlotType = PlotType.Points)]
        public IndicatorDataSeries Close { get; set; }

        public class Brick
        {
            public double Open { get; set; }
            public double Close { get; set; }
        }

        public List<Brick> Bricks = new List<Brick>();

        private double closeLastValue, thickness, renkoPips, renkoLastValue;
        private Colors colorBull, colorBear;
        private bool colorError;
        private int lastCount;

        protected override void Initialize()
        {
            if (!Enum.TryParse<Colors>(ColorBull, out colorBull) || !Enum.TryParse<Colors>(ColorBear, out colorBear))
                colorError = true;

            renkoPips = RenkoPips * Symbol.PipSize;
            thickness = Math.Pow(2, ZoomLevel) - (ZoomLevel > 0 ? 1 : 0);
            renkoLastValue = 0;
        }

        public override void Calculate(int index)
        {
            if (colorError)
            {
                ChartObjects.DrawText("Error0", "{o,o}\n/)_)\n \" \"\nOops! Incorrect colors.", StaticPosition.TopCenter, Colors.Gray);
                return;
            }

            if (renkoLastValue == 0)
            {
                var open = MarketSeries.Open.LastValue;

                renkoLastValue = open - (open % renkoPips) + renkoPips / 2;
            }

            closeLastValue = MarketSeries.Close.LastValue;

            while (closeLastValue >= renkoLastValue + renkoPips * 1.5)
            {
                renkoLastValue += renkoPips;
                Bricks.Insert(0, new Brick 
                {
                    Open = renkoLastValue - renkoPips / 2,
                    Close = renkoLastValue + renkoPips / 2
                });

                if (Bricks.Count() > BricksToShow)
                    Bricks.RemoveRange(BricksToShow, Bricks.Count() - BricksToShow);
                if (IsLastBar)
                    UpdateHistory(index);
            }
            while (closeLastValue <= renkoLastValue - renkoPips * 1.5)
            {
                renkoLastValue -= renkoPips;
                Bricks.Insert(0, new Brick 
                {
                    Open = renkoLastValue + renkoPips / 2,
                    Close = renkoLastValue - renkoPips / 2
                });

                if (Bricks.Count() > BricksToShow)
                    Bricks.RemoveRange(BricksToShow, Bricks.Count() - BricksToShow);
                if (IsLastBar)
                    UpdateHistory(index);
            }

            bool isNewBar = MarketSeries.Close.Count > lastCount;

            if (IsLastBar && isNewBar)
            {
                UpdateHistory(index);

                Open[index - BricksToShow] = double.NaN;
                High[index - BricksToShow] = double.NaN;
                Low[index - BricksToShow] = double.NaN;
                Close[index - BricksToShow] = double.NaN;

                lastCount = MarketSeries.Close.Count;
            }

            if (IsRealTime)
                UpdateLive(index);
        }

        private void UpdateHistory(int index)
        {
            for (int i = 0; i < BricksToShow - 1 && i < Bricks.Count() - 1; i++)
            {
                var color = Bricks[i].Open < Bricks[i].Close ? colorBull : colorBear;

                ChartObjects.DrawLine(string.Format("renko.Last({0})", i + 1), index - i - 1, Bricks[i].Open, index - i - 1, Bricks[i].Close, color, thickness, LineStyle.Solid);

                Open[index - i - 1] = Bricks[i].Open;
                High[index - i - 1] = Math.Max(Bricks[i].Open, Bricks[i].Close);
                Low[index - i - 1] = Math.Min(Bricks[i].Open, Bricks[i].Close);
                Close[index - i - 1] = Bricks[i].Close;
            }
        }

        private void UpdateLive(int index)
        {
            double y1, y2;
            var top = Math.Max(Bricks[0].Open, Bricks[0].Close);
            var bottom = Math.Min(Bricks[0].Open, Bricks[0].Close);

            if (closeLastValue > top)
                y1 = top;
            else if (closeLastValue < bottom)
                y1 = bottom;
            else
                y1 = closeLastValue;

            y2 = closeLastValue;

            var colorLive = y1 < y2 ? colorBull : colorBear;

            ChartObjects.DrawLine("renko.Live", index, y1, index, y2, colorLive, thickness, LineStyle.Solid);

            Open[index] = y1;
            High[index] = y1 > y2 ? y1 : y2;
            Low[index] = y1 < y2 ? y1 : y2;
            Close[index] = y2;
        }
    }
}
Comments

Paul Hayes - January 25, 2016 @ 10:06

Nice job Jiri, thanks.

Jiri Beloch - January 27, 2016 @ 21:17

Please, download latest version for better performance. ;)

trend_meanreversion - January 29, 2016 @ 11:05

Thanks TMC for the indicator but it is not generating renko real time. It seems there is 1 brick delay. I have sent you an email , please respond when you get time.

Jiri Beloch - January 29, 2016 @ 17:43

@trend_meanreversion Thank you for reporting that issue. Outputs are fixed now and Open/Close.LastValue should return value now.

Jiri Beloch - February 01, 2016 @ 21:10

@trend_meanreversion I guess you were talking about another issue I came across today and fixed. Please download updated version. ;)

trend_meanreversion - February 02, 2016 @ 03:56

@tmc : let me do some testing this week and i will get back to you if i still find the initial issue. I am thinking of trying RSI on this Renko, to come up with some strategy. Let's see how it goes.

trend_meanreversion - February 02, 2016 @ 07:43

@tmc : I am not an expert but i think once you have a sell brick followed by buy brick then that buy brick should also be displayed. Currently a sell brick is followed by buy brick only when you have a move of 2*RenkoPips ie..price of 100 -> 95 -> 100 -> 105 => we should have sell , buy and buy brick but currently indicator draws sell(100->95) and buy(100->105) brick only ( misses the 95->100 move )

Jiri Beloch - February 02, 2016 @ 14:16

@trend_meanreversion: Not really. I was studying renko on multiple platforms and they all work just like that. The price needs to surpass the top or bottom of the previous brick by a predefined amount in order to make new brick.

Otherwise, the chart would like something like that.

  •    ⍁⍂
  • ⍁      ⍂

Instead of.

  •    ⍁
  • ⍁   ⍂

trend_meanreversion - February 02, 2016 @ 23:47

@tmc : Thanks mate. I suppose i would have preferred the first way rather than second one.

Marco - March 05, 2016 @ 11:32

A very valuable job, thank you!

marciogarcia - March 17, 2016 @ 14:41

If I change the time frame from M5 to M15 and then change again to M5 the renko bricks appears different. Is that normal?

IE: M5 => In a up trend, we have a formation with 1 brick up and 1 brick down and then some bricks up... If I change the time frame from M5 to M15 and then return to M5, it will appear only up bricks. Is it supposed to be like that?

Jiri Beloch - March 19, 2016 @ 12:54

@marciogarcia : As I stated in "Accuracy" above, when the indicator is loaded it can access only OHLC values of historical data. So if you left indicator running a while, it got fed by tick data and might plot some candles that you can't read from OHLC values only. When you refreshed the chart those candles may disappeared due to lack of data.

marciogarcia - March 19, 2016 @ 16:38

@tmc: Hi tmc, I did not see the accuracy notes, my fault :) Nice job, thank you!

majesamade - March 24, 2016 @ 20:35

i have problem http://octafx.ctrader.com/images/screens/Lzwbn.png

Jiri Beloch - March 26, 2016 @ 14:14

@majesamade What problem exactly?

majesamade - March 28, 2016 @ 00:29

http://octafx.ctrader.com/images/screens/Lzwbn.png

look at image problem 

Jiri Beloch - March 28, 2016 @ 02:58

I don't see any problem.

fouadmail - December 21, 2016 @ 00:13

A very valuable job, thank you!

fouadmail - December 21, 2016 @ 00:48

Great Indicator ! Thank you

However, cannot get it to work in the tester using my cBot ...

Code:

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class RenkoBot : Robot
    {



        [Parameter("RenkoPips", DefaultValue = 10, MinValue = 2, Step = 2)]
        public double RenkoPips { get; set; }

        [Parameter("Quantity (Lots)", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }

        private Renko mr_indi;

        protected override void OnStart()
        {

            mr_indi = Indicators.GetIndicator<Renko>(RenkoPips, 100, 3, "SeaGreen", "Tomato");


        }

        protected override void OnTick()
        {

            var longPosition = Positions.Find("Renko", Symbol, TradeType.Buy);
            var shortPosition = Positions.Find("Renko", Symbol, TradeType.Sell);

            bool lastTwoBarsBullish = mr_indi.Open.Last(1) < mr_indi.Close.Last(1);
            bool lastTwoBarsBearish = mr_indi.Open.Last(1) > mr_indi.Close.Last(1);

            if (lastTwoBarsBullish && longPosition == null)
            {
                if (shortPosition != null)
                    ClosePosition(shortPosition);
                ExecuteMarketOrder(TradeType.Buy, Symbol, 10000, "Renko");
            }
            else if (lastTwoBarsBearish && shortPosition == null)
            {
                if (longPosition != null)
                    ClosePosition(longPosition);
                ExecuteMarketOrder(TradeType.Sell, Symbol, 10000, "Renko");
            }

        }



    }
}
















 

fouadmail - December 21, 2016 @ 00:58

It Repaints ?

Lyuben Sheytanov - February 24, 2017 @ 22:18

tmc - great job!
How can I create rule to trade on the creations of new brick?

larsonsteffensen - May 23, 2017 @ 14:47

This renko can not be used. It has a dangerous bug.

All the renko boxes are not the same size. The problem happen when the color change from red to green, or from green to red.

Example:

i set the renko to 5 pip. And all the boxes are 5 pip. But on color change they are 10 pip becuase the open price is used.

red = 5 pip
red = 5 pip
red = 5 pip
green = 10 pip
green = 5 pip
green = 5 pip
red = 10 pip

This is a MAJOR problem. I can see i am not the first to mention this, and that the developer dont think its a problem. But if you set a renko chart to be 5 pips, then ALL the boxes needs to be 5 pip.

The truth is everytime the color change, 1 box is missing, and this makes a trading problem. Especially if you use it with high pip setting like 20 or 50. Then you have 50 pips missing and it creates the potensial for double loss.

I will be happy to pay anyone to fix this bug. Until its fixed, all should be warned about using this indicator.

If you are a developer who can fix this, please contact me:
larsonsteffensen (a) gmail.com

 

 

 

Jiri Beloch - June 02, 2017 @ 13:41

It's not a bug, that's how classic/standard renko is supposed to work as explained in previous comments. If you want to protect your position just set SL to same size as a renko brick and trail it.

I am planning to release an universal renko which can be optimized to your needs - brick size, open offset and reversal size, as soon as we publish our website.

larsonsteffensen - June 16, 2017 @ 10:13

I would like to say sorry.

Let me be celar. IT IS NOT A BUG, and this is a VERY GOOD indicator.

But what i say is still true. there is boxes missing, and you should KNOW this before trading. i have traded with renko for a long time, and i did not know they build them in many different ways.

The problem is not with tmc or his indicator. It was with my knowledge.

However. It is VERY IMPORTANT, to understand how this indicator work before using it, because if you dont udnerstand it 100% it can cheat you with the illussion of how many pips the market has moved. I found out this can happen easy, because even tho there are many different renko indicators. they all look the same. So educate yourself first.

I HIGHLY recomend this indicator, and tmc as a developer. He does very good work, and you can trust him. He dot work for me personally.

best regards

jadfakhoury@gmail.com - July 06, 2017 @ 08:48

Hey guys i'm a programmer but i'm new to calgo, could anyone show me the way to create a MACD indicator to work on the candles created by this renko indicator? or if it already exist just link me.

Thanks

chiripacha - August 24, 2017 @ 04:34

MACD asks for the source. Just take Renko as the source.

thierry - February 19, 2018 @ 21:26

Does not work well at last. It seems that it has some result default when the current Renko bar returns to the last Renko bar close. This seems to lead visually by a horizontal jump backwards on the last Renko bar. Moreover if you use it in a bot, there are very quick positions (buy & sell or the contrary) likely due to this jump.

At last if you used it with a custom indicator as the following: https://ctdn.com/algos/indicators/show/1608, there will be a failure, again probabaly due to th backwards.

Thanks

Jiri Beloch - February 20, 2018 @ 15:55

The Renko is overlaying your chart, it's just an indicator. Since the chart is time-based while Renko is price-change based there is applied a logic that shifts Renko to align with the latest bar. You will need to integrate same logic to the indicator if you want to feed it with Renko as a source.

didpenny - March 19, 2018 @ 00:37

Hi tmc,

Great job.

Quick question for you, I am trying to calculate a moving average based on your renko chart. Sounds simple but it does not seem to work (nothing appears on the chart), even if this compiles - do you see anything wrong in this section of my code:

 private Renko renko;
 private IndicatorDataSeries renko_data;
 private MovingAverage renko_MA;

 protected override void Initialize()
        {

            renko = Indicators.GetIndicator(RenkoPips, BricksToShow, 3, "SeaGreen", "Tomato");
            renko_data = CreateDataSeries();
            renko_MA = Indicators.MovingAverage(renko_data, 10, MovingAverageType.Simple);

        }

        public override void Calculate(int index)
        {

            renko_data[index] = renko.Close[index];

            Indic[index] = renko_MA.Result[index];

        }

 

ceakuk - March 28, 2018 @ 23:05

@didpenny

The right approach is below. its something @tmc. needs to correct

renko = Indicators.GetIndicator<Renko>(RenkoPips, BricksToShow, 3, "SeaGreen", "Tomato");

Jiri Beloch - April 27, 2018 @ 16:25

Thanks for pointing this out, didn't notice it. :)

mapseam - November 08, 2018 @ 10:11

Thanx for you renko indi!

renko = Indicators.GetIndicator<Renko>(RenkoPips, BricksToShow, 3, "SeaGreen", "Tomato");
Buy renko.Bricks.Count() = 0.

Tell me please, why?

mapseam - November 21, 2018 @ 10:10

Can I do the calculation of Renko bars inside the bot?

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class My_RenkoRobot : Robot
    {
        [Parameter("Renko (Pips)", DefaultValue = 10.0, MinValue = 0.1, Step = 1)]
        public double RenkoPips { get; set; }

    protected class Brick
        {
            public double Open { get; set; }
            public double Close { get; set; }
        }

        protected List<Brick> Bricks = new List<Brick>();

        private double closeLastValue, renkoPips, renkoLastValue;
    private MarketSeries M1;

        protected override void OnStart()
        {
        // ...
            renkoPips = RenkoPips * Symbol.PipSize;
        
        M1 = MarketData.GetSeries(TimeFrame.Minute);        
        var open = M1.Open.LastValue;
            renkoLastValue = open - (open % renkoPips) + renkoPips / 2;

        int totalBars = Math.Min(LookupBars + 1, M1.Close.Count);

        for (int i = 0; i < totalBars; i++)
        {
                closeLastValue = M1.Close[i];

                while (closeLastValue >= renkoLastValue + renkoPips * 1.5)
                {
                    renkoLastValue += renkoPips;
                    Bricks.Insert(0, new Brick
                    {
                            Open = renkoLastValue - renkoPips / 2,
                Low = Open,
                            Close = renkoLastValue + renkoPips / 2,
                High = Close
                    });
                }

                while (closeLastValue <= renkoLastValue - renkoPips * 1.5)
                {
                    renkoLastValue -= renkoPips;
                    Bricks.Insert(0, new Brick
                    {
                            Open = renkoLastValue + renkoPips / 2,
                High = Open,
                            Close = renkoLastValue - renkoPips / 2,
                Low = Close
                    });
                }        
        }
        // ...
    }

        protected override void OnTick()
        {
        // ...
            double y1, y2;
            var top = Math.Max(Bricks[0].Open, Bricks[0].Close);
            var bottom = Math.Min(Bricks[0].Open, Bricks[0].Close);

        closeLastValue = M1.Close[0];

            if (closeLastValue > top)
                y1 = top;
            else if (closeLastValue < bottom)
                y1 = bottom;
            else
                y1 = closeLastValue;

            y2 = closeLastValue;

            Bricks[0].Open = y1;
            Bricks[0].High = y1 > y2 ? y1 : y2;
            Bricks[0].Low = y1 < y2 ? y1 : y2;
            Bricks[0].Close = y2;
        // ...
    }
    }
}

robert.dms83@gmail.com - December 18, 2018 @ 03:34

its appear as indicator, not a chart type so price dont follow...

silvio - January 18, 2019 @ 12:35

Dear Jiri, 

I have opened a thread related to your indicator,  https://ctrader.com/forum/cbot-support/14881

Would you be able to give me any advise on that question?

Thanks

4.44