Trend Shift Pro
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © federalTacos5392b

//@version=5
indicator("Trend Shift Pro", overlay = true)
Threshold=input(0.8, title= "Practical Significance Threshold")
// Calculate subgroup means for each block of 21 bars
a = (hlc3[5] + hlc3[14] + hlc3[16]) / 3
b = (hlc3[8] + hlc3[15] + hlc3[1]) / 3
c = (hlc3[19] + hlc3[7] + hlc3[11]) / 3
d = (hlc3[10] + hlc3[6] + hlc3[18]) / 3
e = (hlc3[0] + hlc3[3] + hlc3[17]) / 3
f = (hlc3[9] + hlc3[20] + hlc3[13]) / 3
g = (hlc3[4] + hlc3[12] + hlc3[2]) / 3

// Create an array with the seven values for the current block of 21 bars
var float[] values = array.new_float(7)
var float MoM = na

if bar_index % 21 == 0
    // Reset the values array for a new block
    array.clear(values)
    
    // Push the subgroup means into the values array for the current block
    array.push(values, a)
    array.push(values, b)
    array.push(values, c)
    array.push(values, d)
    array.push(values, e)
    array.push(values, f)
    array.push(values, g)

    // Calculate the median of the seven values for the current block
    MoM := array.median(values)
else
    // Set non-MoM values to na
    MoM := na

// Calculate IQR for each block of 21 bars
a1 = hlc3[0]
b1 = hlc3[1]
c1 = hlc3[2]
d1 = hlc3[3]
e1 = hlc3[4]
f1 = hlc3[5]
g1 = hlc3[6]
h1 = hlc3[7]
i1 = hlc3[8]
j1 = hlc3[9]
k1 = hlc3[10]
l1 = hlc3[11]
m1 = hlc3[12]
n1 = hlc3[13]
o1 = hlc3[14]
p1 = hlc3[15]
q1 = hlc3[16]
r1 = hlc3[17]
s1 = hlc3[18]
t1 = hlc3[19]
u1 = hlc3[20]

// Create an array with the twenty-one values for the current block of 21 bars
var float[] iqr_values = array.new_float(21)
var float IQR = na

if bar_index % 21 == 0
    // Reset the values array for a new block
    array.clear(iqr_values)
    
    // Push the subgroup means into the values array for the current block
    array.push(iqr_values, a1)
    array.push(iqr_values, b1)
    array.push(iqr_values, c1)
    array.push(iqr_values, d1)
    array.push(iqr_values, e1)
    array.push(iqr_values, f1)
    array.push(iqr_values, g1)
    array.push(iqr_values, h1)
    array.push(iqr_values, i1)
    array.push(iqr_values, j1)
    array.push(iqr_values, k1)
    array.push(iqr_values, l1)
    array.push(iqr_values, m1)
    array.push(iqr_values, n1)
    array.push(iqr_values, o1)
    array.push(iqr_values, p1)
    array.push(iqr_values, q1)
    array.push(iqr_values, r1)
    array.push(iqr_values, s1)
    array.push(iqr_values, t1)
    array.push(iqr_values, u1)

    // Sort the values in ascending order
    array.sort(iqr_values)

    // Calculate Q1, Q3, and IQR
    var float Q1 = na
    var float Q3 = na

    if array.size(iqr_values) >= 4
        Q1 := array.percentile_nearest_rank(iqr_values, 25)
        Q3 := array.percentile_nearest_rank(iqr_values, 75)
        IQR := 0.75*(Q3 - Q1)
else
    // Set non-IQR values to na
    IQR := na

// Non Parametric CohensD (practile significance) calculation
var float CohensD = na

if not na(MoM) and not na(IQR) and not na(MoM[21]) and not na(IQR[21])
    CohensD := (MoM - MoM[21]) / math.sqrt((20 * math.pow(IQR, 2) + 20 * math.pow(IQR[21], 2)) / 40)
else
    CohensD := na

// Determine the color based on median of means direction
color_change = MoM > MoM[21] ? color.green : (MoM < MoM[21] ? color.red : color.blue)
// Detrmine Practical Significance 
Ps=math.abs(CohensD)< Threshold
// Plot the MoM value with straight lines
plot(MoM, title = "MoM Value", color = color.blue, linewidth = 1, style = plot.style_stepline)
plot(MoM, title="MoM Value", color= color_change,style=plot.style_circles, linewidth = 5)

//plot(CohensD, title = "Custom Calculation", color = color.purple, linewidth = 1, style = plot.style_line)
plotshape(Ps,style =shape.triangleup, text= "NS",textcolor = color.rgb(224, 229, 241), size =size.small)