Indicator · Pine Script v5 · On the chart

Quartile Volume, Volume Aggregation, US Range Bars, Gaps

by regalouisei· code credited to KioseffTrading

This indicator provides four selectable analytical datasets directly on the price chart: quartile volume analysis, volume aggregation bars, US range bars, and gap tracking.

View on GitHub

Repaints

GitHub stars2on the repository
Pine versionv5runs as is
Lines of code1,637
Settings39inputs
LicenceNone statedfile: MPL-2.0
Last update8 months ago25 Feb 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

1,637 lines of Pine Script v5 from pinescript/editors_picks/quartile-vol-vol-aggregation-range-us-bars-gaps-kioseff.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

quartile-vol-vol-aggregation-range-us-bars-gaps-kioseff.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © KioseffTrading

//@version=5
indicator("(Quartile Volume; Volume Aggregation; US Range Bars; Gaps) [Kioseff Trading]", overlay          = true, 
                                                                                          max_labels_count = 500 ,
                                                                                          max_boxes_count  = 500 ,
                                                                                          max_lines_count  = 500 , 
                                                                                          max_bars_back    = 500
                                                                                          )

//  ________________________________________________
// |                                               |  
// |       ---------------------------------       | 
// |      | K̲ i̲ o̲ s̲ e̲ f̲ f̲     T̲ r̲ a̲ d̲ i̲ n̲ g |      | 
// |      |                                 |      |  
// |      | ƃ u ᴉ p ɐ ɹ ꓕ     ⅎ ⅎ ǝ s o ᴉ ꓘ |      |  
// |       --------------------------------        |  
// |                                               | 
// |_______________________________________________|

// _______________________________________________________
//
// Inputs
// _______________________________________________________  


//                                                                     => Range US Params <=
 
show                    = input.string(defval = "Quartile Volume", title = "Dataset", options = ["Range US", "Volume Aggregation", "Gaps", "Quartile Volume"]                                                                      )
fast                    = input.bool  (defval = false      , title = "Improve Loading Time?" , tooltip = "Selecting This Box Improves Load Times; However, Data More Than 7,500 Bars Old Will Not be Calculated. This Setting Does Not Improve Initial Compilation Time.")                  
tra                     = input.string(defval = "Auto"    , title = "Auto Range US Candles? Or User-Defined?"        , group = "Range US",  options = ["Auto", "Custom"]                                                           )
rev                     = input.float (defval = 22        , title = "Reverse Candle Price Move"                      , group = "Range US", minval = 0.0000000001                                                                   )
tre                     = input.float (defval = 44        , title = "Trend Candle Price Move"                        , group = "Range US", minval = 0.0000000001                                                                   )
ranShow                 = input.bool  (defval = false     , title = "Segment Range US Bars By Date?"                 , group = "Range US"                                                                                          )
levShow                 = input.bool  (defval = true      , title = "Show Trend/Reverse Levels?"                     , group = "Range US"                                                                                          )
warn1                   = input.bool  (defval = true      , title = "Show Warning?"                                  , group = "Range US"                                                                                          )
sz                      = input.string(defval = "Tiny"    , title = "Box Text Size (Auto Increases Chart Lag)"       , group = "Range US", tooltip = "Box Text Size for Range US Candles.'Auto' Size May Cause Chart Lag"          ,      
                                                                                                                     options = ["Auto", "Tiny", "Small", "Normal", "Large", "Huge"]                                                )
treShow                 = input.int(defval= 7            , title = "Number of Congestion Areas to Show (0 = None)"   , group = "Range US",  minval = 0                                                                             )     
move                    = input.bool(defval = true       , title = "Move Current Range US Bar to Levels Section?"    , group = "Range US")
//                                                                 => Volume Aggregation Params <=

tra1                     = input.string(defval = "Auto"   , title = "Auto Volume Aggregation Candles? Or User-Defined?", group = "Volume Aggregation",  options = ["Auto", "Custom"]                                               )
volInt                  = input.int   (defval = 1000000   , title = "Required Volume", step = 10000                  , group = "Volume Aggregation"                                                                                )
vShow                   = input.bool  (defval = false     , title = "Segment Vol. Aggregation Bars By Date?"         , group = "Volume Aggregation"                                                                                )
sz1                     = input.string(defval = "Tiny"    , title = "Box Text Size (Auto Increases Chart Lag)"       , group = "Volume Aggregation", tooltip = "Box Text Size for Range US Candles.'Auto' Size May Cause Chart Lag",      
                                                                                                                       options = ["Auto", "Tiny", "Small", "Normal", "Large", "Huge"]                                              )
showAl                  = input.bool  (defval = true      , title = "Show Largest Increases and Decreases?"          , group = "Volume Aggregation"                                                                                )
showUp                  = input.int   (defval = 15        , title = "Number of Largest Volume Agg. Increases to Show", group = "Volume Aggregation", minval = 1,maxval = 20                                                        )
showDn                  = input.int   (defval = 15        , title = "Number of Largest Volume Agg. Decreases to Show", group = "Volume Aggregation", minval = 1,maxval = 20                                                        )
warn                    = input.bool  (defval = true      , title = "Show Warning?"                                  , group = "Volume Aggregation"                                                                                )
//                                                                       => Gaps Params <=

perG                    = input.float (defval = 0         , title = "Percentage Difference For Gap to Appear"        , group = "Gaps", step = 0.1, minval = 0                                                                      ) /100
old                     = input.float (defval = -1        , title = "Hide Gaps When Price Deviates by Percentage"    , group = "Gaps", minval = -1, tooltip = "Configuring This Setting to “-1” Will Keep All Gaps on the Chart. Configuring This Setting at or Above “0” Will Hide Gap Boxes if Price Moves the Percentage Amount Away From the Box. The “Percentage Amount” Is the Number in Defined for This Setting.") / 100
del                     = input.bool  (defval = false     , title = "Delete Filled Gaps?"                            , group = "Gaps"                                                                                              )
vis                     = input.bool  (defval = false     , title = "Visualize Gaps?"                                , group = "Gaps"                                                                                              )
rec                     = input.int   (defval = 5         , title = "Recent Unfilled Gaps to Show (Table)"           , group = "Gaps", minval = 0                                                                                  )

//                                                                   => Quartile Volume Params <=

