Momentum Probability Oscillator [SS]
// 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("Momentum Probability Oscillator [SS]", shorttitle = "Probability Oscillator [SS]", max_bars_back = 500)

len = input.int(500, "Length")
timeframe = input.timeframe("", "Timeframe") 
smoothe = input.bool(false, "Smoothing")
showtbl = input.bool(false, "Show Table") 
showlbl = input.bool(true, "Show Labels")


[rsi1, rsi] = request.security(syminfo.ticker, timeframe, [ta.rsi(close,14)[1], ta.rsi(close, 14)], lookahead = barmerge.lookahead_on)
[hitoop, optolo] = request.security(syminfo.ticker, timeframe, [(high[1] - open[1]), (open[1] - low[1])], lookahead = barmerge.lookahead_on)
[sto1, sto] = request.security(syminfo.ticker, timeframe, [ta.stoch(close, high, low, 14)[1], ta.stoch(close, high, low, 14)], lookahead = barmerge.lookahead_on)
[mfi1, mfi] = request.security(syminfo.ticker, timeframe, [ta.mfi(close, 14)[1], ta.mfi(close,14)], lookahead = barmerge.lookahead_on)
op = request.security(syminfo.ticker, timeframe, open, lookahead = barmerge.lookahead_on)
// Bullish vs bearish 
bullishday = hitoop > optolo 
bearishday = optolo > hitoop

bullish_mfi_array = array.new_float() 
bullish_rsi_array = array.new_float() 
bullish_sto_array = array.new_float() 
hitoop_array = array.new_float() 

bearish_mfi_array = array.new_float() 
bearish_rsi_array = array.new_float() 
bearish_sto_array = array.new_float() 
lotoop_array = array.new_float() 

for i = 0 to len 
    if bullishday[i] 
        array.push(bullish_mfi_array, mfi1[i])
        array.push(bullish_rsi_array, rsi1[i])
        array.push(bullish_sto_array, sto1[i])
        array.push(hitoop_array, hitoop[i])
    if bearishday[i]
        array.push(bearish_mfi_array, mfi1[i])
        array.push(bearish_rsi_array, rsi1[i])
        array.push(bearish_sto_array, sto1[i])
        array.push(lotoop_array, optolo[i])


// Bullish avg 

hitoop_avg = array.avg(hitoop_array)
lotoop_avg = array.avg(lotoop_array)
rsi_bull_avg = array.avg(bullish_rsi_array)
rsi_bull_max = array.max(bullish_rsi_array)
rsi_bull_min = array.min(bullish_rsi_array) 

sto_bull_avg = array.avg(bullish_sto_array)
sto_bull_max = array.max(bullish_sto_array)
sto_bull_min = array.min(bullish_sto_array)

mfi_bull_avg = array.avg(bullish_mfi_array)
mfi_bull_max = array.max(bullish_mfi_array)
mfi_bull_min = array.min(bullish_mfi_array)

rsi_bear_avg = array.avg(bearish_rsi_array)
rsi_bear_max = array.max(bearish_rsi_array)
rsi_bear_min = array.min(bearish_rsi_array) 


sto_bear_avg = array.avg(bearish_sto_array)
sto_bear_max = array.max(bearish_sto_array)
sto_bear_min = array.min(bearish_sto_array) 

mfi_bear_avg = array.avg(bearish_mfi_array)
mfi_bear_max = array.max(bearish_mfi_array)
mfi_bear_min = array.min(bearish_mfi_array) 



// EM 

em_hitoop = op + hitoop_avg
em_lotoop = op - lotoop_avg

// Colours
color black = color.rgb(0, 0, 0) 
color white = color.white 
color bearfill = color.new(color.red, 85) 
color bullfill = color.new(color.lime, 85) 
color bearfill2 = color.new(color.red, 70) 
color bullfill2 = color.new(color.lime, 70) 
color grayfill = color.new(color.gray, 65) 
color transp = color.new(color.white, 100) 
var table datatable = table.new(position.middle_right, 10, 10, bgcolor = color.black) 

