Educational LTF -> HTF volume delta
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © fikira
//@version=5
indicator("Educational LTF -> HTF volume delta", overlay=false, format=format.volume)

// This script is part of a collection of educational scripts
// If you want to return to the open source INDEX page, click the link in the comments:
// -> https://www.tradingview.com/script/TUeC9XDq-Education-INDEX/

// This script shows 1 of several technique to gather volume delta 
// When there is an  up-candle  ('green') candle, the volume from that candle is added to an  'up-volume'  variable
// When there is an down-candle ( 'red' ) candle, the volume from that candle is added to an 'down-volume' variable

//  –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
// | [ We are going to do this with lower timeframe candles data against 1 higher timeframe candle ] |
//  –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

// first, we set the lower timeframe:
i_ltf = input.timeframe('1', 'lower timeframe') // -> If the current chart timeframe is set to 60 minutes, then there will be 60 1-minute candles where we can calculate our up/down volume with
i_bar = input.string   ('stack', 'Appearance', options=['stack', 'split', 'sell V -> column / buy V -> hist', 'buy V -> column / sell V -> hist'])
i_len = input.int      (20 , 'length', tooltip='length of ema when \'split\'')



// Next, we save 2 kinds of data of lower tf in a 2 variables

// This will create 2 array's
// • array p which contains   math.sign(close - open)   of each ltf bar
// • array v which contains          volume             of each ltf bar

[p, v] = request.security_lower_tf(syminfo.tickerid, i_ltf, [math.sign(close - open), volume])

// What happens with that 'math.sign' thingy ?

// if data is below 0, it will return -1
// if data is above 0, it will return  1
//          otherwise  it will return  0

// So, in this care, we can easily check 'red'/'green' bars
// when 'open - close' < 0 ('red'   bar) -> math.sign of this data will return -1
// when 'open - close' > 0 ('green' bar) -> math.sign of this data will return  1
//                                          otherwise           it will return  0

// Let's do something with that data

upV = 0. 
ntV = 0. 
dnV = 0. 

// for each [index, data] in the array p 
for [i, n] in p 
    // whatever fits first
    switch n 
        -1 => 
            dnV := dnV + array.get(v, i) // when 'red'     bar -> add 'volume' of that bar to 'dnV'
        1 => 
            upV := upV + array.get(v, i) // when 'green'   bar -> add 'volume' of that bar to 'upV'
        => 
            ntV := ntV + array.get(v, i) // when 'neutral' bar -> add 'volume' of that bar to 'ntV'

tt = ntV + dnV + upV // = total

// -> plotting
//plot(tt  > 0 ? ntV             : na, style=plot.style_columns, color=color.new(color.blue,  0), title='Neutral Volume')
//plot(tt  > 0 ? ntV + dnV       : na, style=plot.style_columns, color=color.new(color.red ,  0), title='Sell Volume'   )
//plot(tt  > 0 ? ntV + dnV + upV : na, style=plot.style_columns, color=color.new(color.lime, 70), title='Buy Volume'    )
//plot(volume                        , style=plot.style_columns, color=color.new(color.red , 80), title='Total Volume'  )


//  –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
// |                                [ This can be written shorter ]                                  |
//  –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

// Since the math.sign() can only have 3 possible values (-1, 0, 1), we can use this to direct immedeatily to a position in an array

a = array.from(0., 0., 0.)

// for each data (sign) in array 
// • if -1 -> add volume at array index 0 (-1 + 1)
// • if  0 -> add volume at array index 1 ( 0 + 1)
// • if  1 -> add volume at array index 2 ( 1 + 1)

for [i, n] in p
    array.set(a, math.round(n + 1), array.get(a, math.round(n + 1)) + array.get(v, i))

gDn = array.get(a, 0), gNt = array.get(a, 1), gUp = array.get(a, 2), tot = gDn + gNt + gUp