colE                    = input.color (defval = color.red , title = "Low Volume Quartile Volume Color" ,inline = "1" , group = "Quartile Volume"                                                                                   )
colE1                   = input.color (defval = color.lime, title = "High Volume Quartile Volume Color",inline = "1" , group = "Quartile Volume"                                                                                   )
pCalculation            = input.int   (defval = 10        , title = "% Gain / Loss After 'n' Bars for Exceeded 90th Percentile" , group = "Quartile Volume" , minval = 2                                                           )
log                     = input.bool  (defval = true      , title = "Use Log Returns?"                               , group = "Quartile Volume"                                                                                   )
la                      = input.bool  (defval = false     , title = "Show Quartile on Bar?"                          , group = "Quartile Volume"                                                                                   )
quar                    = input.bool  (defval = false     , title = "Color Bars by Volume Quartiles"                 , group = "Quartile Volume"                                                                                   )
c1                      = input.color (defval = #a5d6a7   , title = "First Quartile Color"                           , group = "Quartile Volume"                                                                                   )
c2                      = input.color (defval = #81c784   , title = "Second Quartile Color"                          , group = "Quartile Volume"                                                                                   )
c3                      = input.color (defval = #66bb6a   , title = "Third Quartile Color"                           , group = "Quartile Volume"                                                                                   )
c4                      = input.color (defval = #388e3c   , title = "90th Percentile"                                , group = "Quartile Volume"                                                                                   )
c5                      = input.color (defval = #1b5e20   , title = "Fourth Quartile Color"                          , group = "Quartile Volume"                                                                                   )
showIns                 = input.bool  (defval = true      , title = "Show Instructions?"                             , group = "Quartile Volume"                                                                                   )
anch                    = input.bool  (defval = true      , title = "Show Anchored VWAP"                             , group = "Quartile Volume", tooltip = "Adjust Start and End Times Below to Show Anchored VWAP - Drag & Drop the Time Bars On the Chart For Quick Configuration"  )
s                       = input.time  (defval = timestamp("20 Jul 1872 00:00 +0300"), title = "Anchored VWAP Start"  , group = "Quartile Volume"                                                                                   )
e                       = input.time  (defval = timestamp("20 Jul 2023 00:00 +0300"), title = "Anchored VWAP End"    , group = "Quartile Volume"                                                                                   )


// _______________________________________________________
//
// Prerequisite Calculations
// _______________________________________________________  


var color    colCond               = color.yellow
var color    finCol                = na
var float [] xz                    = array.new_float()
var float [] vol                   = array.new_float()

lin() => 

    array.push(xz, close)
    
    if array.size(xz) > 50
        array.shift(xz)
    
    X = array.sum(xz) / array.size(xz) - 
         (ta.linreg(close, array.size(xz), 0) - 
             ta.linreg(close, array.size(xz), 1)) * 
                 math.floor(array.size(xz) / 2) + 0.5 * 
                     (ta.linreg(close, array.size(xz), 0) - 
                         ta.linreg(close, array.size(xz), 1))        
    
    Y  = (array.sum(xz) / array.size(xz) - 
         (ta.linreg(close, array.size(xz), 0) - 
             ta.linreg(close, array.size(xz), 1)) * 
                 math.floor(array.size(xz) / 2))  + 
                     (ta.linreg(close, array.size(xz), 0) - 
                         ta.linreg(close, array.size(xz), 1)) * 
                             (array.size(xz) - 1)
    
    
    float stDev = ta.stdev(X, array.size(xz) > 0 ? array.size(xz) : 1) * 2

    
    [X, Y, stDev]
    
[X, Y, stDev]                               = lin()
atr                                         = ta.atr(14)
tvsVol                                      = request.security(syminfo.ticker + "_SHORT_VOLUME", "D", close, ignore_invalid_symbol = true)
var int loopCount                           = 0

start() => 
    s <= e ? time >= s and time <= e: time <= s and time >= e


var int [] tim = array.new_int(2), var int timFin = 0

if barstate.isfirst
    
    array.set(tim, 0, 
         math.round(timestamp(year, month, dayofmonth, hour, minute, second)))

if bar_index == 1
    
    array.set(tim, 1, 
         math.round(timestamp(year, month, dayofmonth, hour, minute, second)))
    
    timFin := array.get(tim, 1) - array.get(tim, 0)


bool loadFast = switch fast
    
    false => bar_index > -1
    true  => last_bar_index - bar_index <= 7500

// _______________________________________________________
//
// Range US Bars
// _______________________________________________________  

[lowClose, lowHigh, lowLow, lowOpen, lowVol, lowATR] = request.security_lower_tf(syminfo.ticker, "1", [close, high, low, open, volume, atr])



if show == "Range US" and loadFast
    
    var float  [] trCandle                  = array.new_float ()
    var box    [] boxTr                     = array.new_box()
    
    bool cond                               = year(time) == year(timenow) 
                                                 and month(time) == month(timenow) 
                                                     and dayofmonth(time) == dayofmonth(timenow)


    if array.size(lowClose) != 0 

        var float clo                        = 0.0

        float revFin = switch tra 
             
            "Custom" => rev 
            "Auto"   => clo / 150
        
        float treFin = switch tra 
            
            "Custom" => tre 
            "Auto"   => clo /  75


        var int    []            trCount  = array.new_int(initial_value = 0)
        var color  []            col      = array.new_color ()
        var string []            dNp      = array.new_string()

        if array.size(trCandle) > 500
            for i = 0 to array.size(trCandle) - 500
                
                array.shift(trCandle)
                array.shift(trCount)
                array.shift(col)
                array.shift(dNp)    
    
        if na(array.size(lowClose)[1])
            
            array.push(trCandle, array.get(lowHigh, 0))
            array.push(col, color(na))
            array.push(trCount, 0)
            array.push(dNp, "Start")

            clo := close
       
        varip dayCount = array.new_float ()

        if array.size(trCandle) > 0
            
            string dStri  = "\n" + 
                                         str.tostring(year, "###")  + "/" + 
                                         str.tostring(month, "###") + "/" + 
                                         str.tostring(dayofmonth,    "###")

            for i = 0 to array.size(lowClose) - 1
                
                if array.get(trCount, array.size(trCount) - 1) == 0
                
                    if array.size(trCandle) == 1
                       
                        if array.get(lowHigh, i) > array.get(trCandle, array.size(trCandle) - 1) + treFin 

                            array.push(trCandle, array.get(trCandle, array.size(trCandle) - 1)   + treFin)   
                            array.push(col, color(na))
                            array.push(trCount, 0)
                            array.push(dNp, "+ " + str.tostring(treFin, "###.##") + dStri)
                            
                            if cond
                                array.push(dayCount, timFin)
                        
                        if array.get(lowLow, i) < array.get(trCandle, array.size(trCandle) - 1) - revFin
                            
                            array.push(trCandle, array.get(trCandle, array.size(trCandle) - 1)  - revFin)
                            array.push(trCount, 1)
                            array.push(col, color(na))
                            array.push(dNp, "- " + str.tostring(revFin, "###.##") + dStri)
                            
                            if cond
                                array.push(dayCount, timFin)
                                
                    else if array.size(trCandle) > 1
                        
                        if array.get(lowHigh, i) >= array.get(trCandle, array.size(trCandle) - 1) + treFin 
                            
                            array.push(trCandle, array.get(trCandle, array.size(trCandle) - 1)    + treFin)   
                            array.push(col, color.new(color.lime, 50))
                            array.push(trCount, 0)
                            array.push(dNp, "+ " + str.tostring(treFin, "###.##") + dStri)
                            
                            if cond
                                array.push(dayCount, timFin)
                       
                        if array.get(lowLow, i) < array.get(trCandle, array.size(trCandle) - 1) - revFin 

                            array.push(trCandle, array.get(trCandle, array.size(trCandle) - 1)  - revFin)
                            array.push(col, color.new(color.red, 50))
                            array.push(trCount, 1)
                            array.push(dNp, "- " + str.tostring(revFin, "###.##") + dStri)
                            
                            if cond
                                array.push(dayCount, timFin)
                                
                                
                if array.get(trCount, array.size(trCount) - 1) == 1 
                    if array.get(lowLow, i) <= array.get(trCandle, array.size(trCandle) - 1) - treFin 
                        
                        array.push(trCandle, array.get(trCandle, array.size(trCandle) - 1)   - treFin)   
                        array.push(col, color.new(color.red, 50))
                        array.push(trCount, 1)
                        array.push(dNp, "- " + str.tostring(treFin, "###.##") + dStri)
       
                        if cond
                            array.push(dayCount, timFin)
               
                    if array.get(lowHigh, i) > array.get(trCandle, array.size(trCandle) - 1) + revFin 

                        array.push(trCandle, array.get(trCandle, array.size(trCandle) - 1)   + revFin)
                        array.push(col, color.new(color.lime, 50))
                        array.push(trCount, 0)
                        array.push(dNp, "+ " + str.tostring(revFin, "###.##") + dStri)
       
                        if cond
                            array.push(dayCount, timFin)

        if barstate.islast and array.size(trCandle) > 1
        
            var line [] dayCon               = array.new_line  ()
            color    [] colCopy              = array.new_color ()
            float    [] trCandleCopy         = array.new_float ()
            int      [] trCountCopy          = array.new_int   ()
            string   [] dNpCopy              = array.new_string()
                

            for i = array.size(trCandle) - 1 to 0
                
                array.push(colCopy, array.get(col, i))
                array.push(trCandleCopy, array.get(trCandle, i))
                array.push(trCountCopy, array.get(trCount, i))
                array.push(dNpCopy, array.get(dNp, i))


            if array.size(boxTr) > 0 
                for i = 0 to array.size(boxTr) - 1
                    
                    box.delete(array.shift(boxTr))
            
            var string [] finReq1             = array.new_string()
            array.reverse(finReq1)


            string txtSz = switch sz
                
                "Auto"                              => size.auto
                "Tiny"                              => size.tiny
                "Small"                             => size.small
                "Normal"                            => size.normal
                "Large"                             => size.large
                "Huge"                              => size.huge


            for i = 1 to math.min(array.size(trCandleCopy) - 1, 500)


                array.push(finReq1, str.substring(array.get(dNpCopy, i - 1), str.pos(array.get(dNpCopy, i - 1), "/") - 4))
                array.push(boxTr, box.new(bar_index[i + 1], 
                                                         
                                                         array.get(trCandleCopy, i - 1) > array.get(trCandleCopy, i) ? array.get(trCandleCopy, i - 1) : array.get(trCandleCopy, i), 
                                                         bar_index[i],
                                                         array.get(trCandleCopy, i - 1) > array.get(trCandleCopy, i) ? array.get(trCandleCopy, i) : array.get(trCandleCopy, i - 1), 
                                                         bgcolor = array.get(colCopy, i - 1), 
                                                         border_color = color.white,
                                                         border_width = 1, 
                                                         xloc         = xloc.bar_index,
                                                         text         = array.get(dNpCopy, i - 1), 
                                                         text_color   = color.white, 
                                                         text_size    = txtSz

                                                         ))
                                                         
                                                         
                                                         

            var float [] cong = array.new_float()
            
            if array.size(boxTr) > 5 
                for n = 5 to array.size(boxTr) - 1
                    if math.avg(box.get_top(array.get(boxTr, n)), box.get_bottom(array.get(boxTr, n))) == 
                     math.avg(box.get_top(array.get(boxTr, n - 5)), box.get_bottom(array.get(boxTr, n - 5)))
                      and array.includes(cong, math.avg(box.get_top(array.get(boxTr, n)), box.get_bottom(array.get(boxTr, n)))) == false
                        array.push(cong, math.avg(box.get_top(array.get(boxTr, n)), box.get_bottom(array.get(boxTr, n))))
                        

            if ranShow == true
             and array.size(finReq1) > 1
                var linefill [] dayFill = array.new_linefill()
                for n = 1 to array.size(finReq1) - 1
                    if array.get(finReq1, n - 1) != array.get(finReq1, n)
                        array.push(dayCon, line.new(box.get_left(array.get(boxTr, n)) + 1, 
                         
                         close[n], 
                         box.get_left(array.get(boxTr, n)) + 1, 
                         close[n] + syminfo.mintick, 
                         extend =   extend.both, 
                         xloc   =   xloc.bar_index, 
                         color  =   color.new(color.yellow, 50)
                         
                         ))
    
                if array.size(dayCon) > 1
                    for x = 1 to array.size(dayCon) - 1
                        array.push(dayFill, linefill.new(array.get(dayCon, x), array.get(dayCon, x - 1), color.new(color.yellow, 90))) 
                    
                    

                    
                else
                
                        
                        

                        
                    z = line.new(box.get_left(array.get(boxTr, array.size(boxTr) - 1)), 
                                      close, 
                                      box.get_left(array.get(boxTr, array.size(boxTr) - 1)),
                                      close + syminfo.mintick, 
                                      color = color.new(color.yellow, 90)
                                      )
                    z1 = line.new(bar_index, 
                                      close, 
                                      bar_index,
                                      close + syminfo.mintick, 
                                      color = color.new(color.yellow, 90)
                                      )
                    linefill.new(z, z1, color.new(color.yellow, 90))

                                        
            var line     [] x  = array.new_line    (2)
            var linefill [] xf = array.new_linefill(2)
            var label    [] xl = array.new_label   (1)
           

            if array.size(finReq1) > 0
                indexStop = 0
                for i = 1 to array.size(finReq1) - 1
                    if array.get(finReq1, i - 1 ) ==  
                                         str.tostring(year(timenow), "###")  + "/" + 
                                         str.tostring(month(timenow), "###") + "/" + 
                                         str.tostring(dayofmonth(timenow),    "###")
                         and array.get(finReq1, i) != array.get(finReq1, i - 1)
                        
                        indexStop := i + 1
                        
                        break

                if indexStop != 0 
                    
                    array.set(x, 0, line.new(bar_index - indexStop,
                                             close, 
                                             bar_index - indexStop,
                                             close + syminfo.mintick, color = color.white, extend = extend.both, xloc = xloc.bar_index
                                             
                                                 ))
                
                    array.set(x,  1, line.new(bar_index + 1, close, bar_index + 1, close + syminfo.mintick, color = color.white,
                                                 
                                                 extend = extend.both, 
                                                 xloc   = xloc.bar_index
                                                 
                                                 ))
                    
                    array.set(xf, 0, linefill.new(array.get(x, 0), array.get(x, 1), color.new(color.white, 95)))
                    array.set(xl, 0, label.new(math.round(math.avg(line.get_x1(array.get(x, 0)), 
                                    
                                  line.get_x1(array.get(x, 1)))), 
                                  close, 
                                  text      = "Recent Price Action", 
                                  xloc      = xloc.bar_index, 
                                  color     = na, 
                                  textcolor = color.white, 
                                  size      = size.huge, 
                                  yloc      = yloc.abovebar
                                   
                                  ))
            
                    if array.size(dayCon) > 0
                        array.set(xf, 1, linefill.new(array.get(dayCon, 0), array.get(x, 0), color.new(color.yellow, 90)))
            
            var box        []            finBox         = array.new_box(0)
            var line       []            levels         = array.new_line()
            var label      []            levelLabels    = array.new_label()
            var linefill   []            levelsFill     = array.new_linefill()

            bool cX = array.get(trCountCopy, 0) == 0 and close >= box.get_top(array.get(boxTr, 0))
            bool cY = array.get(trCountCopy, 0) == 0 and close <  box.get_top(array.get(boxTr, 0))
            bool cZ = array.get(trCountCopy, 0) == 1 and close >= box.get_bottom(array.get(boxTr, 0))                    
            
            
            
            if array.size(finBox) == 0 
                    
                array.push(finBox, box.new(move == false ? bar_index - 1 : bar_index + 4,
                         cX ? close : 
                         cY ? box.get_top(   array.get(boxTr, 0)) :
                         cZ ? close : 
                         box.get_bottom  (   array.get(boxTr, 0)) ,
                         move == false ? bar_index : bar_index + 5, 
                         cX ? box.get_top(   array.get(boxTr, 0)) : 
                         cY ? close :
                         cZ ? box.get_bottom(array.get(boxTr, 0)) : 
                         close, 
                         border_color = color.white,
                         text_color   = color.white,
                         bgcolor = 
                         cX ? color.new(color.lime, 50) :
                         cY ? color.new(color.red,  50) :
                         cZ ? color.new(color.lime, 50) :
                              color.new(color.red,  50) ,
                         text = 
                         cX ? "+ "  + str.tostring(close - box.get_top(array.get(boxTr, 0)),    format.mintick) :
                         cY ?         str.tostring(close - box.get_top(array.get(boxTr, 0)),    format.mintick) :
                         cZ ? "+ "  + str.tostring(close - box.get_bottom(array.get(boxTr, 0)), format.mintick) :
                                      str.tostring(close - box.get_bottom(array.get(boxTr, 0)), format.mintick) ,
                        
                         xloc      = xloc.bar_index
                         
                             
                             ))
            
        
            
            else
            
                box.set_left(array.get(finBox, 0) , box.get_right(array.get(finBox , 0))    )
                box.set_right(array.get(finBox, 0), box.get_right(array.get(finBox , 0)) + 1)

            
                box.set_top(array.get(finBox, 0), 
                         cX ? close : 
                         cY ? box.get_top(   array.get(boxTr, 0)) :
                         cZ ? close : 
                         box.get_bottom  (   array.get(boxTr, 0))
                         )
                box.set_bottom(array.get(finBox, 0), 
                         cX ? box.get_top(   array.get(boxTr, 0)) : 
                         cY ? close :
                         cZ ? box.get_bottom(array.get(boxTr, 0)) : 
                         close
                         )       
                box.set_bgcolor(array.get(finBox, 0),
                         cX ? color.new(color.lime, 50)   :
                         cY ? color.new(color.red,  50)   :
                         cZ ? color.new(color.lime, 50)   :
                              color.new(color.red,  50)
                         )
                box.set_text(array.get(finBox, 0),
                         cX ? "+ "  + str.tostring(close - box.get_top(array.get(boxTr, 0   )), format.mintick) :
                         cY ?         str.tostring(close - box.get_top(array.get(boxTr, 0   )), format.mintick) :
                         cZ ? "+ "  + str.tostring(close - box.get_bottom(array.get(boxTr, 0)), format.mintick) :
                                      str.tostring(close - box.get_bottom(array.get(boxTr, 0)), format.mintick) 
                        
                         )            
            

            if array.size(cong) > 0 and treShow > 0
                
                str = ""
                
                for n = 0 to math.min(array.size(cong) - 2, treShow - 1)
                    
                    str := array.get(cong, n) >= array.get(cong, n + 1) ? 
                         str + str.tostring(array.get(cong, n), format.mintick) + " △\n" 
                     :   str + str.tostring(array.get(cong, n), format.mintick) + " ▼\n" 
                    
                    if n == math.min(array.size(cong) - 2, treShow - 1)
                        str := str + str.tostring(array.get(cong, n + 1), format.mintick) 
                         + "\n"

                
                var table upRight = table.new(position.top_right, 10, 10, frame_color = color.white, border_color = color.white, frame_width = 1, border_width = 1)
                table.cell(upRight, 0, 0, text = "Congestion Areas \n(Reversed Order of Occurrence)", text_color = #00ffff, bgcolor = color.new(#000000, 75))
                table.cell(upRight, 0, 1, text = str, text_color = color.red, bgcolor = color.new(#000000, 75))
                if tra == "Custom" and warn1 == true
                    if rev < array.get(lowATR, array.size(lowATR) - 1) * 1.9 or tre < array.get(lowATR, array.size(lowATR) - 1) * 1.9
                        table.cell(upRight, 1, 1, bgcolor = color.new(#000000, 75), text_color = color.red, text_size = size.small, text = "This Chart Type Is Using 1 Minute OHLC Data; \nNo Tick Data Is Used. \nIf You’re Seeing This Message: \nYour Configurations for a Trend Candle or Reversal Candle Are Likely Too Low. \nFor Instance, if You Set Trend Candles to $1 Then Trend Candles Will \nForm Subsequent a $1 Price Move. This Is Sufficient for Lower Priced Assets; \nHowever, if You Were Trading, for Instance, Bitcoin - \nA $1 Price Move Can Happen Numerous Times in One Minute. \nThis Script Can’t Plot Bars and Record Data Until a 1-Minute \nBar Closes and a New 1-Minute Bar Opens. \nTry Adjusting the Trend Candle and Reversal Candle Settings to Price Level \nThat’s Unlikely to Be Exceeded Numerous Times per Minute. \nThis Message Will Dissapear if \n You Adjust the Price Levels to\n" + str.tostring(array.get(lowATR, array.size(lowATR) - 1) * 2 , format.mintick) + " or Greater")
                        table.cell(upRight, 1, 0, bgcolor = color.new(#000000, 75), text_color = color.red, text_size = size.normal, text = "Warning")

            var table stats = table.new(position.bottom_right, 10, 10, frame_color = color.white, border_color = color.white, frame_width = 1, border_width = 1)
            table.cell(stats, 0, 0, "Range US🛈",  bgcolor = color.new(#ffffff, 75), text_color = color.white, tooltip = "A Range US Chart Operates Irrespective of Time and Volume - Simply - Bars Move After a User-Defined Price Move Is Achieved/Exceeded in either Direction. A Range US Chart Produces: \n1. “Trend Candles” \n2. “Reversal Candles” \nA Reversal Candle Always Moves Against the Most Immediate Bar; A Trend Candle Always Moves in Favor of the Most Immediate Bar. The User Defines the Dollar Amount Price Must Travel Up/Down for a Trend Candle to Fulfill, and for a Reversal Candle to Fulfill. Note, if a “Down Reversal” Candle (Red) Is Produced, It’s *Impossible* For the Next Candle to Also Be a Down Reversal Candle - For the Downside Move to Continue the Criteria for a Down Trend Candle Must Be Fulfilled. Similarly, if an “Up Reversal” Candle (Green) Is Produced, It’s Impossible for the Next Candle to Also Be an Up Reversal Candle - For the Upside Move to Continue, the Criteria for an Uptrend Trend Candle Must Be Fulfilled. Consequently, Range US Bars Frequently Trade at the Same Level for Extended Periods. This Is Intentional, as This Chart Type Is Theorized to “Filter Noise” - Whether Range US Charts Fulfill This Theory Is to Your Discretion. Lastly, if a Green (Up) Trend Candle Is Produced, the Next Candle Cannot Be up a Reversal Up Candle - Only a Trend Up Candle or Reversal Down Candle Can Produce - Vice Versa for a Trend Down Candle (The Subsequent Candle Cannot Be a Reversal Down Candle). In This Sense, an Uptrend Continues on Successive Trend Up Candles; A Down Trend Continues on Successive Trend Down Candles.")
            table.cell(stats, 0, 1, "🛈",  bgcolor = color.new(#ffffff, 75), text_color = color.lime, tooltip = "The Dollar Amount Prices Must Increase for a Green Trend Candle to Form - The Precise Price Level Is Included in Parenthesis. Note: If the Current Range Us Bar Is a Trend Down Bar or Down Reverse Bar, an Up Reverse Bar Must First Produce.")
            table.cell(stats, 0, 2, "🛈",  bgcolor = color.new(#ffffff, 75), text_color = color.lime, tooltip = "The Dollar Amount Prices Must Decrease for a Red Trend Candle to Form - The Precise Price Level Is Included in Parenthesis. Note: If the Current Range Us Bar Is a Trend Up Bar or Up Reverse Bar, a Down Reverse Bar Must First Produce.")
            table.cell(stats, 0, 3, "🛈",  bgcolor = color.new(#ffffff, 75), text_color = color.lime, tooltip = array.get(trCountCopy, 0) == 0 ? "The Dollar Amount Prices Must Decrease for a Down Reverse Candle to Form - The Precise Price Level Is Included in Parenthesis." : "The Dollar Amount Prices Must Increase for an Up Reverse Candle to Form - The Precise Price Level Is Included in Parenthesis. ")

            table.cell(stats, 2, 1, "Trending After $"  + str.tostring(treFin, format.mintick) + " Price Move", text_color = color.lime, bgcolor = color.new(#000000, 75))
            table.cell(stats, 2, 2, "Reversing After $" + str.tostring(revFin, format.mintick) + " Price Move", text_color = color.lime, bgcolor = color.new(#131722, 75))
            
            table.cell(stats, 1, 1, "$ for Trend Up: "  + str.tostring( 
                                             (box.get_top(array.get(boxTr, 0)) + treFin) - close, format.mintick) + " Price Move ($" 
                                             + str.tostring((box.get_top(array.get(boxTr, 0)) + treFin), format.mintick) + ")" ,
                                             text_color = color.lime, 
                                             bgcolor = color.new(#2a2e39, 75)
                                             )
            
    
            table.cell(stats, 1, 2, "$ for Trend Down: "  + str.tostring( 
                                             (box.get_bottom(array.get(boxTr, 0)) - treFin) - close, format.mintick) + " Price Move ($" 
                                             + str.tostring((box.get_bottom(array.get(boxTr, 0)) - treFin), format.mintick) + ")" ,
                                             text_color = color.lime, 
                                             bgcolor = color.new(#434651, 75)
                                             )
                                             
                                             
                                             
                                                  
                                             
            if array.get(trCountCopy, 0) == 0
                
                table.cell(stats, 1, 3, "$ for Reverse Down: "  + str.tostring( 
                                             (box.get_top(array.get(boxTr, 0)) - revFin) - close, format.mintick) + " Price Move ($" 
                                             + str.tostring((box.get_top(array.get(boxTr, 0)) - revFin), format.mintick) + ")" ,
                                             text_color = color.lime, 
                                             bgcolor = color.new(#5d606b, 75)
                                             )

                if levShow == true
                    

                    array.push(levels, line.new( bar_index + 2, 
                                         box.get_top(array.get(boxTr, 0)) - revFin, 
                                         bar_index + 8, 
                                         box.get_top(array.get(boxTr, 0)) - revFin, 
                                         color = color.orange
                                         ))
                                         
                    array.push(levels, line.new( bar_index + 2, 
                                                 math.avg(box.get_top(array.get(boxTr, 0)) - revFin, box.get_bottom(array.get(boxTr, 0)) - treFin), 
                                                 bar_index + 8, 
                                                 math.avg(box.get_top(array.get(boxTr, 0)) - revFin, box.get_bottom(array.get(boxTr, 0)) - treFin), 
                                                 color = na
                                                 ))           

                    
                    array.push(levelLabels, label.new(bar_index + 8, box.get_top(array.get(boxTr, 0)) - revFin, 
                                                     "Reverse Down", textcolor = color.orange, color = color.new(color.white, 100), 
                                                     size = size.small, style = label.style_label_left  ))
                                                             

            
            else 
        
               
               
                table.cell(stats, 1, 3, "$ for Reverse Up: "  + str.tostring( 
                                             (box.get_bottom(array.get(boxTr, 0)) + revFin) - close, format.mintick) + " Price Move ($" 
                                             + str.tostring((box.get_bottom(array.get(boxTr, 0)) + revFin), format.mintick) + ")" ,
                                             text_color = color.lime, 
                                             bgcolor = color.new(#5d606b, 75)  )
                
                if levShow == true
                    
                    array.push(levels, line.new( bar_index + 2, 
                                                 box.get_bottom(array.get(boxTr, 0)) + revFin, 
                                                 bar_index + 8, 
                                                 box.get_bottom(array.get(boxTr, 0)) + revFin, 
                                                 color = color.blue
                                                 ))         
                    
                    
                    array.push(levels, line.new( bar_index + 2, 
                                                 math.avg(box.get_bottom(array.get(boxTr, 0)) + revFin, box.get_bottom(array.get(boxTr, 0)) - treFin), 
                                                 bar_index + 8, 
                                                 math.avg(box.get_bottom(array.get(boxTr, 0)) + revFin, box.get_bottom(array.get(boxTr, 0)) - treFin), 
                                                 color = na
                                                 ))           

                    array.push(levelLabels, label.new(bar_index + 8, box.get_bottom(array.get(boxTr, 0)) + revFin, 
                                                     "Reverse Up", textcolor = color.blue, color = color.new(color.white, 100), 
                                                     style = label.style_label_left,
                                                     size = size.small))
                                                             
                
            if array.size(cong) > 0    
                table.cell(stats, 2, 3, "Most Recent Congestion Area: $" + str.tostring(array.get(cong, 0), format.mintick),
                                         text_color = color.lime, 
                                         bgcolor = color.new(#5d606b, 75))
            
            table.merge_cells(stats, 0, 0, 2, 0)
                
            if levShow == true
                
                
                array.push(levels, line.new( bar_index + 2, 
                                             box.get_top(array.get(boxTr, 0)) + treFin,
                                             bar_index + 8, 
                                             box.get_top(array.get(boxTr, 0)) + treFin, 
                                             color = color.lime
                                             ))                
                
                array.push(levelLabels, label.new(bar_index + 8, box.get_top(array.get(boxTr, 0)) + treFin, 
                                                     "Trend Up", textcolor = color.lime, color = color.new(color.white, 100), 
                                                     style = label.style_label_left,
                                                     size = size.small))
                
                array.push(levels, line.new( bar_index + 2, 
                                             box.get_bottom(array.get(boxTr, 0)) - treFin,
                                             bar_index + 8, 
                                             box.get_bottom(array.get(boxTr, 0)) - treFin, 
                                             color = color.red
                                             ))       
                                    
                array.push(levelLabels, label.new(bar_index + 8, box.get_bottom(array.get(boxTr, 0)) - treFin, 
                                                     "Trend Down", textcolor = color.red, color = color.new(color.white, 100), 
                                                     style = label.style_label_left, size = size.small))
                                                    
                array.push(levels, line.new( bar_index + 2, 
                                                 math.avg(line.get_y1(array.get(levels, 0)), line.get_y1(array.get(levels, 2))),
                                                 bar_index + 8, 
                                                 math.avg(line.get_y1(array.get(levels, 0)), line.get_y1(array.get(levels, 2))),
                                                 color = na
                                                 ))           


                if array.size(levels) > 5
                    
                    for i = 0 to 4
                        line.delete(array.shift(levels))
                
                if array.size(levels) == 5
                    
                    array.push(levelsFill, linefill.new(array.get(levels, 0), array.get(levels, 2), color.new(color.lime, 90)))
                    array.push(levelsFill, linefill.new(array.get(levels, 0), array.get(levels, 4), color.new(array.get(trCount, 0) == 0 ? color.orange : color.blue, 90)))
                    array.push(levelsFill, linefill.new(array.get(levels, 0), array.get(levels, 3), color.new(array.get(trCount, 0) == 0 ? color.orange : color.blue, 90)))
                    array.push(levelsFill, linefill.new(array.get(levels, 1), array.get(levels, 3), color.new(color.red, 90)))

                if array.size(levelsFill) > 4
                    for i = 0 to 3
                        linefill.delete(array.shift(levelsFill))
                
                if array.size(levelLabels) > 3
                    for i = 0 to 2
                        label.delete(array.shift(levelLabels))

// _______________________________________________________
//
// Volume Aggregation Bars
// _______________________________________________________  


if show == "Volume Aggregation" and loadFast

    var box       finBox        = na
    var float  [] cumVol        = array.new_float()
    var float  [] volC          = array.new_float()
    var string [] date          = array.new_string()
    var line   [] dayCon        = array.new_line()
    var float  [] volMed        = array.new_float()
    array.push(volMed, volume)
    float volIn                 = tra1 == "Auto" ? array.percentile_linear_interpolation(volMed, 90) : volInt

    string txtSz = switch sz1
        
        "Auto"                              => size.auto
        "Tiny"                              => size.tiny
        "Small"                             => size.small
        "Normal"                            => size.normal
        "Large"                             => size.large
        "Huge"                              => size.huge

    array.push(cumVol, array.size(cumVol) == 0 ? volume : array.get(cumVol, array.size(cumVol) - 1) + volume)
    
    if array.size(cumVol) > 0 
        if array.get(cumVol, array.size(cumVol) - 1) > volIn
            var float calc = 0.0
            calc := array.get(cumVol, array.size(cumVol) - 1) - volIn
            array.clear(cumVol)
            array.push(cumVol, calc)
            array.push(volC, close)
            array.push(date, 
                         str.tostring(year)            + "/" 
                         + str.tostring(month)         + "/" 
                         + str.tostring(dayofmonth)    + "\n$" 
                         + str.tostring(close, format.mintick))

            
    if array.size(volC) > 0
        

        if array.size(volC) > 502
            
            array.shift(volC)
            array.shift(date)
            array.shift(volMed)



        if barstate.islast
            
            
            var string [] finReq1   = array.new_string()
            var float  [] max       = array.new_float()
            var box    [] volBox    = array.new_box()
    
            float [] volCopy = array.new_float()
            string [] dateCopy = array.new_string()

            for i = array.size(volC) - 1 to 0
                array.push(volCopy, array.get(volC, i))
                array.push(dateCopy, array.get(date, i))

            if array.size(volBox) > 0
                for i = 0 to array.size(volBox) - 1
                    box.delete(array.shift(volBox))
            
            if array.size(finReq1) > 0
                array.clear(finReq1)
            
            if array.size(max) > 0
                array.clear(max)



            for i = 0 to math.min(array.size(volC) - 2, 500)
                
                array.push(max, i == 0 ? 0 : array.get(volCopy, i) / array.get(volCopy, i + 1) - 1)
                array.push(finReq1, str.substring(array.get(dateCopy, i),0, str.pos(array.get(dateCopy, i), "\n")))
                

                array.push(volBox, box.new(bar_index[i + 1], 
                                         
                                         array.get(volCopy, i) > array.get(volCopy, i + 1) ? array.get(volCopy, i) : array.get(volCopy, i + 1), 
                                         bar_index[i], 
                                         array.get(volCopy, i) > array.get(volCopy, i + 1) ? array.get(volCopy, i + 1) : array.get(volCopy, i), 
                                         bgcolor = array.get(volCopy, i) > array.get(volCopy, i + 1) ? 
                                         color.new(color.green, 50) : 
                                         color.new(color.red,   50) ,
                                         border_color = color.white , 
                                         text         = array.get(dateCopy, i) + "\nMoves On \n" + 
                                         str.tostring(volIn, format.volume) + " Volume"          ,
                                         text_color   = color.white ,
                                         text_size    = txtSz        

                                         ))


                box.delete(finBox)        
               
                finBox := box.new(bar_index, array.get(volCopy, 0) > array.get(volCopy, 1) ? array.get(volCopy, 0) : close, 
                                         
                                         bar_index + 1, 
                                         array.get(volCopy, 0) > array.get(volCopy, 1) ? close : array.get(volCopy, 0), 
                                         bgcolor      = close > array.get(volCopy, 0) ? color.new(color.green, 50) : color.new(color.red, 50),
                                         border_color = color.white, 
                                         text         = str.tostring(year, "###") + "/" + str.tostring(month, "###") + "/" + str.tostring(dayofmonth, "###") + "\n" +
                                         str.tostring(array.get(cumVol, array.size(cumVol) - 1), format.volume) + " Volume", 
                                         text_color   = color.white

                                         )
            if vShow == true 
             and array.size(finReq1) > 1
                var linefill [] dayFill = array.new_linefill()
                for n = 1 to array.size(finReq1) - 1
                    if array.get(finReq1, n - 1) != array.get(finReq1, n)
                        array.push(dayCon, line.new(box.get_left(array.get(volBox, n)) + 1, 
                         
                         close[n], 
                         box.get_left(array.get(volBox, n)) + 1, 
                         close[n] + syminfo.mintick, 
                         extend = extend.both, 
                         xloc = xloc.bar_index, 
                         color = color.new(color.yellow, 50)
                         
                         ))
                    
            
                    
                if array.size(dayCon) > 1
                    for x = 1 to array.size(dayCon) - 1
                        array.push(dayFill, linefill.new(array.get(dayCon, x), array.get(dayCon, x - 1), color.new(color.yellow, 90))) 
                

            var table stats = table.new(position.bottom_right, 10, 10,  frame_color = color.white, border_color = color.white, frame_width = 1, border_width = 1)
            table.cell(stats, 0, 0, text = "Volume Aggregation🛈", text_color = color.red, text_size = size.normal, bgcolor = color.new(#000000, 50)
                                             , tooltip = "Volume Aggregation Bars Aren’t Bound to a Time-Axis; The Bars Form After a User-Defined, Cumulative Amount of Volume Is Achieved or Exceeded. Consequently, Once the Cumulative Amount of Volume Is Achieved or Exceeded - A Bar Is Produced No Matter the Price. Underlying Theory: The Chat Type Is Conducive to Identifying Price Levels Where Traders Are “Trapped”." )
            table.cell(stats, 0, 1, text = "Moving On " + str.tostring(volIn, format.volume) + " Volume", text_color = color.red, text_size = size.normal, 
                                             bgcolor = color.new(#000000, 50) 
                                              )
            table.cell(stats, 0, 2, text = "Largest Upside Move:  " + str.tostring(array.max(max)* 100, format.percent), text_color = color.red, text_size = size.normal, 
                                             bgcolor = color.new(#000000, 50) 
                                              )                        
            table.cell(stats, 0, 3, text = "Largest Downside Move:  " + str.tostring(array.min(max)* 100, format.percent), text_color = color.red, text_size = size.normal, 
                                             bgcolor = color.new(#000000, 50) 
                                              )    
            
                
            if showAl == true
                
                maxStrCop  = array.new_string(array.size(finReq1))
                maxCop     = array.copy(max)
                
                if array.size(max) == array.size(finReq1) and array.size(max) > 1
                    array.sort(maxCop, order.descending)
                    
                    for i = 0 to array.size(max) - 1
                        finCop = array.get(finReq1, array.indexof(max, array.get(maxCop, i)) > 0 ? array.indexof(max, array.get(maxCop, i)) : 0)
                        array.set(maxStrCop, i, finCop)                
                    
                string str = ""
                string str1 = ""    
                                                                
                if array.size(maxCop) > 0
                    for i = 0 to math.min(array.size(maxCop) - 1, showUp - 1)
                        str := str + str.tostring(array.get(maxCop, i) * 100, format.percent) + "(" + array.get(maxStrCop, i) + ")\n"
                    if array.size(maxCop) > showDn 
                        for i = array.size(maxCop) - 1 to array.size(maxCop) - showDn 
                            str1 := str1 + str.tostring(array.get(maxCop, i) * 100, format.percent) + "(" + array.get(maxStrCop, i) + ")\n"
                            
                var table upRight = table.new(position.top_right, 10, 10, frame_color = color.white, border_color = color.white, frame_width = 1, border_width = 1 )
                table.cell(upRight, 0, 0, "Largest Upside Moves", text_color = color.lime, bgcolor = color.new(color.green, 75))
                table.cell(upRight, 0, 1, str, text_color = color.white, bgcolor = color.new(color.green, 75), text_halign = text.align_left)
                table.cell(upRight, 0, 2, "Largest Downside Moves", text_color = color.red, bgcolor = color.new(color.red, 75))
                table.cell(upRight, 0, 3, str1, text_color = color.white, bgcolor = color.new(color.red, 75), text_halign = text.align_left)
                if tra1 == "Custom" and warn == true
                    if volInt < array.percentile_linear_interpolation(volMed, 90)
                        table.cell(upRight, 1, 0, bgcolor = color.new(#000000, 75), text_color = color.red, text_size = size.small, text = "This Data Set Uses the OHLC Data \nFrom the Timeframe on Your Chart; \nNo Tick Data Is Used. \nIf You’re Seeing This Message: \nYour Configurations for Required Volume Are Likely Too Low. \nWhile This Script Calculates Cumulative Volume \nand Remainders Are Carried Over When the Volume Limit Is Exceeded, \nSetting the Volume Requirement Too Low May Result in Missed \nPrice Moves - Should the Cumulative Volume Threshold Be \nExceeded Twice in One Bar. \nSetting the Volume Requirement to " + str.tostring(array.percentile_linear_interpolation(volMed, 90)) + " \nor Deselcting the 'Show Warning' Option \nin the Input Settings Will Hide This Message.")
                        table.merge_cells(upRight, 1, 0, 1, 3)

// _______________________________________________________
// 
// Gaps
// _______________________________________________________  


if show == "Gaps" and loadFast

    bool gDn                               = high < low[1] and math.abs(low[1] / high - 1) > perG
    bool gUp                               = low > high[1] and math.abs(low / high[1] - 1) > perG
    
    var float  []  gArray                  = array.new_float()
    var box    []  gBox                    = array.new_box()
    var color  []  col                     = array.new_color()
    var string []  dNp                     = array.new_string()
    var float  []  sli                     = array.new_float()
    var box    []  boxGpD                  = array.new_box()
    var box    []  boxGpU                  = array.new_box()
    var int    []  boxCountD               = array.new_int()
    var int    []  boxCountU               = array.new_int()
    var float  []  minU                    = array.new_float()
    var float  []  maxD                    = array.new_float()
    var int    []  avgU                    = array.new_int()
    var int    []  avgD                    = array.new_int()

    if array.size(gArray) > 500
        
        for i = 0 to array.size(gArray) - 500
            
            array.shift(gArray)
            array.shift(col)
    
    if gUp

        array.push(gArray, array.size(gArray) == 0 ? low : array.get(gArray, array.size(gArray) - 1) + low - high[1])
        array.push(sli, (low / high[1] - 1) * 100)
        array.push(col, color.new(color.green, 50))
        array.push(dNp, str.tostring(low - high[1], format.mintick) + "\n" + 
                                     str.tostring(year, "###") + "/" + 
                                     str.tostring(month, "###") + "/" + 
                                     str.tostring(dayofmonth, "###"))
                                     
                                     
        array.push(boxGpU, box.new(math.round(time),low, math.round(time) + timFin,high[1], 
                                     text = str.tostring((close / low - 1) * 100, format.percent) + " To Fill", xloc = xloc.bar_time, bgcolor = color.new(color.lime, 50),
                                     border_color = color.lime, text_color = color.white, text_halign = text.align_right))
        array.push(boxCountU, 0), array.push(minU, 1e+13), array.push(avgU, bar_index)

    if gDn

        array.push(gArray, array.size(gArray) == 0 ? high : array.get(gArray, array.size(gArray) - 1) + high - low[1])
        array.push(sli, (high / low[1] - 1) * 100)
        array.push(col, color.new(color.red, 50))
        array.push(dNp, str.tostring(high - low[1], format.mintick) + "\n" + 
                                     str.tostring(year, "###") + "/" + 
                                     str.tostring(month, "###") + "/" + 
                                     str.tostring(dayofmonth, "###"))
        array.push(boxGpD, box.new(math.round(time), low[1], math.round(time) + timFin, high, xloc = xloc.bar_time, 
                                     text = str.tostring((close / high - 1) * 100, format.percent) + " To Fill", bgcolor = color.new(color.red, 50), 
                                     border_color = color.white, text_color = color.white, text_halign = text.align_right))
        array.push(boxCountD, 0), array.push(avgD, bar_index), array.push(maxD, 0)


    var float [] finAvgU = array.new_float()

    if array.size(boxGpU) > 0
        for n = 0 to array.size(boxGpU) - 1
            if low < box.get_bottom(array.get(boxGpU, n)) 
                if array.get(boxCountU, n) != 1 and array.get(boxCountU, n) != 3
                    box.set_text(array.get(boxGpU, n), gDn ? "New Gap" : "Filled")
                    box.set_bgcolor(array.get(boxGpU, n), color.new(color.lime, 90))
                    box.set_border_color(array.get(boxGpU, n), color.new(color.lime, 90))
                    array.push(finAvgU, bar_index - array.get(avgU, n))
                    
                    if del == false 
                        array.set(boxCountU, n, 1)
                    else 
                        array.set(boxCountU, n, 3)

            else if low < box.get_top(array.get(boxGpU, n)) and low > box.get_bottom(array.get(boxGpU, n)) and array.get(boxCountU, n) == 0
                array.set(boxCountU, n, 2)
            
            if array.get(boxCountU, n) != 1 and array.get(boxCountU, n) != 3
                
                array.set(minU, n, math.min(low, array.get(minU, n)))
                box.set_right(array.get(boxGpU, n), math.round(time + timFin))
                box.set_text(array.get(boxGpU, n),array.get(boxCountU, n) == 0 ?
                     
                     str.tostring((box.get_bottom(array.get(boxGpU, n))   / close  - 1) * 100, format.percent) + " Decrease To Fill"
                     : str.tostring((box.get_bottom(array.get(boxGpU, n)) / close  - 1) * 100, format.percent) + " To Fill \n(Partially Filled " + 
                     str.tostring     (((   array.get(minU, n) 
                     - box.get_top    (     array.get(boxGpU, n))) * 100) 
                     / (box.get_bottom(     array.get(boxGpU, n)) 
                     - box.get_top    (     array.get(boxGpU, n))), 
                     format.percent) + ")"                       )
    
        if del == true
            for i = 0 to array.size(boxGpU) - 1
                if i < array.size(boxGpU) 
                    if array.get(boxCountU, i) == 3
                        box.delete(array.remove(boxGpU, i))
                        array.remove(minU, i)
                        array.remove(boxCountU, i)
                     
        else
            if array.size(boxGpU) > 250
                for i = 0 to array.size(boxGpU) - 1
                    if array.get(boxCountU, i) == 1
                        box.delete(array.remove(boxGpU, i))
                        array.remove(minU, i)
                        array.remove(boxCountU, i)
                        break                 
                 
                    
        if old >= 0 and array.size(boxGpU) > 0
            for x = 0 to array.size(boxGpU) - 1
                if array.get(boxCountU, x) != 1 and array.get(boxCountU, x) != 3
                    if close >= box.get_top(array.get(boxGpU, x)) * (1 + old)
                        box.set_bgcolor(array.get(boxGpU, x), na)
                        box.set_border_color(array.get(boxGpU, x), na)
                        box.set_right(array.get(boxGpU, x), box.get_left(array.get(boxGpU, x)))
                    else 
                        
                        box.set_bgcolor(array.get(boxGpU, x), color.new(color.lime, 50))
                        box.set_border_color(array.get(boxGpU, x), color.new(color.lime, 50))                    
                    
    var float [] finAvgD = array.new_float()

    if array.size(boxGpD) > 0
        for n = 0 to array.size(boxGpD) - 1
            if high > box.get_top(array.get(boxGpD, n))
                if array.get(boxCountD, n) != 1 and array.get(boxCountD, n) != 3
                    array.push(finAvgD, bar_index - array.get(avgD, n))
                    box.set_text(array.get(boxGpD, n), gUp ? "New Gap" : "Filled")
                    box.set_bgcolor(array.get(boxGpD, n), color.new(color.red, 90))
                    box.set_border_color(array.get(boxGpD, n), color.new(color.red, 90))
                    
                    if del == false 
                        array.set(boxCountD,n, 1)
                    else     
                        array.set(boxCountD,n, 3)
        
            else if high < box.get_top(array.get(boxGpD, n)) and high > box.get_bottom(array.get(boxGpD, n)) and array.get(boxCountD, n) == 0
                array.set(boxCountD, n, 2)
            
                    
            if array.get(boxCountD, n) != 1 and array.get(boxCountD, n) != 3
                
                array.set(maxD, n, math.max(high, array.get(maxD, n)))
                box.set_right(array.get(boxGpD, n), math.round(time) + timFin)
                box.set_text(array.get(boxGpD, n), array.get(boxCountD, n) == 0 ? 
                     
                     str.tostring((box.get_top(array.get(boxGpD, n)) / close  - 1) * 100, format.percent) + " Increase To Fill" :
                     str.tostring((box.get_top(array.get(boxGpD, n)) / close  - 1) * 100, format.percent) + " To Fill \n(Partially Filled " + 
                     str.tostring(((array.get(maxD, n) 
                     - box.get_bottom(array.get(boxGpD, n))) * 100) 
                     / (box.get_top(array.get(boxGpD, n)) 
                     - box.get_bottom(array.get(boxGpD, n))), 
                     format.percent) + ")") 
            
        if del == true 
            for i = 0 to array.size(boxGpD) - 1
                if i < array.size(boxGpD) 
                    if  array.get(boxCountD, i) == 3
                        box.delete(array.remove(boxGpD, i))
                        array.remove(maxD, i)
                        array.remove(boxCountD, i)
        else
            if array.size(boxGpD) > 250
                for i = 0 to array.size(boxGpD) - 1
                    if array.get(boxCountD, i) == 1
                        box.delete(array.remove(boxGpD, i))
                        array.remove(maxD, i)
                        array.remove(boxCountD, i)
                        break
                        
        if old >= 0 and array.size(boxGpD) > 0
            for x = 0 to array.size(boxGpD) - 1
                if array.get(boxCountD, x) != 1 and array.get(boxCountD, x) != 3
                    if close <= box.get_bottom(array.get(boxGpD, x)) * (1 - old)
                        box.set_bgcolor(array.get(boxGpD, x), na)
                        box.set_border_color(array.get(boxGpD, x), na)
                        box.set_right(array.get(boxGpD, x), box.get_left(array.get(boxGpD, x)))
                    
                    else 
                        
                        box.set_bgcolor(array.get(boxGpD, x), color.new(color.red, 50))
                        box.set_border_color(array.get(boxGpD, x), color.new(color.red, 50))                
    
    if barstate.islast

        var int [] hold = array.new_int(1, 0)
        if array.get(hold, 0) == 0
            
            array.reverse(gArray)
            array.reverse(col)
            array.reverse(dNp)
            array.set(hold, 0, 1)
            

        if array.size(gArray) > 0
         
            if  vis == true
         
                for i = 0 to math.min(500, array.size(gArray) - 2)  
                    
                    array.push(gBox, box.new(bar_index[i + 1], 
                                 
                                 array.get(gArray, i)  > array.get(gArray, i + 1) ? array.get(gArray, i) :  array.get(gArray, i + 1) ,
                                 bar_index[i], 
                                 array.get(gArray, i)  > array.get(gArray, i + 1) ?  array.get(gArray, i + 1) :  array.get(gArray, i),
                                 bgcolor = array.get(col, i),
                                 border_color = color.white, 
                                 text = array.get(dNp, i), 
                                 text_color = color.white
                                 
                                 
                                 ))            
                
                
                
            array.sort(sli, order.ascending)
            
            
            var float [] dn                             = array.new_float()
            var float [] up                             = array.new_float()
            
            for x = 1 to array.size(sli) - 1
                
                
                if array.get(sli, 0) < 0
                    if array.get(sli, array.size(sli) - 1) > 0
                        if array.get(sli, x - 1) < 0 and array.get(sli, x) > 0
                        
                            for n = 0 to x - 1
                                array.push(dn, array.get(sli, n))
                            for n = x to array.size(sli) - 1
                                array.push(up, array.get(sli, n))
                            
                            break
                    
                else if array.get(sli, 0) > 0 
                    if x != array.size(sli) - 1
                        array.push(up, array.get(sli, x - 1))
                    
                    else
                        
                        if array.size(sli) > 1
                            array.push(up, array.get(sli, x))
                            array.push(up, array.get(sli, x - 1))

                if array.get(sli, array.size(sli) - 1) < 0 
                    if x != array.size(sli) - 1 
                        array.push(dn, array.get(sli, x - 1))
                    
                    else 
                    
                        if array.size(sli) > 1
                            array.push(up, array.get(sli, x))
                            array.push(up, array.get(sli, x - 1))
            

            var table stats = table.new(position.bottom_right, 10, 10, border_color = color.white, frame_color= color.white, border_width = 1, frame_width = 1)
            table.cell(stats, 0, 0, "# of Gaps: " + str.tostring(array.size(sli))    ,    text_color = color.lime, bgcolor = color.new(#000000, 75))
            table.cell(stats, 0, 1, "Gaps Up: "   + str.tostring(array.size(up))        , text_color = color.lime, bgcolor = color.new(#000000, 75))
            table.cell(stats, 0, 2, "Gaps Down: " + str.tostring(array.size(dn))        , text_color = color.lime, bgcolor = color.new(#000000, 75))
            table.cell(stats, 1, 1, "Cumulative Increase: " + str.tostring(array.sum(up), format.percent)        , text_color = color.lime, bgcolor = color.new(#000000, 75))
            table.cell(stats, 2, 1, "Cumulative Decrease: " + str.tostring(array.sum(dn), format.percent)        , text_color = color.lime, bgcolor = color.new(#000000, 75))
            table.cell(stats, 1, 2, "Avg. Increase: " + str.tostring(array.avg(up), format.percent)        , text_color = color.lime, bgcolor = color.new(#000000, 75))
            table.cell(stats, 2, 2, "Avg. Decrease: " + str.tostring(array.avg(dn), format.percent)        , text_color = color.lime, bgcolor = color.new(#000000, 75))
    
            strUp = ""
            strDn = ""
            
            if array.size(boxGpU) > 0 and rec > 0 
                upCou                           = 0
                for n = array.size(boxGpU) - 1 to 0
                    if upCou == rec
                        break
                    if array.get(boxCountU, n) != 1 and array.get(boxCountU, n) != 3
                        strUp := strUp + str.tostring(box.get_bottom(array.get(boxGpU, n)), format.mintick) + " - " + str.tostring(box.get_top(array.get(boxGpU, n)), format.mintick) +
                         " (Distance: " + str.tostring((close - box.get_bottom(array.get(boxGpU, n))) * -1, format.mintick) + ")" +
                         "\n"
                        upCou += 1
            
            if array.size(boxGpD) > 0 and rec > 0
                dnCou                           = 0
                for n = array.size(boxGpD) - 1 to 0
                    if dnCou == rec
                        break
                    if array.get(boxCountD, n) != 1 and array.get(boxCountD, n) != 3
                        strDn := strDn + str.tostring(box.get_bottom(array.get(boxGpD, n)), format.mintick) + " - " + str.tostring(box.get_top(array.get(boxGpD, n)), format.mintick) + 
                         " (Distance: +" + str.tostring((close - box.get_top(array.get(boxGpD, n))) * -1, format.mintick) + ")" +
                         "\n"
                        dnCou += 1 


            var table upRight =  table.new(position.top_right, 10, 10, border_color = color.white, frame_color= color.white, border_width = 1, frame_width = 1)

            if rec > 0 
                
                if strUp != ""
                    table.cell(upRight, 0, 0, "Unfilled Up Gaps", bgcolor = color.new(#000000, 75), text_color = color.lime)
                    table.cell(upRight, 0, 1, strUp,  bgcolor = color.new(#000000, 75), text_color = color.lime)                 
                if strDn != ""
                    table.cell(upRight, 0, 2, "Unfilled Down Gaps", bgcolor = color.new(#000000, 75), text_color = color.red)                 
                    table.cell(upRight, 0, 3, strDn, bgcolor = color.new(#000000, 75), text_color = color.red)                 
    
            if del == false
                
                table.cell(stats, 1, 0, "Avg. Bars to Fill Up Gap: " + str.tostring(math.round(array.avg(finAvgU)), "#"), text_color = color.lime, bgcolor = color.new(#000000, 75))
                table.cell(stats, 2, 0, "Avg. Bars to Fill Down Gap: " + str.tostring(math.round(array.avg(finAvgD)), "#") , text_color = color.lime, bgcolor = color.new(#000000, 75))
                
            else
                
                table.merge_cells(stats, 0, 0, 2, 0)
       
        else
        
            runtime.error("No Gaps Detected - Change Assets or Plot a Different Dataset")

        

// _______________________________________________________
//
// Quartile Volume
// _______________________________________________________  


if show == "Quartile Volume" and loadFast

    var line    [] xy                       = array.new_line    (2)
    var linefill[] xyfill                   = array.new_linefill(2)
    var label   [] miniLab                  = array.new_label    ()
    var float   [] volSub                   = array.new_float    ()
    var int     [] hold                     = array.new_int      ()
    var float   [] rang                     = array.new_float    ()
    var float   [] sVol                     = array.new_float    ()
    var float   [] pNl                      = array.new_float    ()
    var int     [] bar                      = array.new_int      ()
    var bool    [] binTra                   = array.new_bool     (1, false)
    var float   [] fin                      = array.new_float    ()
    var table      tab                      = na

    array.push(vol, volume)
    
    if array.size(vol) > 250
        array.shift(vol)

    if array.size(vol) >= 2
        
        colCond := color.from_gradient(
                 
                 volume, 
                 array.percentile_linear_interpolation(vol, 25), 
                 array.percentile_linear_interpolation(vol, 75), 
                 colE, colE1
                 
                 )
    
    var float Q1 = 0.0, var float Q2 = 0.0
    var float Q3 = 0.0
    var float p9 = 0.0, var float Q4 = 0.0    
    
    
    if array.size(vol) >= 5 and array.size(hold) == 0
        
        if array.size(xz) > 0
            
            array.clear(xz)
            array.clear(volSub)
            array.clear(rang)

            if array.size(sVol) > 0 
                array.clear(sVol)
        

        for n = 0 to 4 + loopCount

            array.push(xz, close[n])
            array.push(volSub, volume[n])
            array.push(rang, high[n])
            array.push(rang, low[n])
            
        for n = 4 + loopCount to 0
        
            if not na(tvsVol)
                array.push(sVol, tvsVol[n])
       
        if array.size(vol) > 25 and array.get(binTra, 0) == false
            if array.get(vol, array.size(vol) - 1) >= array.percentile_linear_interpolation(vol, 90)
                
                array.push(pNl, close)
                array.push(bar, bar_index)
                array.set(binTra, 0, true)

        if array.get(binTra, 0) == true
            if bar_index == array.get(bar, array.size(bar) - 1) + pCalculation
                
                ret = switch log
                    
                    true  => math.log(close / array.get(pNl, array.size(pNl) - 1))
                    false => (close / array.get(pNl, array.size(pNl) - 1) - 1)
                
                array.push(fin, ret * 100)
                array.set(binTra, 0, false)
                    
        for i = array.size(vol) - 1 to array.size(vol) - 5 - loopCount
            
            if array.get(vol, i) >= array.percentile_linear_interpolation(vol, 90)
                array.push(hold, 1)
        
            if i == array.size(vol) - 5 - loopCount
                if array.sum(hold) == 5 + loopCount
                    if loopCount == 0

                        array.push(xy, line.new(bar_index - array.size(xz) + 1, X + stDev, bar_index, Y + stDev, color = #00ffff))
                        array.push(xy, line.new(bar_index - array.size(xz) + 1, X - stDev, bar_index, Y - stDev, color = #00ffff))
                        array.push(xy, line.new(bar_index - array.size(xz) + 1, X + stDev, bar_index - array.size(xz) + 1, X - stDev, color = #00ffff))
                        array.push(xy, line.new(bar_index, Y + stDev, bar_index, Y - stDev, color = #00ffff))
                        array.push(xyfill, linefill.new(array.get(xy, array.size(xy) - 1), array.get(xy, array.size(xy) - 2), color.new(#00ffff, 75)))
                        
                        array.push(miniLab, label.new(bar_index[2], math.max(X + stDev, Y + stDev) + atr, text = "Volume: " + str.tostring(array.sum(volSub), format.volume)
                                                     
                                                     + "\nσ: "    + str.tostring(array.stdev(xz, false), format.mintick) 
                                                     + "\nHigh: " + str.tostring(array.max  (rang), format.mintick) 
                                                     + "\nLow: "  + str.tostring(array.min  (rang), format.mintick)
                                                     +"\nRange: " + str.tostring(array.range(rang), format.mintick),
                                                     style = label.style_label_center, 
                                                     color = color.new(#00ffff, 50), 
                                                     textcolor = color.white,
                                                     size = size.small
                                                     
                                                     ))
                        
                        if array.sum(sVol) != 0 

                            label.set_text(array.get(miniLab, array.size(miniLab) - 1), label.get_text(array.get(miniLab, array.size(miniLab) - 1)) + 
                                 "\nShort Volume: " + str.tostring(array.sum(sVol), format.volume))
    
                        loopCount += 1
                    
                    else

                        line.set_xy1(array.get(xy, array.size(xy) - 4), bar_index - array.size(xz) + 1, X + stDev)
                        line.set_xy2(array.get(xy, array.size(xy) - 4), bar_index, Y + stDev)
                        line.set_xy1(array.get(xy, array.size(xy) - 3), bar_index - array.size(xz) + 1, X - stDev)
                        line.set_xy2(array.get(xy, array.size(xy) - 3), bar_index, Y - stDev)
                        line.set_xy1(array.get(xy, array.size(xy) - 2), bar_index - array.size(xz) + 1, X + stDev)
                        line.set_xy2(array.get(xy, array.size(xy) - 2), bar_index - array.size(xz) + 1, X - stDev)
                        line.set_xy1(array.get(xy, array.size(xy) - 1), bar_index, Y + stDev)
                        line.set_xy2(array.get(xy, array.size(xy) - 1), bar_index, Y - stDev)
                        label.set_xy(array.get(miniLab, array.size(miniLab) - 1), math.round(math.avg(bar_index - array.size(xz) + 1, bar_index)), math.max(X + stDev, Y + stDev) + atr)
                        
                        label.set_text(array.get(miniLab, array.size(miniLab) - 1), "Volume: " + str.tostring(array.sum(volSub), format.volume) 
                                             
                                             + "\nσ: "    + str.tostring(array.stdev(xz, false), format.mintick)                                                     
                                             + "\nHigh: " + str.tostring(array.max(rang), format.mintick) 
                                             + "\nLow: "  + str.tostring(array.min(rang), format.mintick)
                                             +"\nRange: " + str.tostring(array.max(rang) - array.min(rang), format.mintick)

                                             )
                        
                        if array.sum(sVol) != 0 
                        
                            label.set_text(array.get(miniLab, array.size(miniLab) - 1), label.get_text(array.get(miniLab, array.size(miniLab) - 1)) + 
                                 "\nShort Volume: " + str.tostring(array.sum(sVol), format.volume))


                        
                        loopCount += 1
                
                if array.size(hold) > 0
                    array.clear(hold)
    

            
    if loopCount == loopCount[5]
        loopCount := 0

    if array.size(vol) > 1
        
        
        Q1 := array.percentile_linear_interpolation(vol, 25)
        Q2 := array.median(vol)
        Q3 := array.percentile_linear_interpolation(vol, 75)
        p9 := array.percentile_linear_interpolation(vol, 90)
        Q4 := array.max(vol)


        bool v1 =                  volume < Q1
        bool v2 = volume >= Q1 and volume < Q2
        bool v3 = volume >= Q2 and volume < Q3
        bool v4 = volume >= Q3 and volume < p9
        var label [] quarLab = array.new_label()
        
        array.push(quarLab, label.new(bar_index, close >= open ? high : low, 
            
             v1                           ?  "1"  :
             v2                           ?  "2"  :
             v3                           ?  "3"  :
             v4                           ?  "p9" :
                                             "4"  ,
             
             color = color.new(color.white, 100), 
             style = close >= open ? label.style_label_down : label.style_label_up, 
             textcolor =                 
             
             v1                           ?  c1  :
             v2                           ?  c2  :
             v3                           ?  c3  :
             v4                           ?  c4  :
                                             c5  
            
            
             ))
        
        if la == false
            if array.size(quarLab) > 15
                label.delete(array.shift(quarLab))


        
    if barstate.islastconfirmedhistory

        array.sort(fin, order.ascending)
        var float [] dn = array.new_float()
        var float [] up = array.new_float()
        

        if array.size(fin) > 0
            if array.get(fin, 0) <= 0
                for i = 1 to array.size(fin) - 1
                    if array.get(fin, i - 1) <= 0 and array.get(fin, i) > 0
                        for x = 0 to i - 1
                            array.push(dn, array.get(fin, x))
                        for x = i to array.size(fin) - 1
                            array.push(up, array.get(fin, x))
                            
                        break
            
            else if array.get(fin, 0) > 0 
                for i = 0 to array.size(fin) - 1
                    array.push(up, array.get(fin, i) )
            else if array.get(fin, array.size(fin) - 1) <= 0
                for i = 0 to array.size(fin) - 1
                    array.push(dn, array.get(fin, i) )                   
                    
            
        if array.size(dn) > 0
            for n = 0 to array.size(dn) - 1
                if n < array.size(dn) - 1
                    if array.get(dn, n) == 0
                        array.remove(dn, n)
        
        
        var table stats = na
        
        
        tab := table.new(position.top_right, 1, 1, border_color = color.white, frame_color = color.white, border_width = 1, frame_width = 1)
        stats := table.new(position.bottom_right, 50, 50, border_width = 1, frame_width = 1, border_color = color.white, frame_color = color.white)
        
        condQuar = showIns == false
        
        table.cell(stats, 0, 0, text = "Volume Percentiles " , bgcolor = color.new(color.white, 50), text_color = #000000)
        table.cell(stats, 0, 1, text = "First Quartile: "  + str.tostring(array.percentile_linear_interpolation(vol, 25), format.volume),  bgcolor = color.new(c1, 50), text_color = color.white)
        table.cell(stats, 0, 2, text = "Second Quartile: " + str.tostring(array.median(vol), format.volume),  bgcolor = color.new(c2, 50), text_color = color.white)
        table.cell(stats, 0, 3, text = "Third Quartile: "  + str.tostring(array.percentile_linear_interpolation(vol, 75), format.volume),  bgcolor = color.new(c3, 50), text_color = color.white)
        table.cell(stats, 0, 4, text = "90 Percentile : "  + str.tostring(array.percentile_linear_interpolation(vol, 90), format.volume),  bgcolor = color.new(c4, 50), text_color = color.white)
        table.cell(stats, 0, 5, text = "Fourth Quartile : " + str.tostring(math.round(array.max(vol)), format.volume),                     bgcolor = color.new(c5, 50), text_color = color.white)

        table.cell(stats, condQuar ? 0 : 1, condQuar ? 6  : 0, text = "Dispersion" , bgcolor = color.new(color.white, 50), text_color = #000000)
        table.cell(stats, condQuar ? 0 : 1, condQuar ? 7  : 1, text = "Q2 - Q1: " + str.tostring(Q2 - Q1, format.volume), bgcolor = color.new(#5d606b, 50), text_color = color.white, text_halign = text.align_left)
        table.cell(stats, condQuar ? 0 : 1, condQuar ? 8  : 2, text = "Q3 - Q2: " + str.tostring(Q3 - Q2, format.volume), bgcolor = color.new(#434651, 50), text_color = color.white, text_halign = text.align_left)
        table.cell(stats, condQuar ? 0 : 1, condQuar ? 9  : 3, text = "Q4 - Q3: " + str.tostring(Q4 - Q3, format.volume), bgcolor = color.new(#2a2e39, 50), text_color = color.white, text_halign = text.align_left)
        table.cell(stats, condQuar ? 0 : 1, condQuar ? 10 : 4, text = "Quartile Deviation: "  + str.tostring((Q3 - Q1) / 2, format.volume), bgcolor = color.new(#131722, 50), text_color = color.white, text_halign = text.align_left)
        table.cell(stats, condQuar ? 0 : 1, condQuar ? 11 : 5, text = "Interquartile Range: " + str.tostring(Q3 - Q1, format.volume), bgcolor = color.new(#000000, 50), text_color = color.white, text_halign = text.align_left)

        table.cell(stats, condQuar ? 0 : 2, condQuar ? 12 : 0, text = "If Volume Exceeds 90th Percentile \n(Flat Returns Excluded)" , bgcolor = color.new(color.white, 50), text_color = #000000)
        table.cell(stats, condQuar ? 0 : 2, condQuar ? 13 : 1, text = "Avg. " + str.tostring(pCalculation, "#") + " Bar PnL: " + str.tostring(array.avg(fin), format.percent) , bgcolor = color.new(#5d606b, 50), text_color = color.white, text_halign = text.align_left)
        table.cell(stats, condQuar ? 0 : 2, condQuar ? 14 : 2, text = "Avg. " + str.tostring(pCalculation, "#") + " Bar Pos. Return: " + str.tostring(array.avg(up), format.percent) , bgcolor = color.new(#434651, 50), text_color = color.white, text_halign = text.align_left)
        table.cell(stats, condQuar ? 0 : 2, condQuar ? 15 : 3, text = "Avg. " + str.tostring(pCalculation, "#") + " Bar Neg. Return: " + str.tostring(array.avg(dn), format.percent) , bgcolor = color.new(#2a2e39, 50), text_color = color.white, text_halign = text.align_left)
        table.cell(stats, condQuar ? 0 : 2, condQuar ? 16 : 4, text = "# of Pos. Returns: " + str.tostring(array.size(up), "#") + " (" + str.tostring(array.size(up) / array.size(fin) * 100, format.percent) + ")", bgcolor = color.new(#131722, 50), text_color = color.white, text_halign = text.align_left)
        table.cell(stats, condQuar ? 0 : 2, condQuar ? 17 : 5, text = "# of Neg. Returns: " + str.tostring(array.size(dn), "#") + " (" + str.tostring(array.size(dn) / array.size(fin) * 100, format.percent) + ")", bgcolor = color.new(#000000, 50), text_color = color.white, text_halign = text.align_left)


        if showIns == true 
            if quar == false
                var table midRight = table.new(position.middle_right, 10, 10, bgcolor = na)
                table.cell(midRight, 0, 0, text = "▮ = Higher Volume" ,  text_color = color.lime)
                table.cell(midRight, 0, 1, text = "▮ = Lower Volume " ,  text_color = color.red)
            table.cell(tab, 0, 0, text = "In Chart Settings, Hide TradingView Plotted Candlesticks ↑", text_size = size.small, bgcolor = color.new(#f06292, 50), text_color = color.white)


    if barstate.islast
        
        
        var label [] y  = array.new_label()
        var line  [] y1 = array.new_line()
        color        c  =   
                
                 volume < Q1                   ? color.new(c1, 75) :
                 volume >= Q1 and volume < Q2  ? color.new(c2, 75) : 
                 volume >= Q2 and volume < Q3  ? color.new(c3, 75) :
                 volume >= Q3 and volume < p9  ? color.new(c4, 75) :
                                                 color.new(c5, 75) 
        
        
        color cFin = switch quar
        
            false                                => colCond
            true                                 => c
        
        if array.size(y) == 0
        
        
            array.push(y, label.new(bar_index + 2, close >= open ? high : low, color = color.new(cFin, 75),
                
                 text      = "This Bar Has Higher Volume Than \n" + str.tostring(array.percentrank(vol, array.size(vol) - 1), format.percent)
                                     + "\n Of Intervals",
                 style     = label.style_label_left,
                 textcolor = color.white           , 
                 size      = size.small            ,
                 tooltip   = str.tostring(100 - array.percentrank(vol, array.size(vol) - 1), format.percent)
                                     + " Of Intervals Had Greater Volume Than This Bar (:"
                 
                     ))
                     
            array.push(y1, line.new(bar_index, label.get_y(array.get(y, array.size(y) - 1)), 
                                             bar_index + 2, 
                                             label.get_y(array.get(y,   array.size(y) - 1)),
                                             style = line.style_dashed, 
                                             color = color.new(cFin, 75)
                                             
                                             ))
            
        else 
            
            label.set_xy     ( array.get(y, array.size(y)  - 1), bar_index + 2, close >= open ? high : low)
            label.set_color  ( array.get(y, array.size(y)  - 1), color.new(cFin, 75))
            line.set_xy1     ( array.get(y1,array.size(y1) - 1), bar_index, label.get_y(array.get(y, array.size(y) - 1)))
            line.set_xy2     ( array.get(y1,array.size(y1) - 1), bar_index + 2, label.get_y(array.get(y, array.size(y) - 1)))
            line.set_color   ( array.get(y1,array.size(y1) - 1), color.new(cFin, 75))
            label.set_tooltip( array.get(y, array.size(y1) - 1), str.tostring(100 - array.percentrank(vol, array.size(vol) - 1), format.percent)
                                     + " Of Intervals Had Greater Volume Than This Bar (:")
            label.set_text   ( array.get(y, array.size(y) - 1), "This Bar Has Higher Volume Than \n" + str.tostring(array.percentrank(vol, array.size(vol) - 1), format.percent)
                                     + "\n Of Intervals")
                                     
        var line     [] sten     = array.new_line()
        var linefill [] stenfill = array.new_linefill()
        
        

        
        if start() 
         and anch == true 
          and s >= array.get(tim, 0)
                    
            array.push(sten, line.new(math.round(s), close, math.round(s), close + syminfo.mintick, xloc = xloc.bar_time, color = color.white, width = 2, extend = extend.both))
            array.push(sten, line.new(math.round(e), close, math.round(e), close + syminfo.mintick, xloc = xloc.bar_time, color = color.white, width = 2, extend = extend.both))
            array.push(stenfill, linefill.new(array.get(sten, array.size(sten) - 1), array.get(sten, array.size(sten) - 2), color.new(color.white, 95)))
            if array.size(sten) > 2
                line.delete(array.shift(sten))
            
            if array.size(stenfill) > 1
                linefill.delete(array.get(stenfill, array.size(stenfill) - 1))
        

finCol() => 
    

    
    if array.size(vol) > 1
    
        q1 = array.percentile_linear_interpolation(vol, 25)
        q2 = array.median(vol)
        q3 = array.percentile_linear_interpolation(vol, 75)
        p9 = array.percentile_linear_interpolation(vol, 90)
        q4 = array.max(vol)
        
        if volume >= 0       and volume < q1
            c1
        else if volume >= q1 and volume < q2
            c2
        else if volume >= q2 and volume < q3
            c3
        else if volume >= q3 and volume < p9
            c4
        else if volume >= p9 and volume <= q4
            c5

VWAP() =>
    

    var float  y  = na
    var float  y1 = na
    var float  y2 = na
    
    if start()[1] == false
        
        if start() == true 
    
            y  := hlc3 * volume            
            y1 := volume                
            y2 := volume * math.pow(hlc3, 2)

    if start()[1] == true
       
        y  := hlc3 * volume + y[1]
        y1 := volume + y1[1]
        y2 := volume * math.pow(hlc3, 2) + y2[1]

    float middle = y / y1
    
    float vaR = y2 / y1 - math.pow(middle, 2)
    
    vaR := vaR < 0 ? 0 : vaR
    
    float stDevX = math.sqrt(vaR)
    
    float upper = middle + stDevX * 2
    
    float lower = middle - stDevX * 2
    
    [middle, upper, lower]

[m,u,l] = VWAP()

Z  = plot(anch == true ? m : na, title = "Anchored VWAP", color = start() ? color.orange : na)
Z1 = plot(anch == true ? u : na, title = "Upper Band",    color = start() ? color.lime   : na)
Z2 = plot(anch == true ? l : na, title = "Lower Band",    color = start() ? color.lime   : na)
fill(Z1, Z2, color = anch == true and start() ?  color.new(color.lime, 80) : na)


color colr = switch show 
    
    "Quartile Volume" => colCond
    =>                            na
    
color colF = switch quar
    
    false => colr
    true  => finCol()
    
plotcandle (

         open, 
         high, 
         low, 
         close, 
         color       = show == "Gaps" and close >= open ? color.lime : show == "Gaps" and close < open ? color.red : colF,
         wickcolor   = show == "Gaps" and close >= open ? color.lime : show == "Gaps" and close < open ? color.red : colF,
         bordercolor = show == "Gaps" and close >= open ? color.lime : show == "Gaps" and close < open ? color.red : colF
         
         )

Overview

Depending on the active mode, it plots synthetic candle structures, historical congestion zones, gap visualization boxes, or bar coloring based on volume quartiles. Input settings allow traders to switch datasets, toggle automated or custom threshold parameters, configure gap percentage filters, and calculate percentile gain or loss metrics. Real-time calculations and dynamic visual updates cause historical elements to repaint on live bars.

Details

Published by

regalouisei on GitHub

Code credit

KioseffTrading, as written in the script's header

Type

Indicator, Pine Script v5

Draws

On the price chart

Category

Volume, Support & resistance, Candlestick patterns

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

  • Signals can change on the live bar or after it closes (repainting)

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
DatasetstringQuartile Volumeshow
Improve Loading Time?boolfalsefast
Auto Range US Candles? Or User-Defined?stringAutotra
Reverse Candle Price Movefloat22rev
Trend Candle Price Movefloat44tre
Segment Range US Bars By Date?boolfalseranShow
Show Trend/Reverse Levels?booltruelevShow
Show Warning?booltruewarn1
Box Text Size (Auto Increases Chart Lag)stringTinysz
Number of Congestion Areas to Show (0 = None)int7treShow
Move Current Range US Bar to Levels Section?booltruemove
Auto Volume Aggregation Candles? Or User-Defined?stringAutotra1
Show all 39 settings
SettingTypeDefaultVariable
Required Volumeint1000000volInt
Segment Vol. Aggregation Bars By Date?boolfalsevShow
Box Text Size (Auto Increases Chart Lag)stringTinysz1
Show Largest Increases and Decreases?booltrueshowAl
Number of Largest Volume Agg. Increases to Showint15showUp
Number of Largest Volume Agg. Decreases to Showint15showDn
Show Warning?booltruewarn
Percentage Difference For Gap to Appearfloat0perG
Hide Gaps When Price Deviates by Percentagefloat-1old
Delete Filled Gaps?boolfalsedel
Visualize Gaps?boolfalsevis
Recent Unfilled Gaps to Show (Table)int5rec
Low Volume Quartile Volume Colorcolorcolor.redcolE
High Volume Quartile Volume Colorcolorcolor.limecolE1
% Gain / Loss After 'n' Bars for Exceeded 90th Percentileint10pCalculation
Use Log Returns?booltruelog
Show Quartile on Bar?boolfalsela
Color Bars by Volume Quartilesboolfalsequar
First Quartile Colorcolor#a5d6a7c1
Second Quartile Colorcolor#81c784c2
Third Quartile Colorcolor#66bb6ac3
90th Percentilecolor#388e3cc4
Fourth Quartile Colorcolor#1b5e20c5
Show Instructions?booltrueshowIns
Show Anchored VWAPbooltrueanch
Anchored VWAP Starttimetimestamp("20 Jul 1872 00:00 +0300")s
Anchored VWAP Endtimetimestamp("20 Jul 2023 00:00 +0300")e
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

This overlay indicator draws rounded psychological price levels and optional PVSRA vector candle colors on the price chart. It plots quarter, half, and whole levels from a user-set rounding value, with separate color, line style, and width for each. Vector col

Indicator v5 Support & resistanceVolume
Updated 5 months ago · None stated GitHub repository of Level Theory + Vector Candles
2 stars

This overlay approximates order-book liquidity from intrabar OHLCV buckets because true depth-of-market data is unavailable. It paints a decaying volume heatmap around price and labels absorption, exhaustion, rejection, and momentum when wick, body, delta, and

Indicator v6 VolumeSupport & resistance
Updated 4 months ago · None stated GitHub repository of Bookmap Liquidity Mapper [TReset]
2 stars

Ghost Zone v9 GTI Signals v18 is an overlay technical indicator designed to replicate Ghost Trade Pro methodology. It calculates anchored Supertrend channels, previous weekly close levels, fair value gaps, and volume profile high-volume nodes. The script evalu

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 6 months ago · None stated GitHub repository of Ghost Zone v9 GTI Signals v18

HTF Candles & Pivots

by itmakesyousick
2 stars

This overlay indicator draws higher-timeframe candles as boxes on the price chart, with a selectable timeframe, candle thickness, wicks, history, vertical divisions, and optional fill for negative candles. It can plot pivot levels, including an optional centra

Indicator v5 Candlestick patternsSupport & resistance
Updated 3 years ago · None stated GitHub repository of HTF Candles & Pivots
2 stars

The LSD-15 indicator detects liquidity sweeps on 15-minute crypto charts by identifying price movements that exceed a threshold from swing highs and lows. It plots swing high and low lines on the price chart and highlights sweep candles in color. Multiple conf

Indicator v5 ScalpingSupport & resistance Repaints
Updated 7 months ago · None stated GitHub repository of LSD-15 Liquidity Sweep Detector
1 stars

This indicator plots bullish and bearish order-block boxes on the price chart. It marks the prior candle when the current bar engulfs it and volume exceeds a twenty-bar average times a multiplier, then stores the zone in a matrix. Volume threshold and box colo

Indicator v5 SMC / ICT / price actionSupport & resistance Repaints
Updated 6 months ago · MIT GitHub repository of Order Blocks Matrix - Castle Trade

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers