[SS] Linear Modeler
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//  /$$$$$$   /$$                                                         /$$                                            
// /$$__  $$ | $$                                                        | $$                                            
//| $$  \__//$$$$$$    /$$$$$$  /$$    /$$ /$$$$$$   /$$$$$$   /$$$$$$$ /$$$$$$    /$$$$$$  /$$    /$$ /$$$$$$   /$$$$$$$
//|  $$$$$$|_  $$_/   /$$__  $$|  $$  /$$//$$__  $$ /$$__  $$ /$$_____/|_  $$_/   /$$__  $$|  $$  /$$//$$__  $$ /$$_____/
// \____  $$ | $$    | $$$$$$$$ \  $$/$$/| $$$$$$$$| $$  \__/|  $$$$$$   | $$    | $$$$$$$$ \  $$/$$/| $$$$$$$$|  $$$$$$ 
// /$$  \ $$ | $$ /$$| $$_____/  \  $$$/ | $$_____/| $$       \____  $$  | $$ /$$| $$_____/  \  $$$/ | $$_____/ \____  $$
//|  $$$$$$/ |  $$$$/|  $$$$$$$   \  $/  |  $$$$$$$| $$       /$$$$$$$/  |  $$$$/|  $$$$$$$   \  $/  |  $$$$$$$ /$$$$$$$/
// \______/   \___/   \_______/    \_/    \_______/|__/      |_______/    \___/   \_______/    \_/    \_______/|_______/ 

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

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                 Quick Info                                                                    //
// This indicator calculates linear regression models and correlations between a chosen data source and time.                    //
// It performs these calculations over different time intervals (e.g., 10, 20, ..., 100 candles) and It displays the results of  //
//these calculations in a table format on the chart, showing regression results, correlation values, and backtesting pass rates. //
// The table's rows represent different time intervals, and the columns show various results and metrics, including:             //
// 1. Regression results                                                                                                         //
// 2. Upper and lower range bounds                                                                                               //
// 3. Backtesting pass rate (percentage of times the data fell within the range)                                                 //
// 4. Correlation values                                                                                                         //
// 5. Trend assessments                                                                                                          //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//@version=5
indicator("[SS] Linear Modeler", overlay=true)

// Groups // 
g1 = "Display Settings" 
g2 = "Modelling Parameters"
g3 = "Backtest Results" 

// Tooltips // 
t1 = "Determines the length of regression assessment. Reccomended to select a length with the strongest correlation assessment."
t2 = "Performs back-test results on the inputed number of candles. Default is a 300 candle lookback period."
t3 = "Determines the source of the assessment. Select the desired variable you want to model (i.e. the High Price, Close price or Low price)."
t4 = "Plots a demographic label at the end of the plotted range." 

// user inputs // 
len =       input.int(50, "Assessment Length", tooltip = t1, group=g2) 
pos =       input.string("Bottom Right", "Table Position", ["Bottom Right", "Middle Right", "Centre", "Bottom Left", "Middle Left"], group = g1)
dispchart = input.bool(true, "Display Chart", group=g1)
dispbt =    input.bool(true, "Display Backtest Results", group=g1)
dispcor =   input.bool(true, "Display Correlation", group=g1) 
distrend =  input.bool(true, "Display Trend Result", group = g1)
lookback =  input.int(300, "Backtest Range", tooltip = t2, group=g3)
src =       input.source(close, "Source", tooltip=t3, group=g2) 
labels =    input.bool(false, "Plot Labels", tooltip = t4, group=g1) 
prjplot =   input.string("None", "Projection Plots", ["None", "10 Candles", "20 Candles", "30 Candles", "40 Candles", "50 Candles", "60 Candles", "70 Candles", "80 Candles", "90 Candles", "100 Candles"], group=g1)


// Pull Source Data //
src_data =          request.security(syminfo.ticker, "", src, lookahead = barmerge.lookahead_on) 
src_data_time =     request.security(syminfo.ticker, "", time, lookahead = barmerge.lookahead_on) 


// Colours //

color black =   color.rgb(0, 0, 0) 
color white =   color.white 
color transp =  color.new(color.white, 100)
color purple =  color.purple 
color orange =  color.orange
color green =   color.lime 
color red =     color.red 

// Fundamental Functions //
f_cor(len) =>
    ta.correlation(src_data, src_data_time, len) 

f_color_cor(variable) => 
    variable >= 0.5 or variable <= -0.5 ? green : red 

f_color_perc(variable) => 
    variable >= 51 ? green : red 
    
