Predictive Pivot Points based on Technicals 
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//  /$$$$$$   /$$                                                         /$$                                            
// /$$__  $$ | $$                                                        | $$                                            
//| $$  \__//$$$$$$    /$$$$$$  /$$    /$$ /$$$$$$   /$$$$$$   /$$$$$$$ /$$$$$$    /$$$$$$  /$$    /$$ /$$$$$$   /$$$$$$$
//|  $$$$$$|_  $$_/   /$$__  $$|  $$  /$$//$$__  $$ /$$__  $$ /$$_____/|_  $$_/   /$$__  $$|  $$  /$$//$$__  $$ /$$_____/
// \____  $$ | $$    | $$$$$$$$ \  $$/$$/| $$$$$$$$| $$  \__/|  $$$$$$   | $$    | $$$$$$$$ \  $$/$$/| $$$$$$$$|  $$$$$$ 
// /$$  \ $$ | $$ /$$| $$_____/  \  $$$/ | $$_____/| $$       \____  $$  | $$ /$$| $$_____/  \  $$$/ | $$_____/ \____  $$
//|  $$$$$$/ |  $$$$/|  $$$$$$$   \  $/  |  $$$$$$$| $$       /$$$$$$$/  |  $$$$/|  $$$$$$$   \  $/  |  $$$$$$$ /$$$$$$$/
// \______/   \___/   \_______/    \_/    \_______/|__/      |_______/    \___/   \_______/    \_/    \_______/|_______/ 

//       ___________________
//      /                   \
//     /  _____        _____ \
//    /  /     \      /     \  \
// __/__/       \____/       \__\_____
//|           ___________           ____|
// \_________/           \_________/
//            \  /////// /
//             \/////////
// © Steversteves

//@version=5
indicator("Predictive Pivot Points with Stat Display and Similarity Identification [SS]", shorttitle = "Predictive Pivot Points [SS]", overlay=true, max_bars_back = 500, max_labels_count = 500) 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                           Tooltips                                                                                  ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

t1 = "Sets the bar lookback length for pivot points, defualt is 10:10" 
t2 = "Sets the lookback length for the arrays" 
t3 = "Sets the Source for the RSI" 
t4 = "Sets the Source for the Stocahstics" 
t5 = "Sets the Source for the MFI" 
t6 = "Sets the Length for the MFI" 
t7 = "Sets the threshold to look for similar technical indicators. This threshold will apply to MFI, Stochastics and RSI. The Default is 2 and 2, so it will look for +/- 2 points of the previous Pivot." 
t9 = "Will look for all similar pivot indicators, including RSI, Stochastics, Volume and MFI" 
t10 = "Will only show identical instances where MFI, Stochastics and RSI are similar within the threshold limits. Volume is NOT included." 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            Groups                                                                                   ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

g1 = "Pivots" 
g2 = "Inputs" 
g3 = "Technicals" 
g4 = "Thresholds"  

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            Technicals                                                                               ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


leftbars = input.int(10, "Left Bars", tooltip = t1, group = g1) 
rightbars = input.int(10, "Right Bars", tooltip = t1, group = g1) 
len = input.int(500, "Lookback Length", tooltip = t2, group = g2) 
rsisource = input.source(close, "RSI Source", tooltip = t3, group = g3) 
rsilen = input.int(14, "RSI Length", tooltip=t7, group = g3) 

stosource = input.source(close, "Stochastic Source", tooltip = t4, group = g3) 
stolen = input.int(14, "Stochastic Length", tooltip = t6, group = g3) 

mfisource = input.source(close, "MFI Source", tooltip = t5, group = g3) 
mfilen = input.int(14, "MFI Length", tooltip = t6, group = g3) 

plusrng = input.int(2, "Upper Threshold", tooltip = t7, group = g4) 
minusrng = input.int(2, "Lower Threshold", tooltip = t7, group = g4) 

showpivots = input.bool(false, "Show Pivots", group = g1) 
showlikersi = input.bool(true, "Show Like RSI Pivots", tooltip = t9, group = g1) 
showlikemfi = input.bool(true, "Show Like MFI Pivots", tooltip = t9, group = g1) 
showlikesto = input.bool(true, "Show Like Stochastic Pivots", tooltip = t9, group = g1) 
showlikevolume = input.bool(true, "Show Like Volume Pivots", tooltip = t9, group = g1) 
showidentical = input.bool(true, "Show Identical Instances", tooltip = t10, group = g1) 