sUp = ta.ema(gUp, i_len), plot( sUp, color=color.lime)
sDn = ta.ema(gDn, i_len), plot(-sDn, color=color.red )


// -> plotting
plot(i_bar !=           'split'                    ? tot > 0 ? gNt : na        : na, style=plot.style_columns  , color=color.new(color.blue  ,  0), title='Neutral Volume')

plot(i_bar == 'stack'                            and tot > 0 ? gNt + gDn       : na, style=plot.style_columns  , color=color.new(color.red   ,  0), title='Sell Volume'   )
plot(i_bar == 'stack'                            and tot > 0 ? gNt + gDn + gUp : na, style=plot.style_columns  , color=color.new(color.lime  , 70), title='Buy Volume'    )

plot(i_bar == 'buy V -> column / sell V -> hist' and tot > 0 ?             gUp : na, style=plot.style_columns  , color=color.new(color.lime  , 60), title='Buy Volume'    )
plot(i_bar == 'buy V -> column / sell V -> hist' and tot > 0 ?       gDn       : na, style=plot.style_histogram, color=color.new(color.red   ,  0), title='Sell Volume' , linewidth=5)

plot(i_bar == 'sell V -> column / buy V -> hist' and tot > 0 ?       gDn       : na, style=plot.style_columns  , color=color.new(color.red   , 60), title='Sell Volume'   )
plot(i_bar == 'sell V -> column / buy V -> hist' and tot > 0 ?             gUp : na, style=plot.style_histogram, color=color.new(color.lime  ,  0), title='Buy Volume'  , linewidth=5)

plot(i_bar ==           'split'                  and tot > 0 ?          volume : na, style=plot.style_circles  , color=
                                         gUp > gDn ? color.new(color.lime, 60) : color.new(color.red, 60)                                         , title='Total Volume', linewidth=2)
plot(i_bar ==           'split'                  and tot > 0 ?      -gDn       : na, style=plot.style_columns  , color=color.new(color.red   , 50), title='Sell Volume'   )
plot(i_bar ==           'split'                  and tot > 0 ?             gUp : na, style=plot.style_columns  , color=color.new(color.lime  , 50), title='Buy Volume'  , linewidth=5)

plot(i_bar !=           'split'                              ?          volume : na, style=plot.style_columns, color= i_bar == 'stack'  ?  color.new(color.red , 80)  :  color.new(color.red , 90), title='Total Volume')


//  –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
// |                [ Actually, this can be written even shorter (~Sharad_Gaikwad) ]                 |
//  –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

[nV, sV, bV, tV] = request.security_lower_tf(syminfo.tickerid, '1', [close == open ? volume : 0, close < open ? volume : 0, close > open ? volume : 0, volume])
//plot(array.sum(nV)                                  , style=plot.style_columns, color=color.new(color.lime, 50), title='Buy Volume'  )
//plot(array.sum(nV) + array.sum(sV)                  , style=plot.style_columns, color=color.new(color.red , 50), title='Sell Volume' ) 
//plot(array.sum(nV) + array.sum(sV) + array.sum(bV)  , style=plot.style_columns, color=color.new(color.red , 50), title='Sell Volume' ) 
//plot(array.sum(tV)                                  , style=plot.style_columns, color=color.new(color.aqua, 50), title='Total Volume')


//  –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
// |                                        [ Do mind: ]                                             |
//  –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

// A maximum of 100,000 intrabars can be accessed by a call. 
// This means not every bar will display ltf data, here this can be easily seen by columns which are only red, there only volume of current tf is shown

//  –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
// |                                 [ Labels buy/sell Volume ]                                      |
//  –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

label.new(bar_index, tot, text= str.tostring(gUp, format.volume), style=label.style_label_down, textcolor=color.green, color=color.new(color.black, 100), size=size.small)
label.new(bar_index,  0 , text= str.tostring(gDn, format.volume), style=label.style_label_up  , textcolor=color.red  , color=color.new(color.black, 100), size=size.small)
