Drawdown Range
// This work is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
// © Trendoscope Pty Ltd
//                                       ░▒             
//                                  ▒▒▒   ▒▒      
//                              ▒▒▒▒▒     ▒▒      
//                      ▒▒▒▒▒▒▒░     ▒     ▒▒          
//                  ▒▒▒▒▒▒           ▒     ▒▒          
//             ▓▒▒▒       ▒        ▒▒▒▒▒▒▒▒▒▒▒  
//   ▒▒▒▒▒▒▒▒▒▒▒ ▒        ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒         
//   ▒  ▒       ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░        
//   ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒▒▒▒▒▒▒▒         
//   ▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒                       
//    ▒▒▒▒▒         ▒▒▒▒▒▒▒                            
//                 ▒▒▒▒▒▒▒▒▒                           
//                ▒▒▒▒▒ ▒▒▒▒▒                          
//               ░▒▒▒▒   ▒▒▒▒▓      ████████╗██████╗ ███████╗███╗   ██╗██████╗  ██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ███████╗
//              ▓▒▒▒▒     ▒▒▒▒      ╚══██╔══╝██╔══██╗██╔════╝████╗  ██║██╔══██╗██╔═══██╗██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔════╝
//              ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒        ██║   ██████╔╝█████╗  ██╔██╗ ██║██║  ██║██║   ██║███████╗██║     ██║   ██║██████╔╝█████╗ 
//             ▒▒▒▒▒       ▒▒▒▒▒       ██║   ██╔══██╗██╔══╝  ██║╚██╗██║██║  ██║██║   ██║╚════██║██║     ██║   ██║██╔═══╝ ██╔══╝  
//            ▒▒▒▒▒         ▒▒▒▒▒      ██║   ██║  ██║███████╗██║ ╚████║██████╔╝╚██████╔╝███████║╚██████╗╚██████╔╝██║     ███████╗
//             ▒▒             ▒                        
//@version=5
indicator('Drawdown Range[Trendoscope]', 'DD[Trendoscope]')

i_numberOfRanges = input.int(20, title='Number of ranges', options=[5, 10, 20, 25, 50, 100], group='Main')
i_percentile = input.bool(true, 'Percentile', group='Main')

i_reference = input.string('ath', title='Reference', options=['ath', 'window'], group='Reference')
i_startTime = input.time(defval=timestamp('01 Jan 2010 00:00 +0000'), title='Start Time', group='Reference')
i_endTime = input.time(defval=timestamp('01 Jan 2099 00:00 +0000'), title='End Time', group='Reference')
inDateRange = time >= i_startTime and time <= i_endTime

i_tablePosition = input.string(defval=position.middle_center, title='Table Position', options=[position.bottom_right, position.bottom_center, position.bottom_left, position.middle_right, position.middle_center, position.middle_left, position.top_right, position.top_center, position.top_left], group='Display')
i_displayRangeHeader = input.bool(true, 'Display Range Header', group='Display')
i_text_size = input.string(size.small, title='Text Size', options=[size.tiny, size.small, size.normal, size.large, size.huge], group='Display', inline='text')
i_headerColor = input.color(color.maroon, title='Header', group='Display', inline='GC')
i_neutralColor = input.color(#FFEEBB, title='Cell', group='Display', inline='GC')

i_presentColor = input.color(color.aqua, title='Present', group='Display', inline='Color')
i_maxColor = input.color(color.green, title='Max', group='Display', inline='Color')
i_minColor = input.color(color.orange, title='Min', group='Display', inline='Color')

f_get_ath_and_drawdown(ath, value) =>
    _ath = ath
    _ath := na(ath) or value > _ath ? value : _ath
    _drawdown = math.round(math.abs(_ath - value) / math.abs(_ath) * 100)
    [_ath, _drawdown]

var DIVISOR = i_numberOfRanges >= 50 ? 10 : 5
var ROWS = i_numberOfRanges / DIVISOR
var COLUMNS = DIVISOR
var CELLRANGE = 100 / i_numberOfRanges
var ROWRANGE = 100 / ROWS
var ath = high
var p_athDistanceRange = array.new_int(i_numberOfRanges, 0)

if i_reference == 'ath' or inDateRange
    var dateStart = str.tostring(year) + '/' + str.tostring(month) + '/' + str.tostring(dayofmonth)
    dateEnd = str.tostring(year) + '/' + str.tostring(month) + '/' + str.tostring(dayofmonth)
    [_ath, _drawdown] = f_get_ath_and_drawdown(ath, high)
    ath := _ath

    index = math.min(math.max(math.round(_drawdown / CELLRANGE), 0), i_numberOfRanges - 1)
    array.set(p_athDistanceRange, index, array.get(p_athDistanceRange, index) + 1)

    var DISPLAY = table.new(position=i_tablePosition, columns=COLUMNS * 2 + 1, rows=ROWS, border_width=1)
    maxRange = array.max(p_athDistanceRange)
    minRange = array.min(p_athDistanceRange)
    for _i = i_numberOfRanges - 1 to 0 by 1
        if minRange != 0
            break
        minRange := array.min(array.slice(p_athDistanceRange, 0, _i))
        minRange

    table.cell(table_id=DISPLAY, column=0, row=0, text=dateStart + ' to ' + dateEnd, bgcolor=color.teal, text_color=color.white, text_size=i_text_size)
    table.cell(table_id=DISPLAY, column=0, row=1, text=syminfo.tickerid, bgcolor=color.teal, text_color=color.white, text_size=i_text_size)
    for _i = 0 to i_numberOfRanges - 1 by 1
        _presentRangeTotal = array.get(p_athDistanceRange, _i)
        _rangeSum = array.sum(p_athDistanceRange)
        _row = (_i - _i % DIVISOR) / DIVISOR
        _columnHeader = 2 * (_i % DIVISOR)
        _column = _columnHeader + 1
        _range_start = ROWRANGE * _row + CELLRANGE * _columnHeader / 2
        _range_next = ROWRANGE * _row + CELLRANGE * (_columnHeader / 2 + 1)
        _rangePercentage = math.round(_presentRangeTotal / _rangeSum * 100, 2)

        _before = array.slice(p_athDistanceRange, 0, _i + 1)
        _rangePercentile = math.round(array.sum(_before) * 100 / _rangeSum, 2)

        _cellColor = index == _i ? i_presentColor : maxRange == _presentRangeTotal ? i_maxColor : minRange == _presentRangeTotal ? i_minColor : i_neutralColor
        _percentDisplay = i_percentile ? _rangePercentile : _rangePercentage
        if _percentDisplay != 0 and (_percentDisplay != 100 or _cellColor != i_neutralColor)
            if i_displayRangeHeader
                headerText = (i_percentile ? '0' : str.tostring(_range_start)) + ' - ' + str.tostring(_range_next)
                table.cell(table_id=DISPLAY, column=_columnHeader + 1, row=_row, text=headerText, bgcolor=i_headerColor, text_color=color.white, text_size=i_text_size)
            table.cell(table_id=DISPLAY, column=_column + 1, row=_row, text=str.tostring(_percentDisplay), bgcolor=_cellColor, text_color=color.black, text_size=i_text_size)