piv_high = ta.pivothigh(high, leftbars, rightbars) 
piv_low = ta.pivotlow(low, leftbars, rightbars) 

rsi = ta.rsi(rsisource, rsilen) 
sto = ta.stoch(stosource, high, low, stolen) 
mfi = ta.mfi(mfisource, mfilen) 

if piv_high and showpivots
    label.new(x=bar_index, y=high, text="Pivot High " + str.tostring(close) + "\n RSI: " + str.tostring(math.round(rsi,2)) + "\n Stoch: " + str.tostring(math.round(sto,2)) + "\n MFI: " + str.tostring(math.round(mfi,2)) + "\n Volume: " + str.tostring(volume), color=color.white, textcolor = color.black) 

if piv_low and showpivots
    label.new(x=bar_index, y=high, text="Pivot Low " + str.tostring(close) + "\n RSI: " + str.tostring(math.round(rsi,2)) + "\n Stoch: " + str.tostring(math.round(sto,2)) + "\n MFI: " + str.tostring(math.round(mfi,2)) + "\n Volume: " + str.tostring(volume), color=color.white, textcolor = color.black) 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            Store Historic Data                                                                      ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


pivot_hi_rsi = array.new_float() 
pivot_hi_vol = array.new_float() 
pivot_hi_mfi = array.new_float() 
pivot_hi_sto = array.new_float() 
pivot_lo_rsi = array.new_float() 
pivot_lo_vol = array.new_float() 
pivot_lo_mfi = array.new_float() 
pivot_lo_sto = array.new_float() 

bar_index_limit = bar_index <= 5000 ? bar_index : 5000
for i = 14 to len 
    if piv_high 
        array.push(pivot_hi_rsi, rsi[i]) 
        array.push(pivot_hi_vol, volume[i]) 
        array.push(pivot_hi_mfi, mfi[i]) 
        array.push(pivot_hi_sto, sto[i]) 
    if piv_low 
        array.push(pivot_lo_rsi, rsi[i]) 
        array.push(pivot_lo_vol, volume[i]) 
        array.push(pivot_lo_mfi, mfi[i]) 
        array.push(pivot_lo_sto, sto[i]) 

var float last_pivot_hi_rsi = na
var float last_pivot_hi_vol = na
var float last_pivot_hi_mfi = na
var float last_pivot_hi_sto = na

var float last_pivot_lo_rsi = na
var float last_pivot_lo_vol = na
var float last_pivot_lo_mfi = na
var float last_pivot_lo_sto = na

var float pivot_hi_rsi_equal = na 
var float pivot_lo_rsi_equal = na 
var float pivot_hi_mfi_equal = na 
var float pivot_lo_mfi_equal = na 
var float pivot_hi_sto_equal = na 
var float pivot_lo_sto_equal = na 

var float rsi_counter_hi = 0
var float rsi_counter_lo = 0 
var float mfi_counter_hi = 0 
var float mfi_counter_lo = 0 
var float sto_counter_hi = 0 
var float sto_counter_lo = 0 

if array.size(pivot_hi_rsi) > 0
    last_pivot_hi_rsi := array.get(pivot_hi_rsi, array.size(pivot_hi_rsi) - 1)
    for i = 0 to array.size(pivot_hi_rsi) - 1  
        if math.abs(rsi[1] - array.get(pivot_hi_rsi, i)) <= plusrng 
            pivot_hi_rsi_equal := rsi[1]
        else 
            pivot_hi_rsi_equal := 0 

if array.size(pivot_hi_vol) > 0
    last_pivot_hi_vol := array.get(pivot_hi_vol, array.size(pivot_hi_vol) - 1)
    

if array.size(pivot_hi_mfi) > 0
    last_pivot_hi_mfi := array.get(pivot_hi_mfi, array.size(pivot_hi_mfi) - 1)
    for i = 0 to array.size(pivot_hi_mfi) - 1  
        if math.abs(mfi[1] - array.get(pivot_hi_mfi, i)) <= plusrng 
            pivot_hi_mfi_equal := mfi[1]
        else 
            pivot_hi_mfi_equal := 0 

