Volume for Renko/Range free

by srlcarlg in category Other at 27/07/2022
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.

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
/*
--------------------------------------------------------------------------------------------------------------------------------
                      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;
        }
    }
}
Comments

normanwolf2972126 - July 27, 2022 @ 12:45

The information is great. This is what I am looking for. Thanks for sharing Elastic man

dawid.pielak - July 27, 2022 @ 20:06

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

srlcarlg - July 27, 2022 @ 20:34

@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.

dawid.pielak - July 28, 2022 @ 18:11

@srlcarlg thank you, 

footmanindustrial - July 29, 2022 @ 13:52

Thank you for the feedback. I had completely forgotten that geometry dash the versions offered by brokers are ones from before Ctrader introduced.NET 6.0.

nobit2021 - August 02, 2022 @ 05:48

You can both enjoy top-notch games while alone guiding a professional team by attending the game retro games. You can choose your favorite team when you first become a coach. However, you do not have to be the coach of the team. This forces you to choose a team that is more passionate about the game.

mztd006 - August 13, 2022 @ 13:26

@srlcarlg

look at this script on tradingview.  Numbers Renko

it have same function but in more visually appealing way

clarkeadams37 - August 13, 2022 @ 13:32

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.
 

mztd006 - August 13, 2022 @ 13:32

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

 

srlcarlg - August 13, 2022 @ 18:29

@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.

thomasmarsden970 - August 30, 2022 @ 14:59

The volume of a candlestick can be calculated by subtracting the volume of the prior candlestick from the volume of the current candlestick.
Check UK Government’s New Visa Scheme For Elite Graduates
 

junealexis001 - September 12, 2022 @ 12:03

Great site i love it keep posting more!   https://fencingcincinnatioh.com

christopherhale68 - September 22, 2022 @ 17:31

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/

howyg1 - November 21, 2022 @ 21:55

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;
 

abhaysinh94 - November 24, 2022 @ 06:34

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

0