Tick Volume Calcs: 100 / 10 = 15?

prosteel1 since: 04 Jul 2018;

  22 Feb 2021, 12:49
Tick Volume Calcs: 100 / 10 = 15?

Hi,

  When comparing the tick volume of time based bars like Minute1, Minute15 etc to the number of 1 tick bars contained within them they don't match. They also don't match to other Tick bars like Tick10 or Tick100. As a bonus the Tick 1 doesn't match the Tick10 or Tick100. I do see a linear correlation between Tick 10, Tick100 and Tick 300 though.

I'm guessing this is expected but I don't understand why a 1 Minute bar's Tick Volume wouldn't equal the number of 1 Tick bars within the open and close time of the 1 minute bar, or why a Tick10 bar would not contain 10% the number of bars of Tick1 within the same start and end time.

Thought I'd ask before making a robot to prove the mathematics doesn't work :)

I do see a reply to a post which suggests the definition is more plastic than static in price and volume moves: 

As an example, on a Hour1 chart of AUDUSD with UTC+2 0900 opentime had a tick volume of 6776 (Using IcMartkets 3.8). The number of Tick1 bars in this time was around 4834. the number of Tick10 bars was 345, the number of Tick100 bars was 35, the number of Tick300 bars was 12. 

PanagiotisCharalampous's avatar

PanagiotisCharalampous since: 13 Jan 2017;

  22 Feb 2021, 13:05

Hi prosteel1,

There is an explanation but better do the robot to make sure we are talking about the same thing :)

Best Regards,

Panagiotis 

Join us on Telegram

Head of Community Management at cTrader

prosteel1 since: 04 Jul 2018;

  22 Feb 2021, 13:26
RE:

PanagiotisCharalampous said:

Hi prosteel1,

There is an explanation but better do the robot to make sure we are talking about the same thing :)

Best Regards,

Panagiotis 

Join us on Telegram

Thanks mate, can you share the potential explanation so I can add it to the robot to check please?

Currently the Tick1 seems to be out of sync with Tick10 etc so will set it up for that.

PanagiotisCharalampous's avatar

PanagiotisCharalampous since: 13 Jan 2017;

  22 Feb 2021, 13:42

Hi prosteel1,

The explanation is that while for time based candles both bid and ask ticks are considered for Tick Volume, for tick based candles only bid ticks are considered. This is a necessary convention to avoid empty candles or tick volume that does not match the candle size.

Best Regards,

Panagiotis 

Join us on Telegram

Head of Community Management at cTrader

prosteel1 since: 04 Jul 2018;

  22 Feb 2021, 13:54
RE:

PanagiotisCharalampous said:

Hi prosteel1,

The explanation is that while for time based candles both bid and ask ticks are considered for Tick Volume, for tick based candles only bid ticks are considered. This is a necessary convention to avoid empty candles or tick volume that does not match the candle size.

Best Regards,

Panagiotis 

Join us on Telegram

Wow, Very interesting! And not at all what I expected, lets see how far down the rabbit hole goes :)

prosteel1 since: 04 Jul 2018;

  23 Feb 2021, 16:22

Here is a robot that counts the ticks in bars on various timeframes. It draws 1 minute bars on tick timeframes so the periods can be counted by dragging the crosshair tool.

It prints the number of counted ticks per bar and compares it to the TickVolume of the bar.

Example output:

The last Minute bar had it's first tick on 23/02/2021 2:17:00 PM, and it's last tick on 23/02/2021 2:17:57 PM for a difference of 51 ticks. The bar opened on 23/02/2021 2:17:00 PM and reports a volume of 71. 71 / 51 = 1.39

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 TickTest : Robot
    {
        [Parameter("Frame0", DefaultValue = "Tick1000")]
        public TimeFrame TF0 { get; set; }
        [Parameter("Frame1", DefaultValue = "Tick750")]
        public TimeFrame TF1 { get; set; }
        [Parameter("Frame2", DefaultValue = "Tick500")]
        public TimeFrame TF2 { get; set; }
        [Parameter("Frame3", DefaultValue = "Tick300")]
        public TimeFrame TF3 { get; set; }
        [Parameter("Frame4", DefaultValue = "Tick250")]
        public TimeFrame TF4 { get; set; }
        [Parameter("Frame5", DefaultValue = "Tick200")]
        public TimeFrame TF5 { get; set; }
        [Parameter("Frame6", DefaultValue = "Tick150")]
        public TimeFrame TF6 { get; set; }
        [Parameter("Frame7", DefaultValue = "Tick100")]
        public TimeFrame TF7 { get; set; }
        [Parameter("Frame8", DefaultValue = "Tick90")]
        public TimeFrame TF8 { get; set; }
        [Parameter("Frame9", DefaultValue = "Tick80")]
        public TimeFrame TF9 { get; set; }
        [Parameter("Frame10", DefaultValue = "Tick60")]
        public TimeFrame TF10 { get; set; }
        [Parameter("Frame11", DefaultValue = "Tick50")]
        public TimeFrame TF11 { get; set; }
        [Parameter("Frame12", DefaultValue = "Tick40")]
        public TimeFrame TF12 { get; set; }
        [Parameter("Frame13", DefaultValue = "Tick30")]
        public TimeFrame TF13 { get; set; }
        [Parameter("Frame14", DefaultValue = "Tick25")]
        public TimeFrame TF14 { get; set; }
        [Parameter("Frame15", DefaultValue = "Tick20")]
        public TimeFrame TF15 { get; set; }
        [Parameter("Frame16", DefaultValue = "Tick15")]
        public TimeFrame TF16 { get; set; }
        [Parameter("Frame17", DefaultValue = "Tick10")]
        public TimeFrame TF17 { get; set; }
        [Parameter("Frame18", DefaultValue = "Tick9")]
        public TimeFrame TF18 { get; set; }
        [Parameter("Frame19", DefaultValue = "Tick8")]
        public TimeFrame TF19 { get; set; }
        [Parameter("Frame20", DefaultValue = "Tick7")]
        public TimeFrame TF20 { get; set; }
        [Parameter("Frame21", DefaultValue = "Tick6")]
        public TimeFrame TF21 { get; set; }
        [Parameter("Frame22", DefaultValue = "Tick5")]
        public TimeFrame TF22 { get; set; }
        [Parameter("Frame23", DefaultValue = "Tick4")]
        public TimeFrame TF23 { get; set; }
        [Parameter("Frame24", DefaultValue = "Tick3")]
        public TimeFrame TF24 { get; set; }
        [Parameter("Frame25", DefaultValue = "Tick2")]
        public TimeFrame TF25 { get; set; }
        [Parameter("Frame26", DefaultValue = "Tick")]
        public TimeFrame TF26 { get; set; }
        [Parameter("Frame27", DefaultValue = "Minute")]
        public TimeFrame TF27 { get; set; }
        [Parameter("Frame28", DefaultValue = "Minute2")]
        public TimeFrame TF28 { get; set; }
        [Parameter("Frame29", DefaultValue = "Minute3")]
        public TimeFrame TF29 { get; set; }
        [Parameter("Frame30", DefaultValue = "Minute4")]
        public TimeFrame TF30 { get; set; }
        [Parameter("Frame31", DefaultValue = "Minute5")]
        public TimeFrame TF31 { get; set; }
        [Parameter("Frame32", DefaultValue = "Minute6")]
        public TimeFrame TF32 { get; set; }
        [Parameter("Frame33", DefaultValue = "Minute7")]
        public TimeFrame TF33 { get; set; }
        [Parameter("Frame34", DefaultValue = "Minute8")]
        public TimeFrame TF34 { get; set; }
        [Parameter("Frame35", DefaultValue = "Minute9")]
        public TimeFrame TF35 { get; set; }
        [Parameter("Frame36", DefaultValue = "Minute10")]
        public TimeFrame TF36 { get; set; }
        [Parameter("Frame37", DefaultValue = "Minute15")]
        public TimeFrame TF37 { get; set; }
        [Parameter("Frame38", DefaultValue = "Minute20")]
        public TimeFrame TF38 { get; set; }
        [Parameter("Frame39", DefaultValue = "Minute30")]
        public TimeFrame TF39 { get; set; }
        [Parameter("Frame40", DefaultValue = "Minute45")]
        public TimeFrame TF40 { get; set; }
        [Parameter("Frame41", DefaultValue = "Hour")]
        public TimeFrame TF41 { get; set; }
        [Parameter("Frame42", DefaultValue = "Hour2")]
        public TimeFrame TF42 { get; set; }
        [Parameter("Frame43", DefaultValue = "Hour3")]
        public TimeFrame TF43 { get; set; }
        [Parameter("Frame44", DefaultValue = "Hour4")]
        public TimeFrame TF44 { get; set; }
        [Parameter("Frame45", DefaultValue = "Hour6")]
        public TimeFrame TF45 { get; set; }
        [Parameter("Frame46", DefaultValue = "Hour8")]
        public TimeFrame TF46 { get; set; }
        [Parameter("Frame47", DefaultValue = "Daily")]
        public TimeFrame TF47 { get; set; }
        [Parameter("Frame48", DefaultValue = "Daily2")]
        public TimeFrame TF48 { get; set; }
        [Parameter("Frame49", DefaultValue = "Daily3")]
        public TimeFrame TF49 { get; set; }
        [Parameter("Frame50", DefaultValue = "Weekly")]
        public TimeFrame TF50 { get; set; }
        [Parameter("Frame51", DefaultValue = "Monthly")]
        public TimeFrame TF51 { get; set; }

        TimeFrame[] Frames = new TimeFrame[52];
        Boolean[] Framesbool = new Boolean[52];
        Bars[] series = new Bars[52];
        int[] serieslast = new int[52];

        protected override void OnStart()
        {
            WriteVariables();

            for (int i = 0; i < Frames.Length; i++)
            {
                if (Framesbool[i] == true)
                {
                    serieslast[i] = series[i].Count - 2;
                    Print(Frames[i] + ", Count = " + (series[i].Count - 2));
                }
            }
        }

        protected override void OnTick()
        {
            for (int i = 0; i < Frames.Length; i++)
            {
                if (Framesbool[i] == true && (series[i].Count - 2) > serieslast[i])
                {
                    int j;
                    int ii;
                    bool Notenoughdata = false;
                    if (i >= 27)
                    {
                        // Find the last tick of the bar
                        for (j = series[26].Count - 1; series[26].OpenTimes[j] > series[i].OpenTimes[series[i].Count - 1]; j--)
                        {
                            if (j == 1)
                                break;
                        }
                        // Find the first tick of the bar
                        for (ii = series[26].Count - 1; series[26].OpenTimes[ii] > series[i].OpenTimes[series[i].Count - 2]; ii--)
                        {
                            if (ii == 1)
                            {
                                Notenoughdata = true;
                                break;
                            }
                        }
                        if (Notenoughdata != true)
                        {
                            Print("The last " + Frames[i] + " bar had it's first tick on " + series[26].OpenTimes[ii + 1] + ", and it's last tick on " + series[26].OpenTimes[j] + " for a difference of " + (j - (ii + 1)) + " ticks. The bar opened on " + series[i].OpenTimes[series[i].Count - 2] + " and reports a volume of " + series[i].TickVolumes[series[i].Count - 2] + ". " + series[i].TickVolumes[series[i].Count - 2] + " / " + (j - (ii + 1)) + " = " + Math.Round((series[i].TickVolumes[series[i].Count - 2] / (j - (ii + 1))), 2));
                            // Draw rectangles of 1 Minute bars on the tick1 chart
                            if (i == 27)
                            {
                                var rect1 = Chart.DrawRectangle(Frames[i] + "-" + j + "-" + ii + 1, series[26].OpenTimes[ii + 1], series[i].LowPrices[series[i].Count - 2], series[26].OpenTimes[j], series[i].HighPrices[series[i].Count - 2], "Blue");
                                rect1.IsInteractive = true;
                            }
                        }
                    }
                    serieslast[i] = series[i].Count - 2;
                }
            }
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
        private void WriteVariables()
        {
            Frames[0] = TF0;
            Frames[1] = TF1;
            Frames[2] = TF2;
            Frames[3] = TF3;
            Frames[4] = TF4;
            Frames[5] = TF5;
            Frames[6] = TF6;
            Frames[7] = TF7;
            Frames[8] = TF8;
            Frames[9] = TF9;
            Frames[10] = TF10;
            Frames[11] = TF11;
            Frames[12] = TF12;
            Frames[13] = TF13;
            Frames[14] = TF14;
            Frames[15] = TF15;
            Frames[16] = TF16;
            Frames[17] = TF17;
            Frames[18] = TF18;
            Frames[19] = TF19;
            Frames[20] = TF20;
            Frames[21] = TF21;
            Frames[22] = TF22;
            Frames[23] = TF23;
            Frames[24] = TF24;
            Frames[25] = TF25;
            Frames[26] = TF26;
            Frames[27] = TF27;
            Frames[28] = TF28;
            Frames[29] = TF29;
            Frames[30] = TF30;
            Frames[31] = TF31;
            Frames[32] = TF32;
            Frames[33] = TF33;
            Frames[34] = TF34;
            Frames[35] = TF35;
            Frames[36] = TF36;
            Frames[37] = TF37;
            Frames[38] = TF38;
            Frames[39] = TF39;
            Frames[40] = TF40;
            Frames[41] = TF41;
            Frames[42] = TF42;
            Frames[43] = TF43;
            Frames[44] = TF44;
            Frames[45] = TF45;
            Frames[46] = TF46;
            Frames[47] = TF47;
            Frames[48] = TF48;
            Frames[49] = TF49;
            Frames[50] = TF50;
            Frames[51] = TF51;

            Framesbool[0] = true;
            Framesbool[1] = true;
            Framesbool[2] = true;
            Framesbool[3] = true;
            Framesbool[4] = true;
            Framesbool[5] = true;
            Framesbool[6] = true;
            Framesbool[7] = true;
            Framesbool[8] = true;
            Framesbool[9] = true;
            Framesbool[10] = true;
            Framesbool[11] = true;
            Framesbool[12] = true;
            Framesbool[13] = true;
            Framesbool[14] = true;
            Framesbool[15] = true;
            Framesbool[16] = true;
            Framesbool[17] = true;
            Framesbool[18] = true;
            Framesbool[19] = true;
            Framesbool[20] = true;
            Framesbool[21] = true;
            Framesbool[22] = true;
            Framesbool[23] = true;
            Framesbool[24] = true;
            Framesbool[25] = true;
            Framesbool[26] = true;
            Framesbool[27] = true;
            Framesbool[28] = true;
            Framesbool[29] = true;
            Framesbool[30] = true;
            Framesbool[31] = true;
            Framesbool[32] = true;
            Framesbool[33] = true;
            Framesbool[34] = true;
            Framesbool[35] = true;
            Framesbool[36] = true;
            Framesbool[37] = true;
            Framesbool[38] = true;
            Framesbool[39] = true;
            Framesbool[40] = true;
            Framesbool[41] = true;
            Framesbool[42] = true;
            Framesbool[43] = true;
            Framesbool[44] = true;
            Framesbool[45] = true;
            Framesbool[46] = true;
            Framesbool[47] = true;
            Framesbool[48] = true;
            Framesbool[49] = true;
            Framesbool[50] = true;
            Framesbool[51] = true;

            for (int i = 0; i < Frames.Length; i++)
            {
                if (Framesbool[i] == true)
                {
                    series[i] = MarketData.GetBars(Frames[i]);
                }
            }
        }
    }
}

