Time Profile [QuantVue]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © QuantVue

//@version=5
indicator("Time Profile [QuantVue]", overlay = true, max_bars_back = 4999)

/////////////
// inputs //
lowerTF             = input.timeframe('15', 'Lower Time Frame Data')
showTimeProfile     = input.bool(true, 'Show Time Profile')
maxColor            = input.color(color.new(color.lime,70), 'Highest', inline = '2')
mincolor            = input.color(color.new(color.yellow,70), 'Lowest', inline = '2')
showVPOC            = input.bool(true, 'Show Volume POC', inline = '3')
pocColor            = input.color(color.fuchsia, ' ', inline = '3', tooltip = 'The close of the highest volume lower time frame bar')
showTime            = input.bool(true, 'Time POC History', inline = '4')
tpocCol             = input.color(color.yellow, ' ', inline = '4', tooltip = 'Plots where the most smaller time frame closes occured for that bar')
double              = input.bool(true, 'Volume and Time POC Aligned', inline = '5')
doubleCol           = input.color(color.lime, ' ', inline = '5', tooltip = 'Highlight when the volume and time point of controls are aligned on the real time bar')


////////////////
// variables //
timeArr     = array.new<int>()
box box1    = na, box box2 = na, box box3 = na, box box4 = na, box box5 = na 
box box6    = na, box box7 = na, box box8 = na, box box9 = na, box box10 = na

up      = close > close[1]
down    = close < close[1]

////////////////
// functions //
ltfVolData() =>
    vol = not na(volume) ? volume : 0
    [close, vol]

proColor(bc) =>
    color.from_gradient(bc, timeArr.get(9), timeArr.get(0), mincolor, maxColor)

///////////////
// ltf Data //
[ltfClose, ltfvol] = request.security_lower_tf(syminfo.ticker, lowerTF, ltfVolData())

/////////////////
// volume POC //
maxVol      = ltfClose.size() > 0 ? ltfvol.max() : na
idxofMax    = ltfClose.size() > 0 ? ltfvol.indexof(maxVol) : na
maxPrice    = ltfClose.size() > 0 ? ltfClose.get(idxofMax) : na

//////////////////
// Time Blocks //
blocks  = (high - low) / 10
block1  = low + (blocks * 1)
block2  = low + (blocks * 2)
block3  = low + (blocks * 3)
block4  = low + (blocks * 4)
block5  = low + (blocks * 5)
block6  = low + (blocks * 6)
block7  = low + (blocks * 7)
block8  = low + (blocks * 8)
block9  = low + (blocks * 9)
block10 = low + (blocks * 10)

///////////////////
// Block Counts //
b1C  = 0
b2C  = 0
b3C  = 0
b4C  = 0
b5C  = 0
b6C  = 0
b7C  = 0
b8C  = 0
b9C  = 0
b10C = 0

///////////////////////
// Count ltf Closes //
for i = 0 to ltfClose.size() > 0 ? ltfClose.size() - 1 : na
    lastClose = ltfClose.get(i)
    if lastClose < block1
        b1C += 1
    else if lastClose > block1 and lastClose <= block2
        b2C += 1
    else if lastClose > block2 and lastClose <= block3
        b3C += 1
    else if lastClose > block3 and lastClose <= block4
        b4C += 1
    else if lastClose > block4 and lastClose <= block5
        b5C += 1
    else if lastClose > block5 and lastClose <= block6
        b6C += 1
    else if lastClose > block6 and lastClose <= block7
        b7C += 1
    else if lastClose > block7 and lastClose <= block8
        b8C += 1
    else if lastClose > block8 and lastClose <= block9
        b9C += 1
    else if lastClose > block9 and lastClose <= block10
        b10C += 1

///////////////////
// Store Counts //
timeArr.push(b1C)
timeArr.push(b2C)
timeArr.push(b3C)
timeArr.push(b4C)
timeArr.push(b5C)
timeArr.push(b6C)
timeArr.push(b7C)
timeArr.push(b8C)
timeArr.push(b9C)
timeArr.push(b10C)

////////////////////
// Highest Count //
timeMax = timeArr.max()
idxTime = timeArr.indexof(timeMax)
timeArr.sort(order.descending)

///////////////////////
// Color Background //
bg1  = proColor(b1C)
bg2  = proColor(b2C)
bg3  = proColor(b3C)
bg4  = proColor(b4C)
bg5  = proColor(b5C)
bg6  = proColor(b6C)
bg7  = proColor(b7C)
bg8  = proColor(b8C)
bg9  = proColor(b9C)
bg10 = proColor(b10C)

///////////////////////////////////
// Placement of Historical Plot //
priceBlock = idxTime == 0 ? block1 : idxTime == 1 ? block2 : idxTime == 2 ? block3 : idxTime == 3 ? block4 : 
 idxTime == 4 ? block5 : idxTime == 5 ? block6 : idxTime == 6 ? block7 : idxTime == 7 ? block8 : 
 idxTime == 8 ? block9 : block10

