Tick Statistics
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Sharad_Gaikwad

//@version=5
indicator("Tick Statistics", overlay = true)
tab = table.new(position=position.top_right, columns=7, rows=200,frame_color = color.yellow, frame_width = 1)
msg(int row, int col, string msg_str, clr=color.blue) =>
    table.cell(table_id=tab, column=col, row=row, text=msg_str, text_color=clr)
    
t(val) => str.tostring(val)

get_tick_summary(_tick_arr, _up_arr, _down_arr, _nc_arr, _cmp_arr, _vol_arr) => 
    summary_ticks  = '========== Ticks  ==========\n'
    summary_volume = '========== Volume ==========\n'
    max_min =        '========== Max-Min =========\n'
    candle_summary = '====== Candle Summary ======\n'
    upp = 0, dnp = 0, ncp = 0
    upv = 0.0, dnv = 0.0, ncv = 0.0
    max_vol = 0.0, min_vol = 99999999999999.99, max_vol_price =0.0, min_vol_price = 0.0
    max_vol_tick = 0.0, min_vol_tick = 0.0
    max_price = 0.0, min_price = 99999999999.99, max_price_vol = 0.0, min_price_vol = 0.0
    max_price_tick = 0.0, min_price_tick = 0.0
    max_tick = 0.0, min_tick = 999999999999.99
    max_tick_tick_no = 0., min_tick_tick_no = 0.

    up_counter = 0, down_counter = 0
    succive_up = 0.0, succive_down = 0.0
    last_tick_price = 0.0, first_tick_price = 0.0
    up_str = ';', down_str = ';'
    if(array.size(_tick_arr) > 1)
        size = array.size(_tick_arr) - 1
        size_cmp = array.size(_cmp_arr) - 1
        vol_now = 0.0  
        // This identifies successive up and down tick but not working as expected
        // for i1 = 0 to size_cmp
        //     if(i1 < size_cmp)
        //         // if(array.get(_cmp_arr, i) < array.get(_cmp_arr, i+1))
        //         //     down_counter := down_counter + 1
        //         //     down_str := down_str + t(down_counter) +  ';'
        //         // else
        //         //     down_counter := 0
                    
        //         if(array.get(_cmp_arr, i1) > array.get(_cmp_arr, i1+1))
        //             up_counter := up_counter + 1
        //             up_str := up_str + t(up_counter) +  ';'
        //         else
        //             up_counter := 0

        //     if(i1 < size_cmp)
        //         if(array.get(_cmp_arr, i1) < array.get(_cmp_arr, i1+1))
        //             down_counter := down_counter + 1
        //             down_str := down_str + t(down_counter) +  ';'
        //         else
        //             down_counter := 0


        for i = 0 to size
            if(i == 0 )
                last_tick_price := array.get(_cmp_arr, i)
            
            first_tick_price := array.get(_cmp_arr, i)
                
            if(i <  size)
                vol_now := array.get(_vol_arr, i) - array.get(_vol_arr, i+1)
            else
                vol_now := array.get(_vol_arr, i)
                
            if(vol_now > max_vol)
                max_vol := vol_now
                max_vol_price := array.get(_cmp_arr, i)
                max_vol_tick := array.get(_tick_arr, i)
     
            if(vol_now < min_vol)
                min_vol :=  vol_now
                min_vol_price := array.get(_cmp_arr, i)
                min_vol_tick := array.get(_tick_arr, i)
    
            if(array.get(_cmp_arr, i)  > max_price)
                max_price := array.get(_cmp_arr, i)
                max_price_vol :=  vol_now
                max_price_tick := array.get(_tick_arr, i)
       
            if(array.get(_cmp_arr, i)  < min_price)
                min_price := array.get(_cmp_arr, i)
                min_price_vol := vol_now
                min_price_tick := array.get(_tick_arr, i)
            
            upp := upp + array.get(_up_arr, i)
            dnp := dnp + array.get(_down_arr, i)
            ncp := ncp + array.get(_nc_arr, i)
            
            if(i !=  size)
                upv := upv + (array.get(_up_arr, i) * (array.get(_vol_arr, i) - array.get(_vol_arr, i+1)))
                dnv := dnv + (array.get(_down_arr, i) * (array.get(_vol_arr, i) - array.get(_vol_arr, i+1)))
                ncv := ncv + (array.get(_nc_arr, i) * (array.get(_vol_arr, i) - array.get(_vol_arr, i+1)))
                
                tick_size = array.get(_cmp_arr, i) - array.get(_cmp_arr, i+1)
                max_tick_tick_no := math.abs(tick_size) > math.abs(max_tick) ? array.get(_tick_arr, i) : max_tick_tick_no
                max_tick := math.abs(tick_size) > math.abs(max_tick) ? tick_size : max_tick
                min_tick_tick_no := math.abs(tick_size) <  math.abs(min_tick)  ? array.get(_tick_arr, i) : min_tick_tick_no
                min_tick := math.abs(tick_size) <  math.abs(min_tick)  ? tick_size : min_tick
            if(i  == size)
                upv := upv + (array.get(_up_arr, i) * (array.get(_vol_arr, i) ))
                dnv := dnv + (array.get(_down_arr, i) * (array.get(_vol_arr, i)))
                ncv := ncv + (array.get(_nc_arr, i) * (array.get(_vol_arr, i) ))
                
                
    up_arr = str.split(up_str, ';')
    if(array.size(up_arr) > 1)
        for x = 0 to array.size(up_arr) - 1
            if(str.tonumber(array.get(up_arr, x)) > succive_up)
                succive_up := str.tonumber(array.get(up_arr, x))
    down_arr = str.split(down_str, ';')
    if(array.size(down_arr) > 1)
        for x1 = 0 to array.size(down_arr) - 1
            if(str.tonumber(array.get(up_arr, x1)) > succive_up)
                succive_up := str.tonumber(array.get(up_arr, x1))
    
    

    summary_ticks := summary_ticks + 'Total ticks     =  '+ t(upp+dnp+ncp) + '\n' +
               'Up ticks        =  '+t(upp)+'\n'+
               'Down ticks      =  '+t(dnp)+'\n'+
               'No chgang (NC)  =  '+t(ncp)+'\n' +
               'Biggest tick    =  '+t(max_tick)+ ' @ Tick no = '+t(max_tick_tick_no) +'\n'+
               'Smallest tick   =  '+t(min_tick)+ ' @ Tick no = '+t(min_tick_tick_no)
            //   'Succive Up      =  '+t(succive_up)+'\n'+
            //   'Succive Down    =  '+t(succive_down)
    summary_volume :=  '\n' + summary_volume + 
               'Total         = '+t(upv+dnv+ncv)+'\n'+
               'Up            = '+t(upv)+'\n'+
               'Down          = '+t(dnv)+'\n'+
               'No Change     = '+t(ncv)+'\n'+
               'Candle Vol    = '+t(volume)
               
    vol_state = upv > dnv ? 'Up' : upv < dnv  ? 'Down' : '---'
    price_state = last_tick_price > first_tick_price ? 'Up' : last_tick_price < first_tick_price ? 'Down' : '---'
    
    candle_summary := candle_summary +
         'Price  = '+ price_state +'\n' +
         'Volume = '+ vol_state +'\n'
    [summary_ticks + summary_volume+ '\n'+
         max_min  + 
         'Max Vol = ' + t(max_vol) + '  @ Price = ' + t(max_vol_price) + '  @ Tick no = ' + t(max_vol_tick) + '\n' +    
         'Min Vol = ' + t(min_vol) + '  @ Price = ' + t(min_vol_price) + '  @ Tick no = ' + t(min_vol_tick)  + '\n' + 
         'Max Price = ' + t(max_price) + '  @ Vol = ' + t(max_price_vol) + '  @ Tick no = ' + t(max_price_tick) + '\n' +   
         'Min Price = ' + t(min_price) + '  @ Vol = ' + t(min_price_vol) + '  @ Tick no = ' + t(min_price_tick) + '\n' +
         candle_summary, vol_state != price_state]
         

