'Only 10 zones should be displayed on the screen, but it displays two more

First of all, test the code on BINANCE:BTCUSDT Daily timeframe. I marked the zones with blue and yellow barcolors, so you can see them better.

The issue is that when you select 10 number of zones in inputs (default) and Do not shrink option (default), the code is being drunk and displays two more zones which are not even the next ones, but two candles after them. I believe it's because of the separate arrays for the bullish and bearish zones. It must be recoded in some way that it displays the correct zones. I marked the zones that should be displayed in the picture below.

Edit:

It actually displays 5 red zones and 5 green zones I think. I expect it to display 10 zones, no matter they are bullish or bearish.

Current

enter image description here

Expected

https://www.tradingview.com/x/4DOGjqSs/

//@version=5
indicator("Imb", overlay = true, max_boxes_count = 500, max_bars_back = 500)

// ———————————————————— Constants {
// ————— Colors
var color GREEN         = color.green
var color RED           = color.red
var color BLUE          = color.blue
var color YELLOW        = color.yellow

// ————— Constants used in inputs
var string G1 = "Show"
var string G2 = "Hide"

var string IMB1 = "Shrink when mitigated"
var string IMB2 = "Do not shrink"
// }

// ———————————————————— Inputs {
// ————— Imbalance Zones
var GRP3 = "Imbalance Zones"
bool showImbalance = input.bool(true, "Show Imbalance/Fair Value Gaps", inline = "30", group = GRP3)
int numberOfZonesInput = input.int(10, "# Zones", inline = "31", group = GRP3)
bool updateZonesWithPriceMovement = input.string(IMB2, "", inline = "32", options = [IMB1, IMB2], group = GRP3) == IMB1
color bullishImbColorInput = input.color(GREEN, "🠅", inline = "32", group = GRP3)
color bearishImbColorInput = input.color(RED, "🠇", inline = "32", group = GRP3)
int imbTranspInput = input.int(80, "Transparency", inline = "32", group = GRP3)
// }

// ———————————————————— Imbalance/Fair Value Gaps {
var line bullishImbOpen = na
var line bullishImbLow = na

var line bearishImbOpen = na
var line bearishImbHigh = na

bullishImb = low > high[2]
bearishImb = high < low[2]

barcolor(bullishImb ? BLUE : bearishImb ? YELLOW : na, offset = -1, title = "Imbalance Bar Color")

plotshape(bullishImb ? bullishImb : na, style = shape.triangleup, location = location.belowbar, color = GREEN, offset = -1, size = size.tiny)
plotshape(bullishImb ? bearishImb : na, style = shape.triangledown, location = location.abovebar, color = RED, offset = -1, size = size.tiny)

var box[] bullishImbBox = array.new_box()
var box[] bearishImbBox = array.new_box()

var color bullColor = color.new(bullishImbColorInput, imbTranspInput)
var color bearColor = color.new(bearishImbColorInput, imbTranspInput)

if bullishImb and showImbalance
    array.push(bullishImbBox, box.new(left = time[1], top = low, right = time, bottom = high[2], extend = extend.none, xloc = xloc.bar_time, border_color = bullColor, border_style = line.style_dashed, bgcolor = bullColor))
    if array.size(bullishImbBox) + array.size(bearishImbBox) > numberOfZonesInput
        box.delete(array.shift(bullishImbBox))

if bearishImb and showImbalance
    array.push(bearishImbBox, box.new(left = time[1], top = low[2], right = time, bottom = high, extend = extend.none, xloc = xloc.bar_time, border_color = bearColor, border_style = line.style_dashed, bgcolor = bearColor))
    if array.size(bullishImbBox) + array.size(bearishImbBox) > numberOfZonesInput
        box.delete(array.shift(bearishImbBox))

if array.size(bullishImbBox) > 0
    for i = 0 to array.size(bullishImbBox) - 1
        if i <= array.size(bullishImbBox) - 1 and array.size(bullishImbBox) > 0
            t = box.get_top(array.get(bullishImbBox, i))
            b = box.get_bottom(array.get(bullishImbBox, i))
            
            // update right side of the box
            box.set_right(array.get(bullishImbBox, i), time)
            
            if updateZonesWithPriceMovement
                // delete box
                if b >= low
                    box.delete(array.remove(bullishImbBox, i))
                // update box
                else if t >= low
                    box.set_top(array.get(bullishImbBox, i), low)


if array.size(bearishImbBox) > 0
    for i = 0 to array.size(bearishImbBox) - 1
        if i <= array.size(bearishImbBox) - 1 and array.size(bearishImbBox) > 0
            t = box.get_top(array.get(bearishImbBox, i))
            b = box.get_bottom(array.get(bearishImbBox, i))
            
            // update right side of the box
            box.set_right(array.get(bearishImbBox, i), time)
            
            if updateZonesWithPriceMovement
                // delete box        
                if t <= high
                    box.delete(array.remove(bearishImbBox, i))
                // update box
                else if b <= high
                    box.set_bottom(array.get(bearishImbBox, i), high)
// }


Solution 1:[1]

When you pass check and create a new box, if your size exceeds the allowed number of 10 boxes, you delete the earliest created box of the same type, while on the chart it will not necessarily be the first created of two types, the first created can be a different type of box and you will remove the box from the middle. All of your boxes are extended until the end of the series and in your screenshot you can see that boxes 9 and 6 are removed, instead of boxes of the opposite type.

You need to remove the first created box from the common set of two types

if bullishImb and showImbalance
    array.push(bullishImbBox, box.new(left = time[1], top = low, right = time, bottom = high[2], extend = extend.none, xloc = xloc.bar_time, border_color = bullColor, border_style = line.style_dashed, bgcolor = bullColor))
    if array.size(bullishImbBox) + array.size(bearishImbBox) > numberOfZonesInput
        box.delete(array.shift(box.all))

if bearishImb and showImbalance
    array.push(bearishImbBox, box.new(left = time[1], top = low[2], right = time, bottom = high, extend = extend.none, xloc = xloc.bar_time, border_color = bearColor, border_style = line.style_dashed, bgcolor = bearColor))
    if array.size(bullishImbBox) + array.size(bearishImbBox) > numberOfZonesInput
        box.delete(array.shift(box.all))

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 vgladkov