Pivot order block boxes [LM]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © lmatl

//@version=5
indicator('Pivot order block boxes [LM]', overlay=true, max_bars_back=500, max_boxes_count=500)

i_firstShowPivotBoxes = input.bool(true, 'Show first boxes', group='first pivot setting')
i_firstLeft = input.int(20, 'Left', group='first pivot setting')
i_firstRight = input.int(10, 'Right', group='first pivot setting')
i_firstBoxCount = input.int(5, title='Box count', group='first pivot setting')
i_firstPercentageChange = input.int(10, title='Percentage change on the right side of pivot', group='first pivot setting')
i_firstPivotHighColor = input.color(color.green, title='Pivot high color', group='first pivot setting')
i_firstPivotLowColor = input.color(color.red, title='Pivot low color', group='first pivot setting')


i_secondShowPivotBoxes = input.bool(false, 'Show second boxes', group='second pivot setting')
i_secondLeft = input.int(50, 'Left', group='second pivot setting')
i_secondRight = input.int(20, 'Right', group='second pivot setting')
i_secondBoxCount = input.int(5, title='Box count', group='second pivot setting')
i_secondPercentageChange = input.int(10, title='Percentage change on the right side of pivot', group='second pivot setting')
i_secondPivotHighColor = input.color(color.lime, title='Pivot high color', group='second pivot setting')
i_secondPivotLowColor = input.color(color.maroon, title='Pivot low color', group='second pivot setting')

firstBoxHighColor = color.new(i_firstPivotHighColor, 70)
firstBoxLowColor = color.new(i_firstPivotLowColor, 70)

secondBoxHighColor = color.new(i_secondPivotHighColor, 70)
secondBoxLowColor = color.new(i_secondPivotLowColor, 70)

var firstBoxArray = array.new_box()
var secondBoxArray = array.new_box()

f_isUpCandle(_index) =>
    open[_index] <= close[_index]

f_extendArray(_boxArray) =>
    if array.size(_boxArray) > 0
        for _i = array.size(_boxArray) - 1 to 0 by 1
            boxId = array.get(_boxArray, _i)
            box.set_right(boxId, bar_index)

f_pivotHigh(_boxColor, _right, _left, _percentage) =>
    pivotHigh = ta.pivothigh(high, _left, _right)
    if not na(pivotHigh)
        isPercentageChangeEnough = false
        for i = 0 to _right + 1 by 1
            if (pivotHigh - high[i]) / pivotHigh >= _percentage / 100
                isPercentageChangeEnough := true
                break

        if isPercentageChangeEnough
            int candleIndex = _right
            for i = _right to _right + _left by 1
                if f_isUpCandle(i)
                    candleIndex := i
                    break

            rangeLow = low[candleIndex]
            rangeHigh = high[candleIndex]
            b = box.new(bar_index[candleIndex], rangeHigh, bar_index, rangeLow, bgcolor=_boxColor, border_style=line.style_dashed, border_color=_boxColor)
            b

f_pivotLow(_boxColor, _right, _left, _percentage) =>
    pivotLow = ta.pivotlow(low, _left, _right)
    if not na(pivotLow)
        isPercentageChangeEnough = false
        for i = 0 to _right - 1 by 1
            if (low[i] - pivotLow) / pivotLow >= _percentage / 100
                isPercentageChangeEnough := true
                break

        if isPercentageChangeEnough
            int candleIndex = _right
            for i = _right to _right + _left by 1
                if not f_isUpCandle(i)
                    candleIndex := i
                    break

            rangeLow = low[candleIndex]
            rangeHigh = high[candleIndex]

            b = box.new(bar_index[candleIndex], rangeHigh, bar_index, rangeLow, bgcolor=_boxColor, border_style=line.style_dashed, border_color=_boxColor)
            b


// first box pivots
if i_firstShowPivotBoxes
    firstPivotHighBox = f_pivotHigh(firstBoxHighColor, i_firstRight, i_firstLeft, i_firstPercentageChange)
    firstPivotLowBox = f_pivotLow(firstBoxLowColor, i_firstRight, i_firstLeft, i_firstPercentageChange)


    if not na(firstPivotHighBox)
        if array.size(firstBoxArray) == i_firstBoxCount
            box.delete(array.shift(firstBoxArray))
        array.push(firstBoxArray, firstPivotHighBox)

    if not na(firstPivotLowBox)
        if array.size(firstBoxArray) == i_firstBoxCount
            box.delete(array.shift(firstBoxArray))
        array.push(firstBoxArray, firstPivotLowBox)

    f_extendArray(firstBoxArray)


// second pivot levels
if i_secondShowPivotBoxes
    secondPivotHighBox = f_pivotHigh(secondBoxHighColor, i_secondRight, i_secondLeft, i_secondPercentageChange)
    secondPivotLowBox = f_pivotLow(secondBoxLowColor, i_secondRight, i_secondLeft, i_secondPercentageChange)


    if not na(secondPivotHighBox)
        if array.size(secondBoxArray) == i_secondBoxCount
            box.delete(array.shift(secondBoxArray))
        array.push(secondBoxArray, secondPivotHighBox)

    if not na(secondPivotLowBox)
        if array.size(secondBoxArray) == i_secondBoxCount
            box.delete(array.shift(secondBoxArray))
        array.push(secondBoxArray, secondPivotLowBox)

    f_extendArray(secondBoxArray)