if showtbl 
    table.cell(datatable, 1, 1, text = "Technicals", bgcolor = black, text_color = white) 
    table.cell(datatable, 1, 2, text = "RSI", bgcolor = black, text_color = white) 
    table.cell(datatable, 1, 3, text = "Stochastics", bgcolor = black, text_color = white) 
    table.cell(datatable, 1, 4, text = "MFI", bgcolor = black, text_color = white) 


    table.cell(datatable, 2, 1, text = "Bullish", bgcolor = black, text_color = white) 
    table.cell(datatable, 3, 1, text = "Bullish Max", bgcolor = black, text_color = white) 
    table.cell(datatable, 4, 1, text = "Bullish Min", bgcolor = black, text_color = white) 
    table.cell(datatable, 5, 1, text = "Bearish", bgcolor = black, text_color = white) 
    table.cell(datatable, 6, 1, text = "Bearish Max", bgcolor = black, text_color = white) 
    table.cell(datatable, 7, 1, text = "Bearish Min", bgcolor = black, text_color = white) 

    table.cell(datatable, 2, 2, text = str.tostring(math.round(rsi_bull_avg, 2)), bgcolor = black, text_color = white) 
    table.cell(datatable, 2, 3, text = str.tostring(math.round(sto_bull_avg, 2)), bgcolor = black, text_color = white) 
    table.cell(datatable, 2, 4, text = str.tostring(math.round(mfi_bull_avg, 2)), bgcolor = black, text_color = white) 


    table.cell(datatable, 3, 2, text = str.tostring(math.round(rsi_bull_max, 2)), bgcolor = black, text_color = white) 
    table.cell(datatable, 3, 3, text = str.tostring(math.round(sto_bull_max, 2)), bgcolor = black, text_color = white) 
    table.cell(datatable, 3, 4, text = str.tostring(math.round(mfi_bull_max, 2)), bgcolor = black, text_color = white) 


    table.cell(datatable, 4, 2, text = str.tostring(math.round(rsi_bull_min, 2)), bgcolor = black, text_color = white) 
    table.cell(datatable, 4, 3, text = str.tostring(math.round(sto_bull_min, 2)), bgcolor = black, text_color = white) 
    table.cell(datatable, 4, 4, text = str.tostring(math.round(mfi_bull_min, 2)), bgcolor = black, text_color = white) 


    table.cell(datatable, 5, 2, text = str.tostring(math.round(rsi_bear_avg, 2)), bgcolor = black, text_color = white) 
    table.cell(datatable, 5, 3, text = str.tostring(math.round(sto_bear_avg, 2)), bgcolor = black, text_color = white) 
    table.cell(datatable, 5, 4, text = str.tostring(math.round(mfi_bear_avg, 2)), bgcolor = black, text_color = white) 


    table.cell(datatable, 6, 2, text = str.tostring(math.round(rsi_bear_max, 2)), bgcolor = black, text_color = white) 
    table.cell(datatable, 6, 3, text = str.tostring(math.round(sto_bear_max, 2)), bgcolor = black, text_color = white) 
    table.cell(datatable, 6, 4, text = str.tostring(math.round(mfi_bear_max, 2)), bgcolor = black, text_color = white) 


    table.cell(datatable, 7, 2, text = str.tostring(math.round(rsi_bear_min, 2)), bgcolor = black, text_color = white) 
    table.cell(datatable, 7, 3, text = str.tostring(math.round(sto_bear_min, 2)), bgcolor = black, text_color = white) 
    table.cell(datatable, 7, 4, text = str.tostring(math.round(mfi_bear_min, 2)), bgcolor = black, text_color = white) 


bullish_average = math.avg(rsi_bull_avg, sto_bull_avg, mfi_bull_avg) 
bullish_max_average = math.avg(rsi_bull_max, sto_bull_max, mfi_bull_max) 
bearish_average = math.avg(rsi_bear_avg, sto_bear_avg, mfi_bear_avg) 
bearish_min_average = math.avg(rsi_bear_min, sto_bear_min, mfi_bear_min) 
current_average = math.avg(mfi, sto, rsi) 
bull_bear_avg = math.avg(bullish_average, bearish_average) 
var float current_average_plot = 0.0

