Simple Range
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © finallynitin
//credits to theapextrader7, wrpteam2020, LazyBear, alpine_trader & TheScrutiniser 

//@version=5
indicator('Simple Range', overlay=false)

//Display Inputs
string GRP0             = "════════ Display Options ═════════"
toggleDarkColors = input(title="Dark Mode", defval=false, group=GRP0)
toggleADR = input(title="Plot ADR", defval=false, group=GRP0)
toggleSQZ = input(title="Display Squeeze Colors", defval=true, group=GRP0)
toggleBB = input(title="Display Big Bar Shapes", defval=true, group=GRP0)


//Length Inputs
string GRP1             = "════════ Numerical Inputs ═════════"
NRlen = input.int(title='Narrow Range', defval=7, group=GRP1)
WRlen = input.int(title='Wide Range', defval=20, group=GRP1)
BBlen = input.int(title='Big Bars % Range', defval=5, group=GRP1)
BBvol = input.int(title='Big Bars Volume', defval=500000, group=GRP1)
ADRlen = input.int(20, title='ADR length', group=GRP1)


//Squeeze Colors
string GRP2             = "════════ Squeeze Options ═════════"
colorRed = input.color(color.red, 'High-compression Squeeze', group=GRP2)
//colorRed = toggleDarkColors ? color.new(color.red,80) : color.new(color.red,20)

colorOrange = input.color(color.orange, 'Mid-compression Squeeze', group=GRP2)
colorYellow = input.color(color.yellow, 'Low-compression Squeeze', group=GRP2)
colorGreen = input.color(color.green, 'Fired Squeeze', group=GRP2)
colorBlue = input.color(color.blue, 'No Squeeze', group=GRP2)


//Range Colors
string GRP3             = "════════ Range Options ═════════"
colorgreyer = toggleDarkColors ? input(color.new(color.white,20), "Neutral-range (dark-mode)", group=GRP3) : input(color.new(color.black,0), "Neutral-range (light-mode)", group=GRP3)
colorOranger = input.color(color.orange, 'Narrow Range', group=GRP3)
colorGreener = input.color(color.green, 'Wide Range up', group=GRP3)
colorRedder = input.color(color.red, 'Wide Range down', group=GRP3)


//--------00 Range------
Range = (high - low) * 100 / high

//--------01 Narrow Range------
//original concept from Thomas Bulkowski
//modified from "NR4 & NR7 Indicator" script by theapextrader7 https://in.tradingview.com/script/pXcafX0I-NR4-NR7-Indicator/

NR_Check(range_1) =>
    range_1 < ta.lowest(range_1, NRlen - 1)[1] ? true : false

range_NR_Prep = high - low
range_isCurrentLowest = NR_Check(range_NR_Prep)


//--------02 Wide Range------
//modified from "WR - BC Identifier" script by wrpteam2020 https://in.tradingview.com/script/dOmlAmFZ-WR-BC-Identifier/

//C_Body = math.abs(close - open)
C_Bullish = close > open
C_Bearish = close < open

// Find the maximum percentage range in the last 20 bars
max_percentage_range = ta.highest(Range, 20)

// Determine if the current bar has the maximum percentage range in the last 20 bars
range_isCurrentHighest = Range == max_percentage_range


//--------PLOT------

//iff_1 = (showbb ? bcu : na) ? colorGreener : colorgreyer
//iff_2 = (showbb ? bcd : na) ? colorRedder : iff_1
iff_3 = range_isCurrentHighest and C_Bearish ? colorRedder : colorgreyer
iff_4 = range_isCurrentHighest and C_Bullish ? colorGreener : iff_3
rcolor = range_isCurrentLowest ? colorOranger : iff_4

// Plot histogram for wide range bars
plot(range_isCurrentHighest or range_isCurrentLowest? Range : na, title="Uncommon Range Bars", color=rcolor, style=plot.style_histogram, linewidth=4)
plot(not range_isCurrentHighest and not range_isCurrentLowest? Range : na, title="Common Range Bars", color=rcolor, style=plot.style_histogram, linewidth=1)


//--------03 Big Bars------
// this identifies big bars i.e. which are greater than equal to a pre-defined (default is 5%) high to low range
// on higher than a pre-defined volume level (default is 500000)

bbrange = math.abs(ta.roc(close, 1)) >= BBlen
bbvolume = volume >= BBvol

plotshape(toggleBB ? bbrange and bbvolume :na, style=shape.circle, color=colorgreyer, location=location.top)


