VS Score [SpiritualHealer117]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © spiritualhealer117

// Disclaimer
//      This indicator was created for informational purposes, and does not constitute my financial or investment advice
//      Every model comes with limitations, and so results produced by this model should not be relied on excessively 

//@version=5
indicator("VS Score [SpiritualHealer117]",max_lines_count = 2,overlay=true, max_boxes_count = 1)
//1 - Inputs {

    //1.1 Inputs for Price Percentage Oscillator
ppo_len = input.int(50,"PPO Length")
ppo_sens = input.float(0.1,"PPO Extreme Threshold")

    //1.2 Inputs for Volume Histogram
v_len = input.int(50, "Volume Histogram Length")
v_src = volume

    //1.3 Inputs for Past State Calculation
rare_sens = input.float(2, "Abnormal Sensitivity")
normal_sens = input.float(0.5, "Normal Sensitivity")

    //1.4 Inputs for Moving Average
ma_len = input.int(14, "Moving Average Length")

    // 1.5 Length for data fitting
data_fit_len = input.int(1000, "Data fitting period")

    //1.5 Other Options
src = input.source(hl2,"Source")
ma_type = input.string("SMA","MA Smoothing Option", ["SMA","WMA","EMA","RMA", "VWMA"])

    //1.6 Inputs for Styling and Coloring
bclr = input.color(color.black,"Border Color")
bgclr = input.color(color.rgb(78, 218, 57),"Gain Color")
bgclr2 = input.color(color.rgb(230, 185, 185),"Loss Color")
bgclr3 = input.color(color.rgb(206, 206, 206),"Neutral Color")
//}

//2 - Indicator State Calculations {
    //2.1 Calculation for Moving Average (0-1) and PPO (-1-1) {
calc_moving_average(ma_type,src,length)=>
    if ma_type == "SMA"
        ta.sma(src,length)
    else if ma_type == "WMA"
        ta.wma(src,length)
    else if ma_type == "EMA"
        ta.ema(src,length)
    else if ma_type == "RMA"
        ta.rma(src, length)
    else
        ta.vwma(src, length)

ma = calc_moving_average(ma_type,src,ma_len)
src2ma_diff = src-ma
ma_state = src2ma_diff > 0 ? 1:0
ppo_ma = calc_moving_average(ma_type,src,ppo_len)
ppo = (src-ppo_ma)/ppo_ma
ppo_state = ppo > ppo_sens?-1:(ppo < -ppo_sens?1:0)
        
    //}
    //2.2 Calculation of Past State (1-5) {
ret = (src-src[1])/src[1]
ret_dev = ta.stdev(ret,ma_len)
ret_ma = calc_moving_average(ma_type,ret,ma_len)
state = ret > rare_sens * ret_dev+ret_ma ? 5 : ret > normal_sens* ret_dev+ret_ma ? 4 : ret > -normal_sens* ret_dev+ret_ma ? 3 : ret > -rare_sens * ret_dev+ret_ma ? 2 : 1
past_state=state[1]

    //}
    //2.3 Calculation for Volume Histogram {
volume_histogram = array.new<float>(5,0)
array.set(volume_histogram,0,math.sum(state==1?v_src:0,v_len))
array.set(volume_histogram,1,math.sum(state==2?v_src:0,v_len))
array.set(volume_histogram,2,math.sum(state==3?v_src:0,v_len))
array.set(volume_histogram,3,math.sum(state==4?v_src:0,v_len))
array.set(volume_histogram,4,math.sum(state==5?v_src:0,v_len))

vh_state = array.indexof(volume_histogram,array.max(volume_histogram))

    //}
    //2.4 Other Important Calculations {
relevant_close = barstate.isconfirmed?close:close[1]
extreme_gain_price = (rare_sens * ret_dev+ 1)*relevant_close
gain_price = (normal_sens * ret_dev + 1)*relevant_close
flat_price = (1)*relevant_close
loss_price = (-normal_sens * ret_dev + 1)*relevant_close
extreme_loss_price = (-rare_sens * ret_dev+ 1)*relevant_close
    //}
//}

//3 - Probability Vector Calculations {
    //3.1 General Calculation Function {
create_probability_vector(indicator_state, state, data_len)=>
    output_vector = array.new<float>(5,0)
    for i = 0 to 4
        sum = 0 
        for j = 0 to data_len
            indic_condition = indicator_state[j] == indicator_state and state[j]==i+1 ? 1 : 0  
            sum := sum + indic_condition
        
        array.set(output_vector,i,sum)
    output_vector
    //}
    //3.2 Vector Transformation {
vt(vector)=>
    transformed_vector = array.new<float>(5,0)
    for i = 0 to 4
        array.set(transformed_vector,i,array.get(vector,i)/array.sum(vector))
    transformed_vector
    //}
    //3.3 Individual Calculations {
ppo_vector = vt(create_probability_vector(ppo_state, state, data_fit_len))
ma_vector = vt(create_probability_vector(ma_state, state, data_fit_len))
vh_vector = vt(create_probability_vector(vh_state,state,data_fit_len))
past_vector = vt(create_probability_vector(past_state,state,data_fit_len))
    //}
//}

//4 - VS Score Calculation {
    //4.1 Vector Combination {
vs_combined_vector = array.new<float>(5,0)
for i = 0 to 4
    array.set(vs_combined_vector,i,array.get(ppo_vector,i)+array.get(ma_vector,i)+array.get(vh_vector,i)+array.get(past_vector,i))

vs_probability_vector = vt(vs_combined_vector)
    //}
//}

//5 - Output {
    //5.1 Tabular Output {
output_table = table.new(position = position.middle_right, columns = 2, rows = 6, bgcolor = bgclr, border_width = 1)
if barstate.islast
    table.cell(table_id = output_table, column = 0, row = 0, text = "Move Type")
    table.cell(table_id = output_table, column = 1, row = 0, text = "p")
    table.cell(table_id = output_table, column = 0, row = 1, text = "Extreme Rise")
    table.cell(table_id = output_table, column = 0, row = 2, text = "Rise")
    table.cell(table_id = output_table, column = 0, row = 3, text = "Flat")
    table.cell(table_id = output_table, column = 0, row = 4, text = "Fall")
    table.cell(table_id = output_table, column = 0, row = 5, text = 'Extreme Fall')
    for i = 0 to 4
        table.cell(table_id = output_table, column = 1, row = i+1, text = str.tostring(math.round(array.get(vs_probability_vector,i),3)))
    b = box.new(bar_index,gain_price,bar_index+5,loss_price,bclr,border_width = 1, xloc=xloc.bar_index, bgcolor = bgclr3, text=str.tostring(math.round(array.get(vs_probability_vector,2),2)),text_size=size.small)
    b2 = box.new(bar_index,extreme_gain_price,bar_index+5,gain_price,bclr,border_width = 1, xloc=xloc.bar_index, bgcolor = bgclr, text=str.tostring(math.round(array.get(vs_probability_vector,1),2)),text_size=size.small)
    b3=box.new(bar_index,extreme_loss_price,bar_index+5,loss_price,bclr,border_width = 1, xloc=xloc.bar_index, bgcolor = bgclr2, text=str.tostring(math.round(array.get(vs_probability_vector,3),2)),text_size=size.small)

    //}
//}