if array.size(pivot_hi_sto) > 0
    last_pivot_hi_sto := array.get(pivot_hi_sto, array.size(pivot_hi_sto) - 1)
    for i = 0 to array.size(pivot_hi_sto) - 1  
        if math.abs(sto[1] - array.get(pivot_hi_sto, i)) <= plusrng 
            pivot_hi_sto_equal := sto[1]
        else 
            pivot_hi_sto_equal := 0 

//
if array.size(pivot_lo_rsi) > 0
    last_pivot_lo_rsi := array.get(pivot_lo_rsi, array.size(pivot_lo_rsi) - 1)
    for i = 0 to array.size(pivot_lo_rsi) - 1  
        if math.abs(rsi[1] - array.get(pivot_lo_rsi, i)) <= plusrng 
            pivot_lo_rsi_equal := rsi[1]
        else 
            pivot_lo_rsi_equal := 0 

if array.size(pivot_lo_vol) > 0
    last_pivot_lo_vol := array.get(pivot_lo_vol, array.size(pivot_lo_vol) - 1)

if array.size(pivot_lo_mfi) > 0
    last_pivot_lo_mfi := array.get(pivot_lo_mfi, array.size(pivot_lo_mfi) - 1)
    for i = 0 to array.size(pivot_lo_mfi) - 1  
        if math.abs(mfi[1] - array.get(pivot_lo_mfi, i)) <= plusrng 
            pivot_lo_mfi_equal := mfi[1]
        else 
            pivot_lo_mfi_equal := 0 

if array.size(pivot_lo_sto) > 0
    last_pivot_lo_sto := array.get(pivot_lo_sto, array.size(pivot_lo_sto) - 1)
    for i = 0 to array.size(pivot_lo_sto) - 1  
        if math.abs(sto[1] - array.get(pivot_lo_sto, i)) <= plusrng 
            pivot_lo_sto_equal := sto[1]
        else 
            pivot_lo_sto_equal := 0 


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            Pivot Assessments                                                                         ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


bool rsi_equal_piv_hi = rsi >= last_pivot_hi_rsi - minusrng and rsi <= last_pivot_hi_rsi + plusrng 
bool sto_equal_piv_hi = sto >= last_pivot_hi_sto - minusrng and sto <= last_pivot_hi_sto  + plusrng 
bool mfi_equal_piv_hi = mfi >= last_pivot_hi_mfi - minusrng and mfi <= last_pivot_hi_mfi + plusrng 
bool vol_equal_piv_hi = volume == last_pivot_hi_vol

bool all_3_piv_hi = rsi_equal_piv_hi and sto_equal_piv_hi and mfi_equal_piv_hi

bool rsi_equal_piv_lo = rsi >= last_pivot_lo_rsi - minusrng and rsi <= last_pivot_lo_rsi + plusrng 
bool sto_equal_piv_lo = sto >= last_pivot_lo_sto - minusrng and sto <= last_pivot_lo_sto  + plusrng 
bool mfi_equal_piv_lo = mfi >= last_pivot_lo_mfi - minusrng and mfi <= last_pivot_lo_mfi + plusrng 
bool vol_equal_piv_lo = volume == last_pivot_lo_vol

bool all_3_piv_lo = rsi_equal_piv_lo and sto_equal_piv_lo and mfi_equal_piv_lo

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            Plots                                                                                   ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

var int rsi_hi_counter = 0 

if rsi_equal_piv_hi and showlikersi
    rsi_counter_hi := rsi_counter_hi + 1
    if rsi_counter_hi >= 10
        label.new(x=bar_index, y=high, text="RSI Pivot High Similar: \n " + str.tostring(math.round(rsi,2)), color=color.white, textcolor = color.black)
        rsi_counter_hi := 0
    if pivot_hi_rsi_equal > 0 
        rsi_hi_counter := rsi_hi_counter + 1 
        if rsi_hi_counter >= 10 
            rsi_hi_counter := 0 
            label.new(x=bar_index, y=high, text="RSI Pivot High Similar: \n " + str.tostring(math.round(rsi,2)), color=color.white, textcolor = color.black)
