Category Other  Published on 17/06/2018

RangeBars

Description

The RangeBars indicator should be attached to 1-minute charts for best historical candle accuracy.

It is displayed as an overlay on the main chart so, you may want to change the chart properties to "line chart" and the "Bear Outline" color to black for better clarity of displayed bars.

The chart contains OLHC reference points so other indicators such as moving averages can be attached directly to the range bar chart.


This is a 14-day trial version. Lifetime license can be purchased >> here <<

RangeBars for cTrader & cAlgo

Available Inputs

  • Bar Size (number of pips)
  • Maximum Bars
  • Reset Open on new trading day (Yes /No)
  • Bullish Bar Color
  • Bearish Bar Color

Referencing the indicator from a cAlgo robot

//
//  Declare and create an instance of  RangeBars indicator
//
 
private RangeBars rb_indi;
 
protected override void OnStart()
{
  object[] parameterValues = 
            {
                10, // Bar size
                100, // Show number of bars
                true, // Reset on new trading day
                "Green", // Bullish bar color
                "Red" // Bearish bar color
            };
    rb_indi =Indicators.GetIndicator<RangeBars>(parameterValues);
 
//
//  Start processing...
//
  
protected override void OnTick()
{
    //
    // Example: check if last 2 completed bars are bullish
    //
 
    bool lastTwoBarsBullish = (rb_indi.Open.Last(1) < rb_indi.Close.Last(1)) && (rb_indi.Open.Last(2) < rb_indi.Close.Last(2));
  
    //
    // Trading logic goes here...
    //
}

 


using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Diagnostics;
using cT_RangeBarsEngine;

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

        [Parameter("Maximum Bars", DefaultValue = 300, MinValue = 1)]
        public int BricksToShow { get; set; }

        [Parameter("Reset Open on new trading day", DefaultValue = false)]
        public bool ResetOpenOnNewTradingDay { get; set; }

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

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

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

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

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

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

        private RangeBarsCore core = null;
        private bool coreOK = true;

        private DateTime lastTime;

        private T_OLHCV OLHCV;
        private T_OLHCV mOLHCV;
        private T_OLHCV cOLHCV;
        private T_OLHCV memRates;
        private T_OLHCV lastBar;

        private List<T_OLHCV> bars = new List<T_OLHCV>();
        private double barSize;
        private Colors colorBull, colorBear;


        private int _lc;

        protected override void Initialize()
        {
            core = new RangeBarsCore();
            coreOK = core.ChackStatus();
            _lc = core.GetLC();

            barSize = BarSizePips * Symbol.PipSize;

            lastTime = new DateTime();
            lastTime = MarketSeries.OpenTime[MarketSeries.Close.Count - 1];

            lastBar = new T_OLHCV();
            OLHCV = new T_OLHCV();
            mOLHCV = new T_OLHCV();
            cOLHCV = new T_OLHCV();
            memRates = new T_OLHCV();

            if (!Enum.TryParse<Colors>(ColorBull, out colorBull))
            {
                colorBull = Colors.SeaGreen;
            }
            if (!Enum.TryParse<Colors>(ColorBear, out colorBear))
            {
                colorBear = Colors.Tomato;
            }
        }

        private bool NewBar(int index)
        {
            if (lastTime != MarketSeries.OpenTime[index])
            {
                lastTime = MarketSeries.OpenTime[index];
                return true;
            }

            return false;
        }

        private static int cc = 0;
        private void pushBars(T_OLHCV bar, bool display)
        {
            int count = bars.Count();

            var newBar = new T_OLHCV();
            newBar.Copy(bar);
            newBar.Index = cc++;

            bars.Insert(0, newBar);
            count++;

            if (display)
            {
                shiftBars(0);
            }

            if (count > BricksToShow)
            {
                if (display)
                {
                    for (int i = BricksToShow - 1; i < count; i++)
                    {
                        ChartObjects.RemoveObject("rb_Wick_" + bars[i].Index);
                        ChartObjects.RemoveObject("rb_Bar_" + bars[i].Index);
                    }
                }

                bars.RemoveRange(BricksToShow, count - BricksToShow);

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

        }

        private void shiftBars(int shift)
        {
            int count = bars.Count;
            int ix = MarketSeries.Close.Count - 2;

            for (int i = 0; i < count && i < BricksToShow; i++)
            {
                var candleColor = (bars[i].Close > bars[i].Open) ? colorBull : colorBear;

                ChartObjects.DrawLine("rb_Wick_" + bars[i].Index, ix, bars[i].High, ix, bars[i].Low, candleColor, 1, LineStyle.Solid);
                ChartObjects.DrawLine("rb_Bar_" + bars[i].Index, ix, bars[i].Close, ix, bars[i].Open, candleColor, 5, LineStyle.Solid);

                Open[ix] = bars[i].Open;
                High[ix] = bars[i].High;
                Low[ix] = bars[i].Low;
                Close[ix] = bars[i].Close;

                ix--;
            }
        }

        private void UpdateLastBar(int ix)
        {
            var candleColor = (memRates.Close > memRates.Open) ? colorBull : colorBear;

            ChartObjects.DrawLine("rb_Wick_Live", ix, memRates.High, ix, memRates.Low, candleColor, 1, LineStyle.Solid);
            ChartObjects.DrawLine("rb_Bar_Live", ix, memRates.Close, ix, memRates.Open, candleColor, 5, LineStyle.Solid);

            Open[ix] = memRates.Open;
            High[ix] = memRates.High;
            Low[ix] = memRates.Low;
            Close[ix] = memRates.Close;

        }

        public override void Calculate(int index)
        {
            if (ResetOpenOnNewTradingDay)
            {
                if (IsNewSession(MarketSeries.OpenTime[(index > 0) ? (index - 1) : index], MarketSeries.OpenTime[index]))
                {
                    cOLHCV.Clear();
                    mOLHCV.Clear();
                    memRates.Copy(mOLHCV);
                }
            }

            if (IsRealTime)
            {
                if (!coreOK)
                {
                    ChartObjects.DrawText("TrialOverMsg", "RangeBars Indicator - Trial period ended. Please purchase a license file at www.az-invest.eu", StaticPosition.Center, Colors.White);
                    return;
                }

                if (NewBar(index))
                {
                    shiftBars(0);

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

                OLHCV.Open = MarketSeries.Close[index];
                OLHCV.Low = MarketSeries.Close[index];
                OLHCV.High = MarketSeries.Close[index];
                OLHCV.Close = MarketSeries.Close[index];
                OLHCV.OpenTime = MarketSeries.OpenTime[index];
                OLHCV.TickVolume = 1;

                ProcessMarketData(OLHCV);
                UpdateLastBar(index);
            }
            else
            {
                OLHCV.Open = MarketSeries.Open[index];
                OLHCV.Low = MarketSeries.Low[index];
                OLHCV.High = MarketSeries.High[index];
                OLHCV.Close = MarketSeries.Close[index];
                OLHCV.OpenTime = MarketSeries.OpenTime[index];
                OLHCV.TickVolume = MarketSeries.TickVolume[index];

                ProcessMarketData(OLHCV);

                if (IsLastBar)
                    UpdateLastBar(index);
            }
        }

        private void ProcessMarketData(T_OLHCV ___OLHCV)
        {
            int rb_return = core.ProcessRangeBars(barSize, ___OLHCV, ref mOLHCV, ref cOLHCV, 1);
            while (true)
            {
                if (((rb_return >= 1) && (rb_return <= 4)) || ((rb_return >= 6) && (rb_return <= 9)))
                {
                    pushBars(cOLHCV, IsRealTime);
                    memRates.Copy(mOLHCV);
                    OLHCV.Copy(memRates);

                    cOLHCV.Clear();
                    mOLHCV.Clear();

                    rb_return = core.ProcessRangeBars(barSize, ___OLHCV, ref mOLHCV, ref cOLHCV, 0);
                    continue;

                }
                else if ((rb_return == 5) || (rb_return == 10))
                {
                    memRates.Copy(mOLHCV);
                    break;
                }
                else if (rb_return == -1)
                {
                    return;
                }
                else
                {
                    throw new Exception("Unhandled return value = " + rb_return);
                }
            }

            if (IsLastBar && !IsRealTime)
            {
                shiftBars(0);
            }
        }

        private bool IsNewSession(DateTime prevTime, DateTime currTime)
        {
            if (prevTime.DayOfWeek != currTime.DayOfWeek)
                return true;
            else
                return false;
        }

    }
}



AR
arturzas

Joined on 15.06.2016

  • Distribution: Free
  • Language: C#
  • Trading platform: cTrader Automate
  • File name: RangeBars.algo
  • Rating: 0
  • Installs: 4189
  • Modified: 13/10/2021 09:54
Comments
Log in to add a comment.
CH
chiripacha · 7 years ago

@asturcas

2) You can only attach indicators that let you choose the "source price" value they should reference for calculations.

