Predictive Candles Variety Pack [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("Predictive Candles Variety Pack [SS]", overlay=true)

// Tooltips 
t1 = "Adjusts the transparency/strength of the colours of the candles." 
t2 = "Select the type of predictive candle you would like."
t3 = "Show Backtest results (over length)" 

len =           input.int(500, "Length")
transp =        input.int(85, "Transparency", tooltip = t1)  
candle_type =   input.string("LinReg Candles", "Candle Types", ["LinReg Candles", "MFI Based Candles", "Stochastic Based Candles", "RSI Based Candles", "9 EMA Candles", "ARIMA Candles"], tooltip = t2)
bt =            input.bool(false, "Backtest", tooltip = t3)

// Candle Plot
float op = 0.0 
float hi = 0.0 
float lo = 0.0 
float cl = 0.0 

// Range Variables
hitoop = high[1] - open[1] 
optolo = open[1] - low[1] 
optoclose = close[1] - open[1]

// Functions
ar_f() => 
    array.new_float() 

f_linreg(y, x, len, bool stationarity_test) =>
    float result = 0.0 
    float std_err = 0.0 
    float cor = 0.0 
    float r2 = 0.0 
    float slope = 0.0 
    dep_array = array.new<float>() 
    indep_array = array.new<float>() 
    for i = 0 to len 
        array.push(dep_array, y[i])
        array.push(indep_array, x[i])
    // Average 
    dep_avg = array.avg(dep_array) 
    indep_avg = array.avg(indep_array) 
    // Covariance
    covariance = array.covariance(dep_array, indep_array) 
    variance = array.variance(indep_array) 
    slope := (covariance / variance) 
    intercept = dep_avg - (indep_avg * slope) 
    result := (x * slope) + intercept 
    result

f_stationarity(y, x, len, bool stationarity_test) =>
    float result = 0.0 
    float std_err = 0.0 
    float cor = 0.0 
    float r2 = 0.0 
    float slope = 0.0 
    dep_array = array.new<float>() 
    indep_array = array.new<float>() 
    for i = 0 to len 
        array.push(dep_array, y[i])
        array.push(indep_array, x[i])
    // Average 
    dep_avg = array.avg(dep_array) 
    indep_avg = array.avg(indep_array) 
    // Covariance
    covariance = array.covariance(dep_array, indep_array) 
    variance = array.variance(indep_array) 
    slope := (covariance / variance) 
    intercept = dep_avg - (indep_avg * slope) 
    result := (x * slope) + intercept 
    // Standard Error 
    se_residuals = array.new_float() 
    for i = 0 to len 
        array.push(se_residuals, (result[i] - y[i]) * (result[i] - y[i]))
    se_add = array.sum(se_residuals) 
    r1 = se_add / (len - 2) 
	std_err := stationarity_test ? 0 : math.sqrt(r1) 
    // Correlation 
    sd1 = array.stdev(dep_array) 
    sd2 = array.stdev(indep_array) 
    cor := covariance / (sd1 * sd2) 
    r2 := math.pow(cor,2)
    [result, std_err, cor, r2, slope]

f_armia_basic_stationary(x) => 
    float t_stat = 0.0 
    bool result = na 
    //returns = (x - x[1]) / x[1] * 100 
    float lagged_x = x[1]
    float delta_x = (x - x[1])
    [r, er, cor, r2, sl] = f_stationarity(delta_x, lagged_x, len, true) 
    t_stat := (sl / er) 
    result := t_stat <= -1.62 ? true : false 
    result 
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



if candle_type == "LinReg Candles" 
    op := f_linreg(open, open[1], len, false) 
    hi := f_linreg(high, high[1], len, false) 
    lo := f_linreg(low, low[1], len, false) 
    cl := f_linreg(close, close[1], len, false) 

if candle_type == "MFI Based Candles" 
    mfi = ta.mfi(close[1], 14) 
    prev_mfi = mfi[1]
    cur_mfi_a = ar_f() 
    mfi_hi_rng_a = ar_f() 
    mfi_lo_rng_a = ar_f() 
    mfi_cl_rng_a = ar_f() 
    mfi_ar = ar_f() 
    // Ranges
    float mfi_hi_tgt = 0.0
    float mfi_lo_tgt = 0.0 
    float mfi_cl_tgt = 0.0 
    int mfi_int = 0
    for i = 0 to 1 
        array.push(cur_mfi_a, mfi[i]) 
    for i = 0 to len 
        array.push(mfi_ar, prev_mfi[i]) 
        array.push(mfi_hi_rng_a, hitoop[i]) 
        array.push(mfi_lo_rng_a, optolo[i]) 
        array.push(mfi_cl_rng_a, optoclose[i]) 

    // Search 
    current_mfi = array.get(cur_mfi_a, 0)   
    for i = 0 to array.size(mfi_ar) - 1 
        if array.get(mfi_ar, i) >= current_mfi - 0.5 and array.get(mfi_ar, i) <= current_mfi + 0.5 
            mfi_int += 1 
            mfi_hi_tgt += array.get(mfi_hi_rng_a, i) 
            mfi_lo_tgt += array.get(mfi_lo_rng_a, i)
            mfi_cl_tgt += array.get(mfi_cl_rng_a, i) 
    op := open 
    hi := open + (mfi_hi_tgt / mfi_int) 
    lo := open - (mfi_lo_tgt / mfi_int) 
    cl := open + (mfi_cl_tgt / mfi_int) 

if candle_type == "RSI Based Candles" 
    rsi= ta.rsi(close[1], 14) 
    prev_rsi = rsi[1]
    cur_rsi_a = ar_f() 
    rsi_hi_rng_a = ar_f() 
    rsi_lo_rng_a = ar_f() 
    rsi_cl_rng_a = ar_f() 
    rsi_ar = ar_f() 
    // Ranges
    float rsi_hi_tgt = 0.0
    float rsi_lo_tgt = 0.0 
    float rsi_cl_tgt = 0.0 
    int rsi_int = 0
    for i = 0 to 1 
        array.push(cur_rsi_a, rsi[i]) 
    for i = 0 to len 
        array.push(rsi_ar, prev_rsi[i]) 
        array.push(rsi_hi_rng_a, hitoop[i]) 
        array.push(rsi_lo_rng_a, optolo[i]) 
        array.push(rsi_cl_rng_a, optoclose[i]) 

    // Search 
    current_rsi = array.get(cur_rsi_a, 0)   
    for i = 0 to array.size(rsi_ar) - 1 
        if array.get(rsi_ar, i) >= current_rsi - 0.5 and array.get(rsi_ar, i) <= current_rsi + 0.5 
            rsi_int += 1 
            rsi_hi_tgt += array.get(rsi_hi_rng_a, i) 
            rsi_lo_tgt += array.get(rsi_lo_rng_a, i)
            rsi_cl_tgt += array.get(rsi_cl_rng_a, i) 
    op := open 
    hi := open + (rsi_hi_tgt / rsi_int) 
    lo := open - (rsi_lo_tgt / rsi_int) 
    cl := open + (rsi_cl_tgt / rsi_int) 

if candle_type == "Stochastic Based Candles" 
    sto = ta.stoch(close[1], high[1], low[1], 14) 
    prev_sto = sto[1]
    cur_sto_a = ar_f() 
    sto_hi_rng_a = ar_f() 
    sto_lo_rng_a = ar_f() 
    sto_cl_rng_a = ar_f() 
    sto_ar = ar_f() 
    // Ranges
    float sto_hi_tgt = 0.0
    float sto_lo_tgt = 0.0 
    float sto_cl_tgt = 0.0 
    int sto_int = 0
    for i = 0 to 1 
        array.push(cur_sto_a, sto[i]) 
    for i = 0 to len 
        array.push(sto_ar, prev_sto[i]) 
        array.push(sto_hi_rng_a, hitoop[i]) 
        array.push(sto_lo_rng_a, optolo[i]) 
        array.push(sto_cl_rng_a, optoclose[i]) 

    // Search 
    current_sto = array.get(cur_sto_a, 0)   
    for i = 0 to array.size(sto_ar) - 1 
        if array.get(sto_ar, i) >= current_sto - 0.5 and array.get(sto_ar, i) <= current_sto + 0.5 
            sto_int += 1 
            sto_hi_tgt += array.get(sto_hi_rng_a, i) 
            sto_lo_tgt += array.get(sto_lo_rng_a, i)
            sto_cl_tgt += array.get(sto_cl_rng_a, i) 
    op := open 
    hi := open + (sto_hi_tgt / sto_int) 
    lo := open - (sto_lo_tgt / sto_int) 
    cl := open + (sto_cl_tgt / sto_int) 

if candle_type == "9 EMA Candles" 
    op := ta.ema(open, 9) 
    hi := ta.ema(high, 9) 
    lo := ta.ema(low, 9) 
    cl := ta.ema(close, 9)

if candle_type == "ARIMA Candles" 
    op_lag_5 = open[5],     op_lag_10 = open[10],       
    hi_lag_5 = high[5],     hi_lag_10 = high[10],       
    lo_lag_5 = low[5],     lo_lag_10 = low[10],        
    cl_lag_5 = close[5],     cl_lag_10 = close[10],       

    // Stationarity 
    op_lag_5_r = f_armia_basic_stationary(op_lag_5),    op_lag_10_r = f_armia_basic_stationary(op_lag_10),         
    hi_lag_5_r = f_armia_basic_stationary(hi_lag_5),    hi_lag_10_r = f_armia_basic_stationary(hi_lag_10),          
    lo_lag_5_r = f_armia_basic_stationary(lo_lag_5),    lo_lag_10_r = f_armia_basic_stationary(lo_lag_10),          
    cl_lag_5_r = f_armia_basic_stationary(cl_lag_5),    cl_lag_10_r = f_armia_basic_stationary(cl_lag_10),     


    int oplag = op_lag_5_r == true ? 5 : op_lag_10_r == true ? 10 : 20
    int hilag = hi_lag_5_r == true ? 5 : hi_lag_10_r == true ? 10 : 20
    int lolag = lo_lag_5_r == true ? 5 : lo_lag_10_r == true ? 10 : 20
    int cllag = cl_lag_5_r == true ? 5 : cl_lag_10_r == true ? 10 : 20
            
    op := f_linreg(open, open[oplag], len, false) 
    hi := f_linreg(high, high[hilag], len, false) 
    lo := f_linreg(low, low[lolag], len, false) 
    cl := f_linreg(close, close[cllag], len, false) 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
color red = color.new(color.red, transp) 
color green = color.new(color.lime, transp) 
color black = color.rgb(0, 0, 0) 
color white = color.white 
color candlecolor = op > cl ? red : cl > op ? green : green 

plotcandle(op, hi, lo, cl, color = candlecolor)  

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if bt 
    int candle_color = 0 
    int hi_obtained = 0 
    int lo_obtained = 0 
    
    bool candle_color_pass = cl > op and close > open or op > cl and open > close 
    bool hi_pass = high >= hi 
    bool lo_pass = low <= lo 

    for i = 0 to len 
        if candle_color_pass[i] 
            candle_color += 1 
        if hi_pass[i] 
            hi_obtained += 1 
        if lo_pass[i]
            lo_obtained += 1 
    hi_perc = (hi_obtained / len) * 100 
    lo_perc = (lo_obtained / len) * 100 
    candle_perc = (candle_color / len) * 100 
    var table bt_table = table.new(position.middle_right, 5, 5, bgcolor = black, frame_color = white, frame_width=3) 
    table.cell(bt_table, 1, 1, text = "Backtest Results for \n" + str.tostring(candle_type), bgcolor = black, text_color = white) 
    table.cell(bt_table, 1, 2, text = "Candle Sentiment Pass Rate: " + str.tostring(math.round(candle_perc,2)) + "%", bgcolor = black, text_color = white) 
    table.cell(bt_table, 1, 3, text = "High Target Success Rate: " + str.tostring(math.round(hi_perc,2)) + "%", bgcolor = black, text_color = white) 
    table.cell(bt_table, 1, 4, text = "Low Target Success Rate : " + str.tostring(math.round(lo_perc,2)) + "%", bgcolor = black, text_color = white) 


