Category Other  Published on 21/11/2022

Volume for Renko/Range

Description

VolumeRenkoRange applies tick volume logic on non-time based charts.

Last Update -> 16/11/2022

Volume on Range/Renko/Candles

It's possible because we have the Open/Close Time of Bar, so:
Volume logic = Number of price updates (ticks) that come during the formation of a bar (between of OpenTime and CloseTime).

Update:
16/11/2022 - A little optimization.
23/08/2022 - Redundant code removed from "Custom Load From" which generated error in previous version of cTrader (v4.0 or 4.1), the functionality still works.
22/08/2022 - Added dynamic 'Load From', removed redundates parameters, and now the messages disappear after the calculaton is finished
03/08/2022 - Code cleanup.
27/07/2022 - Downgrade from .NET 6.0  to .NET 4.x, for the .algo installation to work on previous versions of cTrader.

===== Parameters =====

  • Load From: {Today, Yesterday, 1 Week, 2 Week, Monthly}
  • Custom (dd/mm/yyyy): Custom Date if Load From(Custom)

Load From is the Date to load Previous Historical Ticks Data, all data will be stored in memory and will be used in any Renko timeframe selected in the chosen Symbol.
if Custom (dd/mm/yyyy) runs with wrong value, it will use the existing data available in the chart..
The initial size allocated in memory will depend on how far from the current date "Load From or Custom" was set, as well as the past number of ticks updates, of couse.