varip tick_arr = array.new<float>()
varip up_arr = array.new<int>()
varip down_arr = array.new<int>()
varip nc_arr = array.new<int>()
varip cmp_arr = array.new<float>()
varip vol_arr = array.new<float>()

varip prev_tick_price = float(na)
varip prev_tick_vol = float(na)
varip tick_no = int(na)

if(barstate.isnew)
    tick_no := 0
    array.clear(tick_arr), array.clear(up_arr), array.clear(down_arr)
    array.clear(nc_arr), array.clear(cmp_arr), array.clear(vol_arr)
    
tick_no := tick_no + 1    
upp = close > prev_tick_price ? 1 : 0
downp = close < prev_tick_price ? 1 : 0
ncp =  close == prev_tick_price ? 1 : 0

array.unshift(tick_arr, tick_no)
array.unshift(up_arr, upp)
array.unshift(down_arr, downp)
array.unshift(nc_arr, ncp)
array.unshift(cmp_arr, close)
array.unshift(vol_arr, volume)


//text_str = '' 
if(barstate.isconfirmed)
    text_str = "Data displaying tick by tick changes in price and volume\n\n"+'Tick\t|Typ\t|CMP\t|Vol\t\t|PC\t\t|VC'
    text_str1 = ''
    if(array.size(tick_arr) > 1)
        for i = 0 to array.size(tick_arr) - 1
            price_change = 0.0
            vol_change = 0.0
            if(i < array.size(tick_arr) - 1)
                price_change := array.get(cmp_arr, i) - array.get(cmp_arr, i+1)
                vol_change := array.get(vol_arr, i) - array.get(vol_arr, i+1)
    
            tick_type = array.get(up_arr, i) == 1 ? 'Up' : array.get(down_arr, i) == 1 ? 'Dn' : '--'
            data = t(array.get(tick_arr, i)) + '\t|'
                 + tick_type + '\t|'
                 + t(math.round(array.get(cmp_arr, i), 2)) + '\t|'
                 + t(math.round(array.get(vol_arr, i), 2)) + '\t|'
                 + t(math.round(price_change, 2)) + '\t|'
                 + t(math.round(vol_change, 2))
            if(str.length(text_str) + str.length(data) <= 4000)
                text_str := text_str + '\n' + data  //text_str1 + '\n'+ data
            // else
            //     text_str := text_str + '\n'+ data

        str = text_str // +'\n'+text_str1
        label.new(bar_index, low, yloc = yloc.belowbar, style = label.style_diamond, size = size.tiny, tooltip = str)
        [tick_summary, divergence] = get_tick_summary(tick_arr, up_arr, down_arr, nc_arr, cmp_arr, vol_arr)
        clr = divergence ? color.red : color.green
        label.new(bar_index, low, yloc = yloc.abovebar, style = label.style_diamond, size = size.tiny, tooltip = tick_summary, color = clr)

prev_tick_price := close
prev_tick_vol := volume