f_regression(float independent, float dependent, int len, float variable) =>

	y_array = array.new_float() 
	y_sq_array = array.new_float() 
	x_array = array.new_float() 
	x_sq_array = array.new_float() 
	xy_array = array.new_float() 

	// Loop functions
	for i = 0 to len
		array.push(y_array, dependent[i])
		array.push(y_sq_array, dependent[i] * dependent[i]) 
		array.push(x_array, independent[i])
		array.push(x_sq_array, independent[i] * independent[i]) 
		array.push(xy_array, independent[i] * dependent[i])
	
	// Regression Calculations 
	y = array.sum(y_array)
	y2 = array.sum(y_sq_array) 
	x = array.sum(x_array) 
	x2 = array.sum(x_sq_array)
	xy = array.sum(xy_array) 

	b1 = xy - (x * y) / len 
	bbb2 = x2 - (math.pow(x, 2) / len) 
	slope = (b1 / bbb2) 

	abc = y - (slope * x) 
	abc1 = abc / len 

	result = (variable * slope) + abc1 

f_standard_error(float result, float dependent, int len) =>
	se_residuals = array.new_float() 
	for i = 0 to len 
		array.push(se_residuals, (result[i] - dependent[i]) * (result[i] - dependent[i]))
	
	se_add = array.sum(se_residuals) 

	rk = se_add / (len - 2) 
	se= math.sqrt(rk) 

// Forecast Model // 
change = ta.change(src_data_time)

q10 = f_regression(src_data_time[10], src_data, len, (time + (change * 10)))
q20 = f_regression(src_data_time[20], src_data, len, (time + (change * 20)))
q30 = f_regression(src_data_time[30], src_data, len, (time + (change * 30)))
q40 = f_regression(src_data_time[40], src_data, len, (time + (change * 40)))
q50 = f_regression(src_data_time[50], src_data, len, (time + (change * 50)))
q60 = f_regression(src_data_time[60], src_data, len, (time + (change * 60)))
q70 = f_regression(src_data_time[70], src_data, len, (time + (change * 70)))
q80 = f_regression(src_data_time[80], src_data, len, (time + (change * 80)))
q90 = f_regression(src_data_time[90], src_data, len, (time + (change * 90)))
q100 = f_regression(src_data_time[100], src_data, len, (time + (change * 100)))

// Correlations //
q10_cor = f_cor(10)
q20_cor = f_cor(20) 
q30_cor = f_cor(30) 
q40_cor = f_cor(40) 
q50_cor = f_cor(50) 
q60_cor = f_cor(60) 
q70_cor = f_cor(70) 
q80_cor = f_cor(80)
q90_cor = f_cor(90) 
q100_cor = f_cor(100) 

// Range Determination // 
se_q10 = f_standard_error(q10[10], src_data, len) 
q10_ucl = se_q10 + q10 
q10_lcl = q10 - se_q10 

se_q20 = f_standard_error(q20[20], src_data, len) 
q20_ucl = q20 + se_q20 
q20_lcl = q20 - se_q20 

se_q30 = f_standard_error(q30[30], src_data, len) 
q30_ucl = q30 + se_q30 
q30_lcl = q30 - se_q30

se_q40 = f_standard_error(q40[40], src_data, len) 
q40_ucl = q40 + se_q40 
q40_lcl = q40 - se_q40

se_q50 = f_standard_error(q50[50], src_data, len) 
q50_ucl = q50 + se_q50 
q50_lcl = q50 - se_q50

se_q60 = f_standard_error(q60[60], src_data, len) 
q60_ucl = q60 + se_q60 
q60_lcl = q60 - se_q60

se_q70 = f_standard_error(q70[70], src_data, len) 
q70_ucl = q70 + se_q70 
q70_lcl = q70 - se_q70

se_q80 = f_standard_error(q80[80], src_data, len) 
q80_ucl = q80 + se_q80 
q80_lcl = q80 - se_q80

se_q90 = f_standard_error(q90[90], src_data, len) 
q90_ucl = q90 + se_q90 
q90_lcl = q90 - se_q90

se_q100 = f_standard_error(q100[100], src_data, len) 
q100_ucl = q100 + se_q100 
q100_lcl = q100 - se_q100

// Plot above functions // 

tableposition = pos == "Bottom Right" ? position.bottom_right : pos == "Bottom Left" ? position.bottom_left : pos == "Centre" ? position.middle_center : pos == "Bottom Right" ? position.bottom_right : pos == "Middle Left" ? position.middle_left : position.bottom_right
var data = table.new(tableposition, 9, 12, bgcolor = black, frame_color = white, frame_width = 3) 

if dispchart
    table.cell(data, 1, 1, text = "Time \n by Candle", bgcolor=black, text_color=white)
    table.cell(data, 2, 1, text = "Result", bgcolor=black, text_color=white)
    table.cell(data, 4, 1, text = "Upper Range", bgcolor=black, text_color=white)
    table.cell(data, 5, 1, text = "Lower Range", bgcolor=black, text_color=white)
if dispchart and dispbt
    table.cell(data, 6, 1, text = "% Within Range", bgcolor=black, text_color=white)
    table.cell(data, 3, 1, text = "% Result Achieved", bgcolor=black, text_color=white)