/*
--------------------------------------------------------------------------------------------------------------------------------
                      Volume for Renko/Range
VolumeRenkoRange applies tick volume logic on non-time based charts.

It's possible because we have the Open/Close Time of Bar, so:
Volume logic = Number of price updates (ticks) that come during the formation of a bar (between of OpenTime and CloseTime).

Uses Ticks Data to make the calculation of volume, just like Candles.

For Better Performance, Recompile it on cTrader with .NET 6.0 instead .NET 4.x.

AUTHOR: srlcarlg
----------------------------------------------------------------------------------------------------------------------------
*/
using System;
using System.Globalization;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo
{
    [Indicator(AutoRescale = true, AccessRights = AccessRights.None)]
    public class VolumeRenkoRange : Indicator
    {
        public enum LoadFromData
        {
            Today,
            Yesterday,
            One_Week,
            Two_Week,
            Monthly,
            Custom
        }
        [Parameter("Load From:", DefaultValue = LoadFromData.Today, Group = "==== Volume for Renko&Range ====")]
        public LoadFromData LoadFromInput { get; set; }
        
        [Parameter("Custom (dd/mm/yyyy):", DefaultValue = "00/00/0000", Group = "==== Volume for Renko&Range ====")]
        public string StringDate { get; set; }
        
        [Parameter("Nº Bars to Show:", DefaultValue = -1, MinValue = -1, Group = "==== Volume for Renko&Range ====")]
        public int Lookback { get; set; }
                
        // ==============
        [Output("Main", LineColor="aqua", PlotType = PlotType.Histogram, Thickness = 5)]
        public IndicatorDataSeries Result { get; set; }
        
        [Output("Bullish Volume", LineColor = "green", PlotType = PlotType.Histogram, Thickness = 5)]
        public IndicatorDataSeries BullVolume { get; set; }

        [Output("Bearish Volume", LineColor = "red", PlotType = PlotType.Histogram, Thickness = 5)]
        public IndicatorDataSeries BearVolume { get; set; }
        
        private Bars _TicksOHLC;
        private DateTime FromDateTime;
        private int CurrentVol = 0;
        private bool TextsRemoved = false;
        
        private VerticalAlignment V_Align = VerticalAlignment.Center;
        private HorizontalAlignment H_Align = HorizontalAlignment.Center;
        // ==============
        
        protected override void Initialize()
        {
        
            // First Ticks Data and BarOpened/ObjectsRemoved events 
            _TicksOHLC = MarketData.GetBars(TimeFrame.Tick);
            Bars.BarOpened += ResetCurrentVol;
            Chart.ObjectsRemoved += SetTextsRemoved;
            
            if (LoadFromInput == LoadFromData.Custom)
            {
                // ==== Get datetime to load from: dd/mm/yyyy ====               
                if (DateTime.TryParseExact(StringDate, "dd/mm/yyyy", new CultureInfo("en-US"), DateTimeStyles.None, out FromDateTime))
                {
                    if (FromDateTime > Server.Time.Date) {   
                        // for Log
                        FromDateTime = Server.Time.Date;
                        Print($"Invalid DateTime '{StringDate}'. Using '{FromDateTime}'");
                        // for Screen
                        IndicatorArea.DrawStaticText("txt_2", $"Invalid DateTime '{StringDate}'. \n Using '{FromDateTime.Day}/{FromDateTime.Month}/{FromDateTime.Year}'", VerticalAlignment.Top, HorizontalAlignment.Right, Color.Red);
                    }
                }
                else {
                    // for Log
                    FromDateTime = Server.Time.Date;
                    Print($"Invalid DateTime '{StringDate}'. Using '{FromDateTime}'");
                    // for Screen
                    IndicatorArea.DrawStaticText("txt_2", $"Invalid DateTime '{StringDate}'. \n Using '{FromDateTime.Day}/{FromDateTime.Month}/{FromDateTime.Year}'", VerticalAlignment.Top, HorizontalAlignment.Right, Color.Red);
                }
            }
            else
            {
                DateTime LastBarTime = Bars.LastBar.OpenTime.Date;
                if (LoadFromInput == LoadFromData.Today)
                    FromDateTime = LastBarTime.Date;
                else if (LoadFromInput == LoadFromData.Yesterday)
                    FromDateTime = LastBarTime.AddDays(-1);
                else if (LoadFromInput == LoadFromData.One_Week)
                    FromDateTime = LastBarTime.AddDays(-5);
                else if (LoadFromInput == LoadFromData.Two_Week)
                    FromDateTime = LastBarTime.AddDays(-10);
                else if (LoadFromInput == LoadFromData.Monthly)
                    FromDateTime = LastBarTime.AddMonths(-1);
            }
            
            // ==== Check if existing ticks data on the chart really needs more data ====
            var FirstTickTime = _TicksOHLC.OpenTimes.FirstOrDefault();  
            if (FirstTickTime >= FromDateTime) {                    
                LoadMoreTicks(FromDateTime);
                DrawOnScreen("Data Collection Finished \n Calculating...");
            }
            else {
                Print($"Using existing tick data from '{FirstTickTime}'");  
                DrawOnScreen($"Using existing tick data from '{FirstTickTime}' \n Calculating...");
            }
        }
       
        public override void Calculate(int index)
        {
            // ==== Removing Messages ====
            if (!IsLastBar)
            {
              if (!TextsRemoved)
                    IndicatorArea.RemoveAllObjects();
            }
            else
                CurrentVol += 1;
            
            if (index < (Bars.OpenTimes.GetIndexByTime(Server.Time)-Lookback) && (Lookback != -1 && Lookback > 0))
                return;
            // ==============
            var CurrentTimeBar = Bars.OpenTimes[index];
            var PreviousTimeBar = Bars.OpenTimes[index - 1];
            bool isBullish = (Bars.ClosePrices[index - 1] > Bars.OpenPrices[index - 1]);
            bool currentIsBullish = (Bars.ClosePrices[index] > Bars.OpenPrices[index]);
            // ==============
            
            Result[index - 1] = GetVolume(PreviousTimeBar, CurrentTimeBar);
            Result[index] = CurrentVol;
            
            // ==== HISTORICAL BULL/BEAR VOLUME ====
            if (isBullish)
                BullVolume[index - 1] = Result[index - 1];
            else
                BearVolume[index - 1 ] = Result[index - 1];
            
            // ==== CURRENT BULL/BEAR VOLUME ====
            if (currentIsBullish)
            {
                BullVolume[index] = Result[index];
                BearVolume[index] = 0;
            }
            else
            {
                BearVolume[index] = Result[index];
                BullVolume[index] = 0;
            }
        }
        
        // ========= Functions Area ==========
        private int GetVolume(DateTime startTime, DateTime endTime)
        {
            int volume = 0;
            for (int tickIndex = 0; tickIndex < _TicksOHLC.Count; tickIndex++)
            {
                Bar tickBar = _TicksOHLC[tickIndex];

                if (tickBar.OpenTime < startTime || tickBar.OpenTime > endTime)
                {
                    if (tickBar.OpenTime > endTime)
                        break;
                    else
                        continue;
                }
                
                volume += 1;
            }

            return volume;
        }
        // ========= ========== ==========
        private void LoadMoreTicks(DateTime FromDateTime)
        {
            bool msg = false;
            while (_TicksOHLC.OpenTimes.FirstOrDefault() > FromDateTime)
            {
                if (!msg) {
                    Print($"Loading from '{_TicksOHLC.OpenTimes.Reverse().Last()}' to '{FromDateTime}'...");
                    msg = true;
                }
                int loadedCount = _TicksOHLC.LoadMoreHistory();
                Print("Loaded {0} Ticks, Current Tick Date: {1}", loadedCount, _TicksOHLC.OpenTimes.FirstOrDefault());
                if (loadedCount == 0)
                    break;
            }
            Print("Data Collection Finished, First Tick from: {0}", _TicksOHLC.OpenTimes.FirstOrDefault());
        }
        // ========= ========== ==========
        private void ResetCurrentVol(BarOpenedEventArgs obj)
        {
            CurrentVol = 0;
        }
        // ========= ========== ==========
        private void DrawOnScreen(string Msg)
        {
            IndicatorArea.DrawStaticText("txt", $"{Msg}", V_Align, H_Align, Color.Orange);
        }
        // ========= ========== ==========
        private void SetTextsRemoved(ChartObjectsRemovedEventArgs obj)
        {
            TextsRemoved = true;
        }
    }
}

