Ice Cream Volume Profile [Visible range]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © TZack88

//@version=5
indicator("Ice Cream Volume Profile [Visible range]",overlay = true,max_bars_back = 2000)

type ice
    array<float> LOWS
    array<float> HIGH
    array<float> VOL
    array<float> SCR
    array<float> Levels
    array<float> Total
    array<float> Green
    array<float> Red
    array<chart.point> Top
    array<chart.point> LowTop
    array<polyline> Cone
    array<label> Labels
    color OFF



var ICE = ice.new(
     array.new<float>(),
     array.new<float>(),
     array.new<float>(),
     array.new<float>(),
     array.new<float>(10),
     array.new<float>(10,0.0),
     array.new<float>(10,0.0),
     array.new<float>(10,0.0),
     array.new<chart.point>(),
     array.new<chart.point>(),
     array.new<polyline>(9),
     array.new<label>(9),
     color.new(color.black,100)
     )

string Voldata   = input.string("Volume",title = "Volume Type",
     group = "CORE",
     options=["Volume","Points","Delta"],
     tooltip = "Choose Volume Type to Show in Boxes",inline = "C")

BullCol = input.color(color.rgb(225, 142, 10, 60),"",group = "CORE",inline = "C")
BearCol = input.color(color.rgb(8, 145, 99, 31),"",group = "CORE",inline = "C")

// chcck the Bull , Bear volume ratio
method VolCal(ice self) =>
    GreenV = array.new<float>()
    RedV = array.new<float>()
    Vtotal = array.new<float>()
    for i = 0 to self.SCR.size() -1
        if self.SCR.get(i) > open[i]
            GreenV.push(volume[i])

        else if self.SCR.get(i) < open[i]
            RedV.push(volume[i])

        Vtotal.push(volume[i])
    GreenRatio = math.round(GreenV.sum() / Vtotal.sum()* 100,2)
    RedRatio = math.round(RedV.sum() / Vtotal.sum()* 100,2)
    Out = GreenRatio > 30 ? color.rgb(10, 170, 16, 49) : RedRatio > 55 ? color.rgb(204, 15, 15, 35) : color.rgb(245, 221, 8, 48) 
    Out


// visable range data
if time > chart.left_visible_bar_time
    ICE.LOWS.push(low)
    ICE.HIGH.push(high)
    ICE.VOL.push(volume)
    ICE.SCR.push(close)


GenCol(i,L,M)=>
    color.from_gradient(i,L,M,BullCol,BearCol)



volATR(int len)=>
    math.min(ta.atr(len) * 0.3, close * (0.3/100)) [20] /2

ATR = volATR(30)


if barstate.islast
    var polyline Pol1 = na , polyline.delete(Pol1)
    var polyline Pol2 = na , polyline.delete(Pol2)
    var num = 0 
    var mean = 0
    Bartime = time - time[1]
    var TIME = time  + (Bartime * 5)
    int [] PNT       = array.new_int(10,0)

    // levels calculation
    TOP = ICE.HIGH.max() - (ATR* 20)
    Last = ICE.LOWS.min() 
    step =  (TOP - Last) / 8

    for i = 0  to 8 by 1
        Pos = TOP - step * i
        ICE.Levels.set(i,Pos)
        
    // check if the bar is within a level and add to the points <array> counter    
    for i = 0 to ICE.SCR.size() -1
        for x = 0 to ICE.Levels.size() -2
            if ICE.SCR.get(i) < ICE.Levels.get(x) 
                 and 
                 ICE.SCR.get(i) > ICE.Levels.get(x+1)
                
                PNT.set(x,PNT.get(x)+1)
                ICE.Total.set(x,ICE.Total.get(x) + volume[i])
                // check Bull , Bear volume within the range
                if ICE.SCR.get(i) < open[i]   
                    ICE.Green.set(x,ICE.Green.get(x) + volume[i])

                if ICE.SCR.get(i) > open[i]
                    ICE.Red.set(x,ICE.Red.get(x) + volume[i])

                break
           
    // levels build                 
    for i = 1  to 8 by 1
        Poly = array.new<chart.point>()
        polyline.delete(ICE.Cone.get(i))
        Start = TIME + (Bartime * (4 + num) ) 
        END = TIME + (Bartime * (56 - num))

        Poly.push(chart.point.from_time( Start , ICE.Levels.get(i)))
        Poly.push(chart.point.from_time( END , ICE.Levels.get(i)))
        Poly.push(chart.point.from_time( END , ICE.Levels.get(i-1)))
        Poly.push(chart.point.from_time( Start , ICE.Levels.get(i-1)))
        Value   = Voldata == "Points" ? PNT.get(i) : ICE.Total.get(i)
        Min     = Voldata == "Points" ? PNT.min() : ICE.Total.min()
        MAX     = Voldata == "Points" ? PNT.max() : ICE.Total.max()

        ColCond = color.new(GenCol(i == 0 ?  Value : Voldata == "Points" ? PNT.get(i-1):
         Voldata == "Volume" or  Voldata == "Delta"  ? ICE.Total.get(i-1) : Value ,Min,MAX), 80)

        ICE.Cone.set(i,polyline.new(Poly,false,true,xloc.bar_time,color.new(#484749, 80),fill_color = ColCond))

        // label text position 
        mean :=  ((TIME + (Bartime * (56 - num)))  + (TIME + (Bartime * (4 + num)))) /2
        num +=3
    
     // data labels
    str = ""
    for i = 0  to ICE.Levels.size() -2
        label.delete(ICE.Labels.get(i))
        Delta = ICE.Green.get(i) - ICE.Red.get(i)
        if ICE.Total.get(i) > 0
            str := switch Voldata
                "Volume" => str.tostring(ICE.Total.get(i),format.volume)
                "Points" => str.tostring(PNT.get(i))
                "Delta" => str.tostring(Delta,format.volume)
             
        if i < 8
            ICE.Labels.set(i,label.new(mean,((ICE.Levels.get(i) + ICE.Levels.get(i+1)) /2)  ,str,style = label.style_label_center,color = ICE.OFF , textcolor = Voldata == "Delta" and Delta < 0 ? color.red : color.rgb(255, 255, 255, 31),xloc = xloc.bar_time))


    // Mango and Watermelon top
    ICE.Top.push(chart.point.from_time(TIME , ICE.HIGH.max()- (ATR* 20)))
    ICE.Top.push(chart.point.from_time(TIME + (Bartime * 30) , ICE.HIGH.max() +(ATR* 8) ))
    ICE.Top.push(chart.point.from_time(TIME + (Bartime * 60) , ICE.HIGH.max()- (ATR* 20)))

    ICE.LowTop.push(chart.point.from_time(TIME , ICE.HIGH.max() - (ATR* 20)))
    ICE.LowTop.push(chart.point.from_time(TIME + (Bartime * 30) , ICE.HIGH.max() -(ATR* 8) ))
    ICE.LowTop.push(chart.point.from_time(TIME + (Bartime * 60) , ICE.HIGH.max() - (ATR* 20)))
    Pol1:=polyline.new(ICE.Top,true,false,xloc.bar_time,color.new(#2d2d2e, 29),fill_color = ICE.VolCal())
    Pol2:=polyline.new(ICE.LowTop,true,false,xloc.bar_time,color.new(#333434, 50),fill_color = color.rgb(180, 180, 187, 54))