//--------04 SQUEEZE------
// original concept from John Carter's book "Mastering the Trade"
// based on LazyBear's script (Squeeze Momentum Indicator) https://in.tradingview.com/script/nqQ1DT5a-Squeeze-Momentum-Indicator-LazyBear/

ma = ta.sma(close, 20)
devBB = ta.stdev(close, 20)
devKC = ta.sma(ta.tr, 20)


//Bollinger 2x
upBB = ma + devBB * 2
lowBB = ma - devBB * 2

//Keltner 2x
upKCWide = ma + devKC * 2
lowKCWide = ma - devKC * 2

//Keltner 1.5x
upKCNormal = ma + devKC * 1.5
lowKCNormal = ma - devKC * 1.5

//Keltner 1x
upKCNarrow = ma + devKC
lowKCNarrow = ma - devKC

sqzOnWide = lowBB >= lowKCWide and upBB <= upKCWide  //Low-compression Squeeze: YELLOW
sqzOnNormal = lowBB >= lowKCNormal and upBB <= upKCNormal  //Mid-compression Squeeze: ORANGE
sqzOnNarrow = lowBB >= lowKCNarrow and upBB <= upKCNarrow  //High-compression Squeeze: RED
sqzOffWide = lowBB < lowKCWide and upBB > upKCWide  //Fired Squeeze: GREEN
noSqz = sqzOnWide == false and sqzOffWide == false  //No Squeeze: BLUE

sq_color = noSqz ? colorBlue : sqzOnNarrow ? colorRed : sqzOnNormal ? colorOrange : sqzOnWide ? colorYellow : colorGreen

bgcolor(toggleSQZ ? toggleDarkColors? color.new(sq_color, 30): color.new(sq_color, 80): na)


//--------05 ADR%------
// original idea by alpine_trader
// Modified from "ADR% - Average Daily Range % by MikeC" script by TheScrutiniser https://in.tradingview.com/script/6KVjtmOY-ADR-Average-Daily-Range-by-MikeC-AKA-TheScrutiniser/

//var table rangeTable = table.new(position=position.middle_right, columns=2, rows=2, frame_color=color.gray, frame_width=1, border_width=1, border_color=color.black)

dhigh = request.security(syminfo.tickerid, 'D', high)
dlow = request.security(syminfo.tickerid, 'D', low)
ADR = 100 * (ta.sma(dhigh / dlow, ADRlen) - 1)

plot(toggleADR ? ADR:na, title="ADR", color=colorgreyer, style=plot.style_line, linewidth=1)


//--------TABLE------

string GRP4             = "════════ Table Options ═════════"
string tablesize = input.string("small",  "Size",      inline = "21", group = GRP4, options = ["tiny", "small", "normal", "large", "huge", "auto"])
string tableposY = input.string("middle", "↕",         inline = "21", group = GRP4, options = ["top", "middle", "bottom"])
string tableposX = input.string("right",   "↔",         inline = "21", group = GRP4, options = ["left", "center", "right"])

ColorBackground = toggleDarkColors ? input(color.new(color.black, 0), "Background Color (dark-mode)", inline = "21",group=GRP4) : input(color.new(color.white, 0), "Background Color (light-mode)", inline = "21", group=GRP4)
TextCol = toggleDarkColors ? input(color.new(color.white, 0), "Text Color (dark-mode)", inline = "21",group=GRP4) : input(color.new(color.black, 0), "Text Color (light-mode)", inline = "21", group=GRP4)

ColorGreenText = toggleDarkColors ? color.new(color.white, 0) : color.new(color.green, 0)
ColorOrangeText = toggleDarkColors ? color.new(color.white, 0) : color.new(color.orange, 0)

var table rangeTable = table.new(tableposY + "_" + tableposX, 3, 3, frame_color=color.new(#999999, 50), frame_width=1,border_color=color.new(#999999, 50), border_width=1)

if barstate.islast

    table.cell(rangeTable, 0, 1, text="ADR", text_halign=text.align_center, bgcolor=ColorBackground, text_color=TextCol, text_size=tablesize)
    table.cell(rangeTable, 0, 2, text="Range", text_halign=text.align_center, bgcolor=ColorBackground, text_color=TextCol, text_size=tablesize)
    
    table.cell(rangeTable, 1, 1, text=na(ADR) ? '-' : str.tostring(math.round(ADR,1)) +" "+ "%", text_halign=text.align_center, bgcolor=ColorBackground, text_color=TextCol, text_size=tablesize)
    table.cell(rangeTable, 1, 2, text=na(Range) ? '-' : str.tostring(math.round(Range,1)) +" "+ "%", text_halign=text.align_center, bgcolor=ColorBackground, text_color=TextCol, text_size=tablesize)