if dispchart and dispcor 
    table.cell(data, 7, 1, text = "Correlation", bgcolor=black, text_color=white)
if dispchart 
    table.cell(data, 1, 2, text = "10", bgcolor=black, text_color=white)
    table.cell(data, 1, 3, text = "20", bgcolor=black, text_color=white)
    table.cell(data, 1, 4, text = "30", bgcolor=black, text_color=white)
    table.cell(data, 1, 5, text = "40", bgcolor=black, text_color=white)
    table.cell(data, 1, 6, text = "50", bgcolor=black, text_color=white)
    table.cell(data, 1, 7, text = "60", bgcolor=black, text_color=white)
    table.cell(data, 1, 8, text = "70", bgcolor=black, text_color=white)
    table.cell(data, 1, 9, text = "80", bgcolor=black, text_color=white)
    table.cell(data, 1, 10, text = "90", bgcolor=black, text_color=white)
    table.cell(data, 1, 11, text = "100", bgcolor=black, text_color=white)
    table.cell(data, 2, 2, text = str.tostring(math.round(q10,2)), bgcolor=black, text_color=white)
    table.cell(data, 2, 3, text = str.tostring(math.round(q20,2)), bgcolor=black, text_color=white)
    table.cell(data, 2, 4, text = str.tostring(math.round(q30,2)), bgcolor=black, text_color=white)
    table.cell(data, 2, 5, text = str.tostring(math.round(q40,2)), bgcolor=black, text_color=white)
    table.cell(data, 2, 6, text = str.tostring(math.round(q50,2)), bgcolor=black, text_color=white)
    table.cell(data, 2, 7, text = str.tostring(math.round(q60,2)), bgcolor=black, text_color=white)
    table.cell(data, 2, 8, text = str.tostring(math.round(q70,2)), bgcolor=black, text_color=white)
    table.cell(data, 2, 9, text = str.tostring(math.round(q80, 2)), bgcolor=black, text_color=white)
    table.cell(data, 2, 10, text = str.tostring(math.round(q90,2)), bgcolor=black, text_color=white)
    table.cell(data, 2, 11, text = str.tostring(math.round(q100, 2)), bgcolor=black, text_color=white)
// error
    table.cell(data, 4, 2, text = str.tostring(math.round(q10_ucl,2)), bgcolor=black, text_color=white)
    table.cell(data, 4, 3, text = str.tostring(math.round(q20_ucl,2)), bgcolor=black, text_color=white)
    table.cell(data, 4, 4, text = str.tostring(math.round(q30_ucl,2)), bgcolor=black, text_color=white)
    table.cell(data, 4, 5, text = str.tostring(math.round(q40_ucl,2)), bgcolor=black, text_color=white)
    table.cell(data, 4, 6, text = str.tostring(math.round(q50_ucl,2)), bgcolor=black, text_color=white)
    table.cell(data, 4, 7, text = str.tostring(math.round(q60_ucl,2)), bgcolor=black, text_color=white)
    table.cell(data, 4, 8, text = str.tostring(math.round(q70_ucl,2)), bgcolor=black, text_color=white)
    table.cell(data, 4, 9, text = str.tostring(math.round(q80_ucl, 2)), bgcolor=black, text_color=white)
    table.cell(data, 4, 10, text = str.tostring(math.round(q90_ucl,2)), bgcolor=black, text_color=white)
    table.cell(data, 4, 11, text = str.tostring(math.round(q100_ucl, 2)), bgcolor=black, text_color=white)
    table.cell(data, 5, 2, text = str.tostring(math.round(q10_lcl,2)), bgcolor=black, text_color=white)
    table.cell(data, 5, 3, text = str.tostring(math.round(q20_lcl,2)), bgcolor=black, text_color=white)
    table.cell(data, 5, 4, text = str.tostring(math.round(q30_lcl,2)), bgcolor=black, text_color=white)
    table.cell(data, 5, 5, text = str.tostring(math.round(q40_lcl,2)), bgcolor=black, text_color=white)
    table.cell(data, 5, 6, text = str.tostring(math.round(q50_lcl,2)), bgcolor=black, text_color=white)
    table.cell(data, 5, 7, text = str.tostring(math.round(q60_lcl,2)), bgcolor=black, text_color=white)
    table.cell(data, 5, 8, text = str.tostring(math.round(q70_lcl,2)), bgcolor=black, text_color=white)
    table.cell(data, 5, 9, text = str.tostring(math.round(q80_lcl, 2)), bgcolor=black, text_color=white)
    table.cell(data, 5, 10, text = str.tostring(math.round(q90_lcl,2)), bgcolor=black, text_color=white)
    table.cell(data, 5, 11, text = str.tostring(math.round(q100_lcl, 2)), bgcolor=black, text_color=white)