prosteel1 since: 04 Jul 2018;

  24 Feb 2021, 14:05
RE:

PanagiotisCharalampous said:

Hi prosteel1,

The explanation is that while for time based candles both bid and ask ticks are considered for Tick Volume, for tick based candles only bid ticks are considered. This is a necessary convention to avoid empty candles or tick volume that does not match the candle size.

Best Regards,

Panagiotis 

Join us on Telegram

I haven't seen anything to suggest your explanation is not correct. Typically the time based candles have between 1.3 and 1.5 times the number of ticks in tick based candles. The difference could well be ask ticks.

The reason why I posted this is because I would like to be able to compare the number of ticks in tick based candles with the number of ticks in time based candles to be able to sort both time based and tick based candles in a sorted hierarchy based on ticks.

The above robot proves that the number of ticks in time based candles is not equal to the number of ticks in tick based candles within that time - the time based candles contain between 1.3 and 1.5 more ticks based on series[i].TickVolumes of time based candles compared to the number of ticks counted on tick based candles within the open and close times of the time based candles.

It would appear that the liquidity provider is including ask ticks in time based candles but not in tick candles.

I'm testing ways to compare both, but worth asking if this is correct in the first place as it was unexpected.

Further questions might be why can't we have ask ticks in the tick candles so the tick volume of tick candles matches the tick volume of time based candles? While I sort of understand why from a technical perspective (ask ticks might be superfluous), there is a disconnect between the two measurement methods that result in different tick volumes within the same time period.

PanagiotisCharalampous's avatar

PanagiotisCharalampous since: 13 Jan 2017;

  24 Feb 2021, 14:07

Hi prosteel1,

Since the convention is different, any comparison will not make sense. I will have to discuss this with the product team if they are willing to change the convention or if there is a reason that would not allow this to be changed.

Best Regards,

Panagiotis 

Join us on Telegram

Head of Community Management at cTrader

prosteel1 since: 04 Jul 2018;

  24 Feb 2021, 14:43
RE:

PanagiotisCharalampous said:

Hi prosteel1,

Since the convention is different, any comparison will not make sense. I will have to discuss this with the product team if they are willing to change the convention or if there is a reason that would not allow this to be changed.

Best Regards,

Panagiotis 

Join us on Telegram

The above code shows that it is possible to measure volume in a way that they can be compared. Perhaps another volume metric could be added to time based candles that matches with the tick candle volume within the open and close of the candle on that timeframe. And/Or the difference could be added to the tick based volume as another metric.

With a bit of work it might be possible to compare the volume on 1 minute candle with the number of ticks reported since that 1 minute candle opened, and that difference might be the number of ask ticks.

The ask ticks might be the key to comparing time based and tick based candles it seems.