Titans Price Incidence
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © mmmarsh

//@version=5
indicator("Price Incidence", overlay=true)

//Inputs
degree=input.int(defval=100, title='Price intervals as a ratio of minimum tick', options=[20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000])
lookback=input.int(defval=200, title='Bars to look back', options=[50,100,150,200,250,300,350,400,450,500])
historical=input.int(defval=0,title='Reference candle to start study',step=1)

//Price range
highestHigh=ta.highest(high,lookback)
lowestLow=ta.lowest(low,lookback)

//Colour setting
transparency(targetCount,averageCount) => targetCount>=averageCount ? 50 : 80

//Check precision
minTick=syminfo.mintick
precisionCurrent=0
for i=0 to 6 by 1
    if math.pow(10,i)==1/minTick
        precisionCurrent:=i
        break 
precisionNew=0
for i=0 to 6 by 1
    if math.pow(10,i)>degree
        precisionNew:=i-1
        break

//Set minimums
rangeLow=0.0
rangeHigh=0.0
rangeInterval=0.0
if precisionNew<precisionCurrent
    rangeLow:=math.round(lowestLow[0],precisionCurrent-precisionNew)
    rangeHigh:=math.round(highestHigh[0],precisionCurrent-precisionNew)
    rangeInterval:=minTick*degree
if precisionNew>=precisionCurrent
    rangeLow:=math.round(lowestLow[0]/math.pow(10,(precisionNew-precisionCurrent)))*math.pow(10,precisionNew-precisionCurrent)
    rangeHigh:=math.round(highestHigh[0]/math.pow(10,(precisionNew-precisionCurrent)))*math.pow(10,precisionNew-precisionCurrent)
    rangeInterval:=math.pow(10,precisionNew-precisionCurrent)*(degree/math.pow(10,precisionNew))
rangeCovered=rangeHigh-rangeLow
totalIntervals=int(rangeCovered/rangeInterval)+2

//Run on last bar
if barstate.islast
//Set price intervals
    priceLevel=array.new_float(0)
    for j=0 to totalIntervals by 1
        array.push(priceLevel,rangeLow+j*rangeInterval)

//Incidence recording
    counter=array.new_float(totalIntervals,0)
    incidenceTotal=0
    for k=0 to totalIntervals-1 by 1
        incidence=0
        for j=historical to lookback by 1
            if high[j]>array.get(priceLevel,k) and high[j]<array.get(priceLevel,(k+1))
                incidence:=incidence+1
            if low[j]>array.get(priceLevel,k) and low[j]<array.get(priceLevel,(k+1))
                incidence:=incidence+1    
        array.set(counter,k,incidence)
        incidenceTotal:=incidenceTotal+incidence
    incidenceAverage=incidenceTotal/totalIntervals

//Plot result
    for m=0 to totalIntervals-1 by 1
        box.new(bar_index[array.get(counter,m)+historical],array.get(priceLevel,m),bar_index[historical],array.get(priceLevel,m+1),border_color=color.white, border_width=0, bgcolor=color.rgb(22, 222, 122, transparency(array.get(counter,m),incidenceAverage)))

plot(minTick)