//correlation
if dispcor and dispchart
    table.cell(data, 7, 2, text = str.tostring(math.round(q10_cor,2)), bgcolor=black, text_color=f_color_cor(q10_cor))
    table.cell(data, 7, 3, text = str.tostring(math.round(q20_cor,2)), bgcolor=black, text_color=f_color_cor(q20_cor))
    table.cell(data, 7, 4, text = str.tostring(math.round(q30_cor,2)), bgcolor=black, text_color=f_color_cor(q30_cor))
    table.cell(data, 7, 5, text = str.tostring(math.round(q40_cor,2)), bgcolor=black, text_color=f_color_cor(q40_cor))
    table.cell(data, 7, 6, text = str.tostring(math.round(q50_cor,2)), bgcolor=black, text_color=f_color_cor(q50_cor))
    table.cell(data, 7, 7, text = str.tostring(math.round(q60_cor,2)), bgcolor=black, text_color=f_color_cor(q60_cor))
    table.cell(data, 7, 8, text = str.tostring(math.round(q70_cor,2)), bgcolor=black, text_color=f_color_cor(q70_cor))
    table.cell(data, 7, 9, text = str.tostring(math.round(q80_cor, 2)), bgcolor=black, text_color=f_color_cor(q80_cor))
    table.cell(data, 7, 10, text = str.tostring(math.round(q90_cor,2)), bgcolor=black, text_color=f_color_cor(q90_cor))
    table.cell(data, 7, 11, text = str.tostring(math.round(q100_cor, 2)), bgcolor=black, text_color=f_color_cor(q100_cor))

// Range Backtest // 
int q10_pass = 0 
int q10_fail = 0 
int q20_pass = 0 
int q20_fail = 0 
int q30_pass = 0 
int q30_fail = 0 
int q40_pass = 0 
int q40_fail = 0 
int q50_pass = 0 
int q50_fail = 0 
int q60_pass = 0 
int q60_fail = 0 
int q70_pass = 0 
int q70_fail = 0 
int q80_pass = 0 
int q80_fail = 0 
int q90_pass = 0 
int q90_fail = 0 
int q100_pass = 0 
int q100_fail = 0 

bool q10_rng_bt = src_data >= q10_lcl[10] and src_data <= q10_ucl[10] 
bool q20_rng_bt = src_data >= q20_lcl[20] and src_data <= q20_ucl[20] 
bool q30_rng_bt = src_data >= q30_lcl[30] and src_data <= q30_ucl[30] 
bool q40_rng_bt = src_data >= q40_lcl[40] and src_data <= q40_ucl[40] 
bool q50_rng_bt = src_data >= q50_lcl[50] and src_data <= q50_ucl[50] 
bool q60_rng_bt = src_data >= q60_lcl[60] and src_data <= q50_ucl[60] 
bool q70_rng_bt = src_data >= q70_lcl[70] and src_data <= q70_ucl[70] 
bool q80_rng_bt = src_data >= q80_lcl[80] and src_data <= q80_ucl[80] 
bool q90_rng_bt = src_data >= q90_lcl[90] and src_data <= q90_ucl[90] 
bool q100_rng_bt = src_data >= q100_lcl[100] and src_data <= q100_ucl[100] 
for i = 0 to lookback 
    if q10_rng_bt[i] and barstate.islast
        q10_pass := q10_pass + 1
    else 
        q10_fail := q10_fail + 1
    
    if q20_rng_bt[i] and barstate.islast 
        q20_pass := q20_pass + 1
    else 
        q20_fail := q20_fail + 1

    if q30_rng_bt[i] and barstate.islast 
        q30_pass := q30_pass + 1
    else 
        q30_fail := q30_fail + 1

    if q40_rng_bt[i] and barstate.islast  
        q40_pass := q40_pass + 1
    else 
        q40_fail := q40_fail + 1

    if q50_rng_bt[i] and barstate.islast 
        q50_pass := q50_pass + 1
    else 
        q50_fail := q50_fail + 1

    if q60_rng_bt[i] and barstate.islast 
        q60_pass := q60_pass + 1
    else 
        q60_fail := q60_fail + 1

    if q70_rng_bt[i] and barstate.islast 
        q70_pass := q70_pass + 1
    else 
        q70_fail := q70_fail + 1

    if q80_rng_bt[i] and barstate.islast 
        q80_pass := q80_pass + 1
    else 
        q80_fail := q80_fail + 1

    if q90_rng_bt[i] and barstate.islast 
        q90_pass := q90_pass + 1
    else 
        q90_fail := q90_fail + 1

    if q100_rng_bt[i] and barstate.islast 
        q100_pass := q100_pass + 1
    else
        q100_fail := q100_fail + 1

f_perc(pass, fail) => 
    pass / (pass + fail) * 100 