you can't use then e.g.Parabolic SAR or Stochastic aso. That seems to me to be a BIG disadvantage. You are not able to play the strategies in which these indicators are involved. Right?

CH
chiripacha · 7 years ago

2) You can only attach indicators that let you choose the "source price" value they should reference for calculations.

you can't use then e.g.Parabolic SAR or Stochastic aso. That seems to me to be a BIG disadvantage. You are not able to play the strategies in which these indicators are involved. Right?

AR
arturzas · 7 years ago

Sorry for the delay with my answers - unfortunately I do not get any notifications about new coments.

Anyway here are the answers to the two questions above:

1) You need to provide full access rights in your robot (AccessRights = AccessRights.FullAccess), because the indicator requires them to access functions of the .NET framework.
Failing to do so will block the indicator from initializing and you will have a NULL reference instead of a reference to the median renko indicator.

2) You can only attach indicators that let you choose the "source price" value they should reference for calculations.

Please see the image file for Renko charts with MAs applied - range bars also have reference points that can be used by indicators. You need to set the "source" as one of the range bars open,low,high or close, provided that the indicator you are using lets you set this.

JS
JS1979 · 7 years ago

Hi,

I purchased this indicator the other day and it is amazing.

I have been trying to attach a Dual Stochastic to the range bars but the highs and lows of the stochastic do not match up with the highs and lows of the range bars. I think the stochastis is actually matching up with price instead. Is there any way to correct this?

Thank you

J

CO
cousens · 8 years ago

Hi, 

Nice indicator but just a couple of questions:

1) If I set the range to 50 it only has about 20 bars going backwards

2) I'm trying to create another indicator referencing yours but I can't seem to get it displaying any data.

             rb = Indicators.GetIndicator<RangeBars>(10, 100, "Green", "Red");

             GoLong[index - 1] = rb.Open.Last(1);

What am I doing wrong in referencing as there are no build errors, just no data is being returned.

Thanks