var int sto_hi_counter = 0 
if sto_equal_piv_hi and showlikesto
    sto_counter_hi := sto_counter_hi + 1 
    if sto_counter_hi >= 10
        label.new(x=bar_index, y=high, text="Sto Pivot High Similar: \n " + str.tostring(math.round(sto,2)), color=color.white, textcolor = color.black)
        sto_counter_hi := 0 
    if pivot_hi_sto_equal > 0 
        sto_hi_counter := sto_hi_counter + 1
        if sto_hi_counter >= 10 
            sto_hi_counter := 0 
            label.new(x=bar_index, y=high, text="Stochastic Pivot High Similar: \n " + str.tostring(math.round(sto,2)), color=color.white, textcolor = color.black)

var int mfi_hi_counter = 0 

if mfi_equal_piv_hi and showlikemfi
    mfi_counter_hi := mfi_counter_hi + 1 
    if mfi_counter_hi >= 10
        label.new(x=bar_index, y=high, text="MFI Pivot High Similar: \n " + str.tostring(math.round(mfi,2)), color=color.white, textcolor = color.black)
        mfi_counter_hi := 0 
    if pivot_hi_mfi_equal > 0 
        mfi_hi_counter := mfi_hi_counter + 1 
        if mfi_hi_counter >= 10 
            mfi_hi_counter := 0 
            label.new(x=bar_index, y=high, text="MFI Pivot High Similar: \n " + str.tostring(math.round(mfi,2)), color=color.white, textcolor = color.black)

if vol_equal_piv_hi and showlikevolume
    label.new(x=bar_index, y=high, text="Volume Pivot High Similar: \n " + str.tostring(math.round(volume,2)), color=color.white, textcolor = color.black)

if all_3_piv_hi and showidentical 
    label.new(x=bar_index, y=high, text="RSI, Sto and MFI similar to \n previous pivot high", color=color.white, textcolor = color.black)

var int rsi_lo_counter = 0 

if rsi_equal_piv_lo and showlikersi 
    rsi_counter_lo := rsi_counter_lo + 1 
    if rsi_counter_lo >= 10
        label.new(x=bar_index, y=high, text="RSI Pivot Low Similar: \n " + str.tostring(math.round(rsi,2)), color=color.white, textcolor = color.black)
        rsi_counter_lo := 0 
    if pivot_lo_rsi_equal > 0 
        rsi_lo_counter := rsi_lo_counter + 1 
        if rsi_lo_counter >= 10 
            rsi_lo_counter := 0 
            label.new(x=bar_index, y=high, text="RSI Pivot Low Similar: \n " + str.tostring(math.round(rsi,2)), color=color.white, textcolor = color.black)

var int sto_lo_counter = 0 

if sto_equal_piv_lo and showlikesto
    sto_counter_lo := sto_counter_lo + 1 
    if sto_counter_lo >=10
        label.new(x=bar_index, y=high, text="Sto Pivot Low Similar: \n " + str.tostring(math.round(sto,2)), color=color.white, textcolor = color.black)
        sto_counter_lo := 0 
    if pivot_lo_sto_equal > 0 
        sto_lo_counter := sto_lo_counter + 1 
        if sto_lo_counter >= 10 
            sto_lo_counter := 0 
            label.new(x=bar_index, y=high, text="Sto Pivot Low Similar: \n " + str.tostring(math.round(sto,2)), color=color.white, textcolor = color.black)

var int mfi_lo_counter = 0 

if mfi_equal_piv_lo and showlikemfi
    mfi_counter_lo := mfi_counter_lo + 1 
    if mfi_counter_lo >= 10
        label.new(x=bar_index, y=high, text="MFI Pivot Low Similar: \n " + str.tostring(math.round(mfi,2)), color=color.white, textcolor = color.black)
        mfi_counter_lo := 0 
    if pivot_lo_mfi_equal > 0 
        mfi_lo_counter := mfi_lo_counter + 1 
        if mfi_lo_counter >= 10 
            mfi_lo_counter := 0 
            label.new(x=bar_index, y=high, text="MFI Pivot Low Similar: \n " + str.tostring(math.round(mfi,2)), color=color.white, textcolor = color.black)

if vol_equal_piv_lo and showlikevolume
    label.new(x=bar_index, y=high, text="Volume Pivot Low Similar: \n " + str.tostring(math.round(volume,2)), color=color.white, textcolor = color.black)

if all_3_piv_lo and showidentical
    label.new(x=bar_index, y=high, text="RSI, Sto and MFI similar to \n previous pivot low", color=color.white, textcolor = color.black)