q10_pass_res = (q10_pass / (q10_pass + q10_fail)) * 100 
q20_pass_res = (q20_pass / (q20_pass + q20_fail)) * 100 
q30_pass_res = (q30_pass / (q30_pass + q30_fail)) * 100 
q40_pass_res = (q40_pass / (q40_pass + q40_fail)) * 100 
q50_pass_res = (q50_pass / (q50_pass + q50_fail)) * 100 
q60_pass_res = (q60_pass / (q60_pass + q60_fail)) * 100 
q70_pass_res = f_perc(q70_pass, q70_fail)
q80_pass_res = f_perc(q80_pass, q80_fail)
q90_pass_res = f_perc(q90_pass, q90_fail)
q100_pass_res = f_perc(q100_pass, q100_fail)

// Result Backtest // 
highest10 = ta.highest(high, 10) 
lowest10 = ta.lowest(low, 10) 
highest20 = ta.highest(high, 20) 
lowest20 = ta.lowest(low, 20) 
highest30 = ta.highest(high, 30) 
lowest30 = ta.lowest(low, 30) 
highest40 = ta.highest(high, 40) 
lowest40 = ta.lowest(low, 40) 
highest50 = ta.highest(high, 50) 
lowest50 = ta.lowest(low, 50) 
highest60 = ta.highest(high, 60) 
lowest60 = ta.lowest(low, 60) 
highest70 = ta.highest(high, 70) 
lowest70 = ta.lowest(low, 70) 
highest80 = ta.highest(high, 80) 
lowest80 = ta.lowest(low, 80) 
highest90 = ta.highest(high, 90) 
lowest90 = ta.lowest(low, 90) 
highest100 = ta.highest(high, 100) 
lowest100 = ta.lowest(low, 100) 

int q10_res_pass = 0
int q10_res_fail = 0 
int q20_res_pass = 0
int q20_res_fail = 0 
int q30_res_pass = 0
int q30_res_fail = 0 
int q40_res_pass = 0
int q40_res_fail = 0 
int q50_res_pass = 0
int q50_res_fail = 0 
int q60_res_pass = 0
int q60_res_fail = 0 
int q70_res_pass = 0
int q70_res_fail = 0 
int q80_res_pass = 0
int q80_res_fail = 0 
int q90_res_pass = 0
int q90_res_fail = 0 
int q100_res_pass = 0
int q100_res_fail = 0 

bool q10_bt = q10[10] <= highest10 and q10[10] >= lowest10 
bool q20_bt = q20[20] <= highest20 and q20[20] >= lowest20 
bool q30_bt = q30[30] <= highest30 and q30[30] >= lowest30 
bool q40_bt = q40[40] <= highest40 and q40[40] >= lowest40 
bool q50_bt = q50[50] <= highest50 and q50[50] >= lowest50 
bool q60_bt = q60[60] <= highest60 and q60[60] >= lowest60 
bool q70_bt = q70[70] <= highest70 and q70[70] >= lowest70 
bool q80_bt = q80[80] <= highest80 and q80[80] >= lowest80 
bool q90_bt = q90[90] <= highest90 and q90[90] >= lowest90 
bool q100_bt = q100[100] <= highest100 and q100[100] >= lowest100 

for i = 0 to lookback 
     
    if q10_bt[i] and barstate.islast 
        q10_res_pass := q10_res_pass + 1 
    else 
        q10_res_fail := q10_res_fail + 1 
    if q20_bt[i] and barstate.islast 
        q20_res_pass := q20_res_pass + 1 

    else 
        q20_res_fail := q20_res_fail + 1 
         
    if q30_bt[i] and barstate.islast 
        q30_res_pass := q30_res_pass + 1 
    else 
        q30_res_fail := q30_res_fail + 1

    if q40_bt[i] and barstate.islast 
        q40_res_pass := q40_res_pass + 1 
    else 
        q40_res_fail := q40_res_fail + 1 

    if q50_bt[i] and barstate.islast 
        q50_res_pass := q50_res_pass + 1 
    else 
        q50_res_fail := q50_res_fail + 1 

    if q60_bt[i] and barstate.islast 
        q60_res_pass := q60_res_pass + 1 
    else 
        q60_res_fail := q60_res_fail + 1

    if q70_bt[i] and barstate.islast 
        q70_res_pass := q70_res_pass + 1 
    else 
        q70_res_fail := q70_res_fail + 1

    if q80_bt[i] and barstate.islast 
        q80_res_pass := q80_res_pass + 1 
    else 
        q80_res_fail := q80_res_fail + 1

    if q90_bt[i] and barstate.islast 
        q90_res_pass := q90_res_pass + 1 
    else 
        q90_res_fail := q90_res_fail + 1

    if q100_bt[i] and barstate.islast 
        q100_res_pass := q100_res_pass + 1 
    else 
        q100_res_fail := q100_res_fail + 1