if smoothe 
    current_average_plot := ta.sma(current_average, 14) 
else 
    current_average_plot := current_average 
bull_mid = math.avg(bullish_average, bullish_max_average)
bear_mid = math.avg(bearish_average, bearish_min_average) 

e = plot(bear_mid, color=bearfill) 
f = plot(bull_mid, color=bullfill) 

plot(bull_bear_avg, color=color.yellow) 
plot(current_average_plot, color=color.purple, linewidth=3)  
c = plot(bullish_max_average, color=bullfill2) 
d = plot(bearish_min_average, color=bearfill2) 
a = plot(bullish_average, color=grayfill)
b = plot(bearish_average, color=grayfill) 

fill(a, b, color=grayfill) 
fill(b, e, color=bearfill) 
fill(f, a, color = bullfill) 
fill(e, d, color=bearfill2) 
fill(f, c, color=bullfill2) 
// Candle distribution 

bool neut = current_average >= bearish_average and current_average <= bullish_average 
bool bull_upper = current_average > bull_mid and current_average <= bullish_max_average 
bool bull_lower = current_average > bullish_average and current_average <= bull_mid 


bool bear_upper = current_average < bearish_average and current_average >= bear_mid  
bool bear_lower = current_average < bear_mid and current_average >= bearish_min_average 


int neut_count = 0 
int bull_count = 0 
int bull_overbought_count = 0 
int bear_count = 0 
int bear_overbought_count = 0 

for i = 0 to len 
    if neut[i] and barstate.islast 
        neut_count := neut_count + 1 
    if bull_lower[i] and barstate.islast 
        bull_count := bull_count + 1 
    if bull_upper[i] and barstate.islast 
        bull_overbought_count := bull_overbought_count + 1 
    if bear_upper[i] and barstate.islast 
        bear_count := bear_count + 1 
    if bear_lower[i] and barstate.islast 
        bear_overbought_count := bear_overbought_count + 1 

f_perc(count, lookback) => 
    count / lookback * 100 

neut_perc = f_perc(neut_count, len) 
bull_perc = f_perc(bull_count, len) 
bear_perc = f_perc(bear_count, len) 
bull_o_perc = f_perc(bull_overbought_count, len) 
bear_o_perc = f_perc(bear_overbought_count, len) 

var label neut_lbl = na 
var label bull_lbl = na 
var label bull_o_lbl = na 
var label bear_lbl = na 
var label bear_o_lbl = na 
var label hi_lbl = na 
var label lo_lbl = na 
if barstate.islast and showlbl
    label.delete(neut_lbl) 
    label.delete(bull_lbl) 
    label.delete(bull_o_lbl) 
    label.delete(bear_lbl) 
    label.delete(bear_o_lbl) 
    label.delete(hi_lbl) 
    label.delete(lo_lbl) 
    bull_lbl := label.new(bar_index - 10, y = bullish_average, text = str.tostring(math.round(bull_perc,2)) + "%", color=transp, textcolor = white) 
    bull_o_lbl := label.new(bar_index - 10, y = bull_mid, text = str.tostring(math.round(bull_o_perc,2)) + "%", color=transp, textcolor = white) 
    neut_lbl := label.new(bar_index + 10, y = bull_bear_avg, text = str.tostring(math.round(neut_perc,2)) + "%", style=label.style_label_right, color = transp, textcolor = white)
    bear_lbl := label.new(bar_index - 10, y = bearish_average, text = str.tostring(math.round(bear_perc,2)) + "%", style=label.style_label_up, color = transp, textcolor = white) 
    bear_o_lbl := label.new(bar_index - 10, y = bear_mid, text = str.tostring(math.round(bear_o_perc,2)) + "%", style=label.style_label_up, color = transp, textcolor = white)   
    hi_lbl := label.new(bar_index + 5, y = bull_mid, text = str.tostring(math.round(em_hitoop,2)), style=label.style_label_right, color = transp, textcolor = white)
    lo_lbl := label.new(bar_index + 5, y = bear_mid, text = str.tostring(math.round(em_lotoop,2)), style=label.style_label_right, color = transp, textcolor = white)