blockPos = priceBlock == block1 ? (low + block1) / 2 : priceBlock == block2 ? (block1 + block2) / 2 : priceBlock == block3 ? (block2 + block3) / 2  : 
 priceBlock == block4 ? (block3 + block4) / 2  : priceBlock == block5 ? (block4 + block5) / 2  : priceBlock == block6 ? (block5 + block6) / 2  : 
 priceBlock == block7 ? (block6 + block7) / 2  : priceBlock == block8 ? (block7 + block8) / 2  : priceBlock == block9 ? (block8 + block9) / 2 : (block9 + high) / 2

////////////
// Plots //
if barstate.islast and showTimeProfile
    (box1[1]).delete(), (box2[1]).delete(), (box3[1]).delete(), (box4[1]).delete(), (box5[1]).delete()
    (box6[1]).delete(), (box7[1]).delete(), (box8[1]).delete(), (box9[1]).delete(), (box10[1]).delete()
    box1 := box.new(bar_index, block1, bar_index + b1C, low, bgcolor = bg1, border_color = color.black)
    box2 := box.new(bar_index, block2, bar_index + b2C, block1, bgcolor = bg2, border_color = color.black)
    box3 := box.new(bar_index, block3, bar_index + b3C, block2, bgcolor = bg3, border_color = color.black)
    box4 := box.new(bar_index, block4, bar_index + b4C, block3, bgcolor = bg4, border_color = color.black)
    box5 := box.new(bar_index, block5, bar_index + b5C, block4, bgcolor = bg5, border_color = color.black)
    box6 := box.new(bar_index, block6, bar_index + b6C, block5, bgcolor = bg6, border_color = color.black)
    box7 := box.new(bar_index, block7, bar_index + b7C, block6, bgcolor = bg7, border_color = color.black)
    box8 := box.new(bar_index, block8, bar_index + b8C, block7, bgcolor = bg8, border_color = color.black)
    box9 := box.new(bar_index, block9, bar_index + b9C, block8, bgcolor = bg9, border_color = color.black)
    box10 := box.new(bar_index, block10, bar_index + b10C, block9, bgcolor = bg10, border_color = color.black)


plotshape(showVPOC ? maxPrice : na, 'vpoc', shape.circle, location.absolute, pocColor, size = size.tiny)
plotchar(showTime and barstate.ishistory ? blockPos : na, 'Time', '-', location.absolute, tpocCol, size = size.small)

if maxPrice > box1.get_bottom() and maxPrice < box1.get_top() and b1C == timeMax and double
    box1.set_bgcolor(doubleCol)
    alert('VPOC & TPOC Aligned', alert.freq_once_per_bar_close)
else if maxPrice > box2.get_bottom() and maxPrice < box2.get_top() and b2C == timeMax and double
    box2.set_bgcolor(doubleCol)
    alert('VPOC & TPOC Aligned', alert.freq_once_per_bar_close)
else if maxPrice > box3.get_bottom() and maxPrice < box3.get_top() and b3C == timeMax and double
    box3.set_bgcolor(doubleCol)
    alert('VPOC & TPOC Aligned', alert.freq_once_per_bar_close)
else if maxPrice > box4.get_bottom() and maxPrice < box4.get_top() and b4C == timeMax and double
    box4.set_bgcolor(doubleCol)
    alert('VPOC & TPOC Aligned', alert.freq_once_per_bar_close)
else if maxPrice > box5.get_bottom() and maxPrice < box5.get_top() and b5C == timeMax and double
    box5.set_bgcolor(doubleCol)
    alert('VPOC & TPOC Aligned', alert.freq_once_per_bar_close)
else if maxPrice > box6.get_bottom() and maxPrice < box6.get_top() and b6C == timeMax and double
    box6.set_bgcolor(doubleCol)
    alert('VPOC & TPOC Aligned', alert.freq_once_per_bar_close)
else if maxPrice > box7.get_bottom() and maxPrice < box7.get_top() and b7C == timeMax and double
    box7.set_bgcolor(doubleCol)
    alert('VPOC & TPOC Aligned', alert.freq_once_per_bar_close)
else if maxPrice > box8.get_bottom() and maxPrice < box8.get_top() and b8C == timeMax and double
    box8.set_bgcolor(doubleCol)
    alert('VPOC & TPOC Aligned', alert.freq_once_per_bar_close)
else if maxPrice > box9.get_bottom() and maxPrice < box9.get_top() and b9C == timeMax and double
    box9.set_bgcolor(doubleCol)
    alert('VPOC & TPOC Aligned', alert.freq_once_per_bar_close)
else if maxPrice > box10.get_bottom() and maxPrice < box10.get_top() and b10C == timeMax and double
    box10.set_bgcolor(doubleCol)
    alert('VPOC & TPOC Aligned', alert.freq_once_per_bar_close)