q10_perc = f_perc(q10_res_pass, q10_res_fail) 
q20_perc = f_perc(q20_res_pass, q20_res_fail)  
q30_perc = f_perc(q30_res_pass, q30_res_fail) 
q40_perc = f_perc(q40_res_pass, q40_res_fail) 
q50_perc = f_perc(q50_res_pass, q50_res_fail)  
q60_perc = f_perc(q60_res_pass, q60_res_fail) 
q70_perc = f_perc(q70_res_pass, q70_res_fail) 
q80_perc = f_perc(q80_res_pass, q80_res_fail) 
q90_perc = f_perc(q90_res_pass, q90_res_fail)  
q100_perc = f_perc(q100_res_pass, q100_res_fail)

// Plot above functions // 
if dispbt and dispchart
    table.cell(data, 6, 2, text = str.tostring(math.round(q10_pass_res, 2)) + "%", bgcolor = black, text_color = f_color_perc(q10_pass_res)) 
    table.cell(data, 6, 3, text = str.tostring(math.round(q20_pass_res, 2)) + "%", bgcolor = black, text_color = f_color_perc(q20_pass_res)) 
    table.cell(data, 6, 4, text = str.tostring(math.round(q30_pass_res, 2)) + "%", bgcolor = black, text_color = f_color_perc(q30_pass_res)) 
    table.cell(data, 6, 5, text = str.tostring(math.round(q40_pass_res, 2)) + "%", bgcolor = black, text_color = f_color_perc(q40_pass_res)) 
    table.cell(data, 6, 6, text = str.tostring(math.round(q50_pass_res, 2)) + "%", bgcolor = black, text_color = f_color_perc(q50_pass_res)) 
    table.cell(data, 6, 7, text = str.tostring(math.round(q60_pass_res, 2)) + "%", bgcolor = black, text_color = f_color_perc(q60_pass_res)) 
    table.cell(data, 6, 8, text = str.tostring(math.round(q70_pass_res, 2)) + "%", bgcolor = black, text_color = f_color_perc(q70_pass_res)) 
    table.cell(data, 6, 9, text = str.tostring(math.round(q80_pass_res, 2)) + "%", bgcolor = black, text_color = f_color_perc(q80_pass_res)) 
    table.cell(data, 6, 10, text = str.tostring(math.round(q90_pass_res, 2)) + "%", bgcolor = black, text_color = f_color_perc(q90_pass_res)) 
    table.cell(data, 6, 11, text = str.tostring(math.round(q100_pass_res, 2)) + "%", bgcolor = black, text_color = f_color_perc(q100_pass_res)) 
    table.cell(data, 3, 2, text = str.tostring(math.round(q10_perc, 2)) + "%", bgcolor = black, text_color = f_color_perc(q10_perc)) 
    table.cell(data, 3, 3, text = str.tostring(math.round(q20_perc, 2)) + "%", bgcolor = black, text_color = f_color_perc(q20_perc)) 
    table.cell(data, 3, 4, text = str.tostring(math.round(q30_perc, 2)) + "%", bgcolor = black, text_color = f_color_perc(q30_perc)) 
    table.cell(data, 3, 5, text = str.tostring(math.round(q40_perc, 2)) + "%", bgcolor = black, text_color = f_color_perc(q40_perc)) 
    table.cell(data, 3, 6, text = str.tostring(math.round(q50_perc, 2)) + "%", bgcolor = black, text_color = f_color_perc(q50_perc)) 
    table.cell(data, 3, 7, text = str.tostring(math.round(q60_perc, 2)) + "%", bgcolor = black, text_color = f_color_perc(q60_perc)) 
    table.cell(data, 3, 8, text = str.tostring(math.round(q70_perc, 2)) + "%", bgcolor = black, text_color = f_color_perc(q70_perc)) 
    table.cell(data, 3, 9, text = str.tostring(math.round(q80_perc, 2)) + "%", bgcolor = black, text_color = f_color_perc(q80_perc)) 
    table.cell(data, 3, 10, text = str.tostring(math.round(q90_perc, 2)) + "%", bgcolor = black, text_color = f_color_perc(q90_perc)) 
    table.cell(data, 3, 11, text = str.tostring(math.round(q100_perc, 2)) + "%", bgcolor = black, text_color = f_color_perc(q100_perc)) 


// Range Plotting Functions // 
var float plot_input = 0.0 
var float plot_input_ucl = 0.0 
var float plot_input_lcl = 0.0 
var int offset_int = 0 


if prjplot == "10 Candles" 
    plot_input := q10 
    plot_input_ucl := q10_ucl 
    plot_input_lcl := q10_lcl 
    offset_int := 10 
if prjplot == "20 Candles" 
    plot_input := q20 
    plot_input_ucl := q20_ucl 
    plot_input_lcl := q20_lcl 
    offset_int := 20 
if prjplot == "30 Candles" 
    plot_input := q30 
    plot_input_ucl := q30_ucl 
    plot_input_lcl := q30_lcl 
    offset_int := 30 