srlcarlg's avatar
srlcarlg

Joined on 25.07.2022

  • Distribution: Free
  • Language: C#
  • Trading platform: cTrader Automate
  • File name: Volume for Renko&Range.algo
  • Rating: 5
  • Installs: 2125
  • Modified: 16/11/2022 14:43
Comments
Log in to add a comment.
SC
scotpip · 2 months ago

Good effort! But it's a pity they have never to around to fixing this issue - it should be part of the app, where it would be more efficient.

JO
johnmic629 · 5 months ago


This is such awesome content i got to read after lot of time. Its so interesting as well as informative. I am sure everyone who read it got a lot to learn from it.

 

tbird jackets

 

EU
eurodrigopaixao · 1 year ago

Olá, acabei de ver sua biblioteca renkodf e gostaria de entrar em contato, se não for incomodo. Obrigado.

AB
abhaysinh94 · 1 year ago

Can you add option to display commutative wave volume or bar volume?

HO
howyg1 · 1 year ago

How Would i reference in a cbot, for last bar bull or bears above 1000

        private VolumeRenkoRange _vrr;
 

            _vrr = Indicators.GetIndicator<VolumeRenkoRange>(?, ?);


                var VolumeUP = _vrr.BullVolume.Last(1) > 1000;
                var VolumeDOWN = _vrr.BearVolume.Last(1) > 1000;
 

CH
christopherhale68 · 2 years ago

Summarize your experience in a polished professional bio. Use these bio examples, templates, and tips to showcase your career online for ...

  •  The key to using the APA style is consistent grammar throughout your work. You should also avoid using contractions or words that have irregular spellings. For example, you should write “the” as “thee” instead of “their.You can also check ou https://aceassignment.co.uk/essaysnassignments-review/
srlcarlg's avatar
srlcarlg · 2 years ago

@mztd006 A crazy tool!! I really liked what I saw, thanks for letting me know about it.
Now, about bringing it to cTrader, it might take a while to make it polished, BUT special attention will be given to this script.

MZ
mztd006 · 2 years ago

if you could bring Renko with Volume and Time in the box  to ctrader it would be great tool 

 

CL
clarkeadams37 · 2 years ago

Complete and maintain code. I am also her web developer and need to integrate these codes into her website. for now, I am working with cute halloween outfits. They have grown tremendously since launching its first website.
 

MZ
mztd006 · 2 years ago

@srlcarlg

look at this script on tradingview.  Numbers Renko

it have same function but in more visually appealing way

DA
dawid.pielak · 2 years ago

@srlcarlg thank you, 

srlcarlg's avatar
srlcarlg · 2 years ago

@dawid.pielak Now it should work, download the updated file.

Thanks for the feedback, I really had forgotten that the versions available in the brokers are versions prior to the implementation of .NET 6.0 in Ctrader.

DA
dawid.pielak · 2 years ago

I have a problem, during installation  a windows pop out ,,unable to parse targer framework net6.0''