Modified ATR Indicator [KL]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © DojiEmoji

//@version=5
indicator(title="ATR [KL]", overlay=false)

MODEL_1 = "Two-tail hypothesis testing"
MODEL_2 = "Point estimation"
model_choice = input.string(title="Model", defval=MODEL_2, options=[MODEL_1, MODEL_2])

conf_interval      = input.string(title="Confidence Interval", defval="95%", options=["90%","95%","99%"], tooltip="Critical values of 1.645, 1.96, 2.58, for CI=90%/95%/99%, respectively; Under 2-tailed test to compare atr_fast vs atr_slow. Null hypothesis (H0) is that both should equal. Based on the computed test statistic value, if absolute value of it is +/- critical value, then H0 will be rejected.")
reliability_factor = conf_interval == "90%" ? 1.645 : conf_interval == "95%" ? 1.96 : 2.58
length_fast        = input.int(title="Length of lookback (fast)", defval=14, minval=1)
length_slow        = input.int(title="Length of lookback (slow)", defval=50, minval=1)

// Main indicator
atr_fast            = ta.sma(ta.tr(true), length_fast)
atr_fast_std_error  = ta.stdev(ta.tr, length_fast) / math.pow(length_fast, 0.5)
 
// - - - - - - - - - - - - - - - - - - - - 
// Model #1 Hypothesis testing (2-tailed) {
// Assumption is that 'atr_fast' is a set of sample data within deemed population 'atr_slow'
// Null Hypothesis           H0 : atr_fast equals atr_slow
// Alternative hypothesis    Ha : atr_fast not equals to atr_slow
//   "                            if reject H0, we conclude atr_fast is too high or too low

model1_atr_slow        = ta.sma(ta.tr(true), length_slow)
model_1_test_stat      = (atr_fast - model1_atr_slow) / atr_fast_std_error
model_1_critical_value = reliability_factor
// }

// - - - - - - - - - - - - - - - - - - - - 
// Model #2 - Point estimation model: {
// Since the population mean is unknown, based on sample data 'atr_fast' and user's desired confidence interval,
// we can estimate the Lower bound & Upper bound serving as the range describing where the population mean should lie.
// If 'atr_fast' is below/above this range, then we conclude ATR is too low/high, respectively.

model_2_sample_mean    = ta.sma(atr_fast, length_slow) // being the moving avg of ATR_fast
model_2_critical_value = reliability_factor * atr_fast_std_error
model_2_lowerbound     = model_2_sample_mean - model_2_critical_value
model_2_upperbound     = model_2_sample_mean + model_2_critical_value
// }

// - - - - - - - - - - - - - - - - - - - - 
// Color coding the ATR line + Plotting
var color_normal    = input.color(#7b1fa2, title="ATR Color (Normal)")
var color_high      = input.color(color.red, title="ATR Color (Extreme high)")
var color_low       = input.color(color.green, title="ATR Color (Extremely low)")

atr_extremely_high = false, atr_extremely_low = false //initialize states

if model_choice == MODEL_1
    atr_extremely_high := model_1_test_stat > math.abs(model_1_critical_value)
    atr_extremely_low  := model_1_test_stat < -math.abs(model_1_critical_value)
else if model_choice == MODEL_2
    atr_extremely_high := atr_fast > model_2_upperbound
    atr_extremely_low  := atr_fast < model_2_lowerbound

color_length_fast = atr_extremely_high ? color_high : atr_extremely_low ? color_low : color_normal

// Plotting {
plot(atr_fast, title = "ATR fast", color=color.new(color_length_fast, 0), linewidth=2)
plot_arrows = input(false, title="Plot arrows", tooltip="Arrows at top/bottom of ATR panel to indicate extreme high/low periods")
plot_ref_line = input(false, title="Plot reference lines", tooltip="Model 1: being atr_slow; Model 2: being the slow moving avg. of ATR")
plotshape(plot_arrows and atr_extremely_high, style=shape.triangleup, location=location.top, color=color.red)
plotshape(plot_arrows and atr_extremely_low, style=shape.triangledown, location=location.bottom, color=color.green)

// Reference plots: Population ATR (MODEL_1), and MA of ATR (MODEL_2)
model1_plot_transp = 100, model2_plot_transp = 100
if plot_ref_line
    if model_choice == MODEL_1 // only becomes visible when MODEL_1 is selected
        model1_plot_transp := 50
    else if model_choice == MODEL_2 // only becomes visible when MODEL_2 is selected
        model2_plot_transp := 50
plot(model1_atr_slow, title = "MA of ATR", color=color.new(color.gray, model1_plot_transp), linewidth=0)
plot(model_2_sample_mean, title = "MA of ATR", color=color.new(color.gray, model2_plot_transp), linewidth=0)
// }

// ATR label
var label lbl = na
string _msg = "atr(" + str.tostring(length_fast) +") = " + str.tostring(atr_fast, "#.##")
if barstate.islast
    lbl := label.new(bar_index + 5, atr_fast, _msg, xloc.bar_index, yloc.price, color.new(color.black, 0), label.style_label_left, color.black, size.small, text.align_left)
    label.set_textcolor(id=lbl, textcolor=color.white)
    label.delete(lbl[1])