if prjplot == "40 Candles" 
    plot_input := q40 
    plot_input_ucl := q40_ucl 
    plot_input_lcl := q40_lcl 
    offset_int := 40 
if prjplot == "50 Candles" 
    plot_input := q50 
    plot_input_ucl := q50_ucl 
    plot_input_lcl := q50_lcl 
    offset_int := 50 
if prjplot == "60 Candles" 
    plot_input := q60 
    plot_input_ucl := q60_ucl 
    plot_input_lcl := q60_lcl 
    offset_int := 60 
if prjplot == "70 Candles" 
    plot_input := q70 
    plot_input_ucl := q70_ucl 
    plot_input_lcl := q70_lcl 
    offset_int := 70 
if prjplot == "80 Candles" 
    plot_input := q80 
    plot_input_ucl := q80_ucl 
    plot_input_lcl := q80_lcl
    offset_int := 80 
if prjplot == "90 Candles" 
    plot_input := q90 
    plot_input_ucl := q90_ucl 
    plot_input_lcl := q90_lcl 
    offset_int := 90 
if prjplot == "100 Candles" 
    plot_input := q100 
    plot_input_ucl := q100_ucl 
    plot_input_lcl := q100_lcl 
    offset_int := 100



plot(plot_input, color=purple, linewidth=3, offset = offset_int)  
plot(plot_input_lcl, color = orange, linewidth=3, offset = offset_int)
plot(plot_input_ucl, color = orange, linewidth=3, offset = offset_int) 

// Plot labels //

var label q10_label = na 
var label q20_label = na 
var label q30_label = na 
var label q40_label = na 
var label q50_label = na 
var label q60_label = na 
var label q70_label = na 
var label q80_label = na 
var label q90_label = na 
var label q100_label = na 


if labels and barstate.islast 
    label.delete(q10_label) 
    label.delete(q20_label)
    label.delete(q30_label)
    label.delete(q40_label)   
    label.delete(q50_label) 
    label.delete(q60_label) 
    label.delete(q70_label)
    label.delete(q80_label)
    label.delete(q90_label)   
    label.delete(q100_label) 
    if prjplot == "10 Candles" 
        q10_label := label.new(bar_index + 10, y=plot_input, text = "Projection at 10 Candles \n Range: $" + str.tostring(math.round(q10_lcl,2)) + " to $" + str.tostring(math.round(q10_ucl,2)) +  "\n Correlation: " + str.tostring(math.round(q10_cor,2)) + "\n Reliability: " + str.tostring(math.round(q10_pass_res,2)) + "%", style = label.style_label_left, textcolor = purple, color = transp, size = size.large)
    if prjplot == "20 Candles" 
        q20_label := label.new(bar_index + 20, y=plot_input, text = "Projection at 20 Candles \n Range: $" + str.tostring(math.round(q20_lcl,2)) + " to $" + str.tostring(math.round(q20_ucl,2)) +  "\n Correlation: " + str.tostring(math.round(q20_cor,2)) + "\n Reliability: " + str.tostring(math.round(q20_pass_res,2)) + "%", style = label.style_label_left, textcolor = purple, color = transp, size = size.large)
    if prjplot == "30 Candles" 
        q30_label := label.new(bar_index + 30, y=plot_input, text = "Projection at 30 Candles \n Range: $" + str.tostring(math.round(q30_lcl,2)) + " to $" + str.tostring(math.round(q30_ucl,2)) +  "\n Correlation: " + str.tostring(math.round(q30_cor,2)) + "\n Reliability: " + str.tostring(math.round(q30_pass_res,2)) + "%", style = label.style_label_left, textcolor = purple, color = transp, size = size.large)
    if prjplot == "40 Candles" 
        q40_label := label.new(bar_index + 40, y=plot_input, text = "Projection at 40 Candles \n Range: $" + str.tostring(math.round(q40_lcl,2)) + " to $" + str.tostring(math.round(q40_ucl,2)) +  "\n Correlation: " + str.tostring(math.round(q40_cor,2)) + "\n Reliability: " + str.tostring(math.round(q40_pass_res,2)) + "%", style = label.style_label_left, textcolor = purple, color = transp, size = size.large)
    if prjplot == "50 Candles" 
        q50_label := label.new(bar_index + 50, y=plot_input, text = "Projection at 50 Candles \n Range: $" + str.tostring(math.round(q50_lcl,2)) + " to $" + str.tostring(math.round(q50_ucl,2)) +  "\n Correlation: " + str.tostring(math.round(q50_cor,2)) + "\n Reliability: " + str.tostring(math.round(q50_pass_res,2)) + "%", style = label.style_label_left, textcolor = purple, color = transp, size = size.large)
    if prjplot == "60 Candles" 
        q60_label := label.new(bar_index + 60, y=plot_input, text = "Projection at 60 Candles \n Range: $" + str.tostring(math.round(q60_lcl,2)) + " to $" + str.tostring(math.round(q60_ucl,2)) +  "\n Correlation: " + str.tostring(math.round(q60_cor,2)) + "\n Reliability: " + str.tostring(math.round(q60_pass_res,2)) + "%", style = label.style_label_left, textcolor = purple, color = transp, size = size.large)
    if prjplot == "70 Candles" 
        q70_label := label.new(bar_index + 70, y=plot_input, text = "Projection at 70 Candles \n Range: $" + str.tostring(math.round(q70_lcl,2)) + " to $" + str.tostring(math.round(q70_ucl,2)) +  "\n Correlation: " + str.tostring(math.round(q70_cor,2)) + "\n Reliability: " + str.tostring(math.round(q70_pass_res,2)) + "%", style = label.style_label_left, textcolor = purple, color = transp, size = size.large)
    if prjplot == "80 Candles" 
        q80_label := label.new(bar_index + 80, y=plot_input, text = "Projection at 80 Candles \n Range: $" + str.tostring(math.round(q80_lcl,2)) + " to $" + str.tostring(math.round(q80_ucl,2)) +  "\n Correlation: " + str.tostring(math.round(q80_cor,2)) + "\n Reliability: " + str.tostring(math.round(q80_pass_res,2)) + "%", style = label.style_label_left, textcolor = purple, color = transp, size = size.large)
    if prjplot == "90 Candles" 
        q90_label := label.new(bar_index + 90, y=plot_input, text = "Projection at 90 Candles \n Range: $" + str.tostring(math.round(q90_lcl,2)) + " to $" + str.tostring(math.round(q90_ucl,2)) +  "\n Correlation: " + str.tostring(math.round(q90_cor,2)) + "\n Reliability: " + str.tostring(math.round(q90_pass_res,2)) + "%", style = label.style_label_left, textcolor = purple, color = transp, size = size.large)
    if prjplot == "100 Candles" 
        q100_label := label.new(bar_index + 100, y=plot_input, text = "Projection at 100 Candles \n Range: $" + str.tostring(math.round(q100_lcl,2)) + " to $" + str.tostring(math.round(q100_ucl,2)) +  "\n Correlation: " + str.tostring(math.round(q100_cor,2)) + "\n Reliability: " + str.tostring(math.round(q100_pass_res,2)) + "%", style = label.style_label_left, textcolor = purple, color = transp, size = size.large)


f_trend(cor) => 
    string res = na 
    if cor >= 0.5 and cor <= 0.7 
        res := "Moderate Uptrend"
    else if cor > 0.7 
        res := "Strong Uptrend" 
    else if cor <= -0.5 and cor >= -0.7 
        res := "Moderate Downtrend"
    else if cor < -0.7 
        res := "Strong Downtrend"
    else 
        res := "No Clear Trend"
trend_color(cor) => 
    if cor >= 0.5 and cor <= 0.7 
        color.lime
    else if cor > 0.7 
        color.lime 
    else if cor <= -0.5 and cor >= -0.7
        color.red 
    else if cor < -0.7 
        color.red 
    else 
        color.orange 
s_10 = f_trend(q10_cor)
s_20 = f_trend(q20_cor) 
s_30 = f_trend(q30_cor) 
s_40 = f_trend(q40_cor) 
s_50 = f_trend(q50_cor) 
s_60 = f_trend(q60_cor) 
s_70 = f_trend(q70_cor) 
s_80 = f_trend(q80_cor) 
s_90 = f_trend(q90_cor) 
s_100 = f_trend(q100_cor) 


// Trend Table

if distrend and dispchart
    table.cell(data, 8, 1, text = "Trend", bgcolor = black, text_color = white)
    table.cell(data, 8, 2, text = str.tostring(s_10), bgcolor = black, text_color = trend_color(q10_cor))
    table.cell(data, 8, 3, text = str.tostring(s_20), bgcolor = black, text_color = trend_color(q20_cor))
    table.cell(data, 8, 4, text = str.tostring(s_30), bgcolor = black, text_color = trend_color(q30_cor))
    table.cell(data, 8, 5, text = str.tostring(s_40), bgcolor = black, text_color = trend_color(q40_cor))
    table.cell(data, 8, 6, text = str.tostring(s_50), bgcolor = black, text_color = trend_color(q50_cor))
    table.cell(data, 8, 7, text = str.tostring(s_60), bgcolor = black, text_color = trend_color(q60_cor))
    table.cell(data, 8, 8, text = str.tostring(s_70), bgcolor = black, text_color = trend_color(q70_cor))
    table.cell(data, 8, 9, text = str.tostring(s_80), bgcolor = black, text_color = trend_color(q80_cor))
    table.cell(data, 8, 10, text = str.tostring(s_90), bgcolor = black, text_color = trend_color(q90_cor))
    table.cell(data, 8, 11, text = str.tostring(s_100), bgcolor = black, text_color = trend_color(q100_cor))

