Technical Dashboard with High and Low Price Prediction 
// 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("Technical Dashboard", overlay=true)

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            User Inputs                                                                              ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Stochastic inputs 
showsto = input.bool(true, title="Show Stochastics", group="Stochastics")
stolength = input.int(14, title="Stochastic Length (K)", group = "Stochastics") 
stosmad = input.int(3, title="Stochastic SMA (D)", group="Stochastics")
storeversal = input.bool(false, title="Display Reversals based on SMA", group="Stochastics")

// RSI Inputs 
showrsi = input.bool(true, title="Show RSI", group="RSI")
rsilength = input.int(14, title="RSI Length", group="RSI") 
rsisource = input.source(close, title="RSI Source", group="RSI") 
rsismalength = input.int(14, title="RSI SMA Length", group="RSI")
rsireversal = input.bool(false, title="Display Reversals based on SMA", group="RSI")

// Z-Score Inputs 
showz = input.bool(true, title="Show Z-Score", group="Z-Score")
zsource = input.source(close, title="Z-Score Source", group="Z-Score")
zlength = input.int(14, title="Z-Score Length", group="Z-Score") 
zsmalength = input.int(3, title="Z-Score SMA Length", group="Z-Score") 
zreversal = input.bool(false, title="Display reversals based on SMA", group="Z-Score")

//MFI Inputs 
showmfi = input.bool(true, title="Show MFI", group="MFI")
mfisource = input.source(close, title="MFI Source", group="MFI")
mfilength = input.int(14, title="MFI Length", group="MFI") 
mfismalength = input.int(14, title="MFI SMA Length", group="MFI")
mfireversal = input.bool(false, title="Display reversals based on SMA")
lookback = input.int(14, title="Lookback Period", tooltip="Technical lookback period, applies to all technical indicators.")

// Price Prediction Inputs 
len = input(defval = 15, title = 'Price Prediction Lookback', group="Price Prediction", tooltip="This determines the amount of time the indicator will analyze to predict prospective price targets. This will also apply to the Highest High and Lowest Low values.")
smalen = input.int(15, title="High and Low SMA Length", group="Price Prediction", tooltip="The lookback length for the High and Low SMA")

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            Stochastics                                                                              ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Stochastics 
sto = ta.stoch(close, high, low, stolength)
stosma = ta.sma(sto, stosmad)

stohighest = ta.highest(sto, lookback) 
stolowest = ta.lowest(sto, lookback) 

stosmahighest = ta.highest(stosma, lookback) 
stosmalowest = ta.lowest(stosma, lookback) 

bool stobearishreversal = sto >= stohighest 
bool stobullishreversal = sto <= stolowest 
bool stobearishreversalsma = stosma >= stosmahighest 
bool stobullishreversalsma = stosma <= stosmalowest 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            RSI                                                                                      ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

rsi = ta.rsi(rsisource, rsilength)
rsisma = ta.sma(rsi, rsismalength)
rsihighest = ta.highest(rsi, lookback) 
rsilowest = ta.lowest(rsi, lookback) 
rsismahighest = ta.highest(rsisma, lookback)
rsismalowest = ta.lowest(rsisma, lookback)

bool rsibearishreversal = rsi >= rsihighest
bool rsibullishreversal = rsi <= rsilowest 
bool rsibearishreversalsma = rsisma >= rsismahighest 
bool rsibullishreversalsma = rsisma <= rsismalowest 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            Z-Score                                                                                   ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
zavg = ta.sma(zsource, zlength) 
zsd = ta.stdev(zsource, zlength) 

z = (zsource - zavg) / zsd 

zsma = ta.sma(z, zsmalength)

zhighest = ta.highest(z, lookback) 
zlowest = ta.lowest(z, lookback) 

zsmahighest = ta.highest(zsma, lookback) 
zsmalowest = ta.lowest(zsma, lookback) 

bool zbearishreversal = z >= zhighest 
bool zbullishreversal = z <= zlowest 
bool zbearishreversalsma = zsma >= zsmahighest 
bool zbullishreversalsma = zsma <= zsmalowest 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            MFI                                                                                      ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

mfi = ta.mfi(mfisource, mfilength)
mfisma = ta.sma(mfi, mfismalength)

mfihighest = ta.highest(mfi, lookback) 
mfilowest = ta.lowest(mfi, lookback) 
mfismahighest = ta.highest(mfisma, lookback)
mfismalowest = ta.lowest(mfisma, lookback) 

bool mfibearishreversal = mfi >= mfihighest 
bool mfibullishreversal = mfi <= mfilowest 
bool mfibearishreversalsma = mfisma >= mfismahighest 
bool mfibullishreversalsma = mfisma <= mfismalowest 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            Price Prediction                                                                         ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
linregs(y, x, len) =>
    ybar = math.sum(y, len)/len
    xbar = math.sum(x, len)/len
    b = math.sum((x - xbar)*(y - ybar),len)/math.sum((x - xbar)*(x - xbar),len)
    a = ybar - b*xbar
    [a, b]
   

// Historical stock price data
h = high 
o = open 
l = low

// Calculate linear regression for stock price based on open price
[a, b] = linregs(h, o, len)
[c, d] = linregs(l, o, len) 

predicted_high = a + b*o
predicted_low = c + d * o 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            Highs and Lows                                                                           ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
maxhi = ta.highest(high, len) 
minhi = ta.lowest(high, len) 
maxlo = ta.highest(low, len) 
minlo = ta.lowest(low, len) 

// Hi and Lo SMA 

hisma = ta.sma(high, smalen) 
losma = ta.sma(low, smalen) 

// Predicted High / low result 

bool highachieved = high >= predicted_high 
bool lowachieved = low <= predicted_low 

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

phplots = input.bool(false, title="Plot Predicted Highs", group="Price Prediction")
plplots = input.bool(false, title="Plot Predicted Lows", group="Price Prediction")
hismaplots = input.bool(false, title="SMA of High", group="Price Prediction")
losmaplots = input.bool(false, title="SMA of Low", group="Price Prediction")

var loplots = 0.0 
var hiplots = 0.0 
var hismaplot = 0.0 
var losmaplot = 0.0 

if phplots 
    hiplots := predicted_high

if plplots
    loplots := predicted_low 

if hismaplots 
    hismaplot := hisma 

if losmaplots 
    losmaplot := losma 

plot(hismaplot, "High SMA Plot", color=color.green)
plot(losmaplot, "Low SMA Plots", color=color.red)
plot(loplots, "Predicted Low", color=color.red)  
plot(hiplots, "Predicted High", color=color.green) 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            Colours                                                                                  ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

color black = color.new(color.black, 75)
color blue = color.new(color.blue, 75) 
color aqua = color.new(color.aqua, 65) 
color white = color.new(color.white, 0) 
color green = color.new(color.green, 0) 
color red = color.new(color.red, 0)

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                    Strings for Assessment Results                                                                    ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

string bull = "In Lowest Range"
string bear = "In Max Range"
string nothing = "In Neutral Range"

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            Data Tables                                                                              ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

tablePosInput = input.string(title="Position", defval="Top Right", options=["Bottom Left", "Bottom Right", "Top Left", "Top Right"], tooltip="Select where you want the table to draw.")
reversaltable = input.bool(true, title="Show Reversal Table")
var tablePos  = tablePosInput == "Bottom Left" ? position.bottom_left : tablePosInput == "Bottom Right" ? position.bottom_right : tablePosInput == "Top Left" ? position.top_left : tablePosInput == "Top Right" ? position.top_right : na
var techtable = table.new(tablePos, columns = 9, rows = 8, border_color = color.black, border_width = 2)

// Columns 
table.cell(techtable, 1, 1, text = "Tech Dashboard", bgcolor = black, text_color = white)
table.cell(techtable, 2, 1, text = "Highest", bgcolor = black, text_color = white)
table.cell(techtable, 3, 1, text = "Lowest", bgcolor = black, text_color = white)
table.cell(techtable, 4, 1, text = "Current SMA", bgcolor = black, text_color = white)
table.cell(techtable, 5, 1, text = "Current Value", bgcolor = black, text_color = white)
// Rows
table.cell(techtable, 1, 6, text = "Highs", bgcolor = blue, text_color = white)
table.cell(techtable, 1, 7, text = "Lows", bgcolor = blue, text_color = white)
// RSI 
if showrsi 
    table.cell(techtable, 1, 2, text = "RSI", bgcolor = blue, text_color = white)
    table.cell(techtable, 2, 2, text = rsireversal ? str.tostring(math.round(rsismahighest, 2)) : str.tostring(math.round(rsihighest, 2)), bgcolor = aqua, text_color = white)
    table.cell(techtable, 3, 2, text = storeversal ? str.tostring(math.round(rsismalowest, 2)) : str.tostring(math.round(rsilowest, 2)), bgcolor = aqua, text_color=white)
    table.cell(techtable, 4, 2, text = str.tostring(math.round(rsisma, 2)), bgcolor=aqua, text_color=white)
    table.cell(techtable, 5, 2, text = str.tostring(math.round(rsi, 2)), bgcolor = aqua, text_color = white)
// Stochastics
if showsto
    table.cell(techtable, 1, 3, text = "Stochastics", bgcolor = blue, text_color = white)
    table.cell(techtable, 2, 3, text = storeversal ? str.tostring(math.round(stosmahighest, 2)) : str.tostring(math.round(stohighest, 2)), bgcolor = aqua, text_color = white)
    table.cell(techtable, 3, 3, text = storeversal ? str.tostring(math.round(stosmalowest, 2)) : str.tostring(math.round(stolowest, 2)), bgcolor = aqua, text_color=white)
    table.cell(techtable, 4, 3, text = str.tostring(math.round(stosma, 2)), bgcolor=aqua, text_color=white)
    table.cell(techtable, 5, 3, text = str.tostring(math.round(sto, 2)), bgcolor = aqua, text_color = white)
// Z-Score
if showz
    table.cell(techtable, 1, 4, text = "Z-Score", bgcolor = blue, text_color = white)
    table.cell(techtable, 2, 4, text = zreversal ? str.tostring(math.round(zsmahighest, 2)) : str.tostring(math.round(zhighest, 2)), bgcolor = aqua, text_color = white)
    table.cell(techtable, 3, 4, text = zreversal ? str.tostring(math.round(zsmalowest, 2)) : str.tostring(math.round(zlowest, 2)), bgcolor = aqua, text_color=white)
    table.cell(techtable, 4, 4, text = str.tostring(math.round(zsma, 2)), bgcolor=aqua, text_color=white)
    table.cell(techtable, 5, 4, text = str.tostring(math.round(z, 2)), bgcolor = aqua, text_color = white)
// MFI
if showmfi
    table.cell(techtable, 1, 5, text = "MFI", bgcolor = blue, text_color = white)
    table.cell(techtable, 2, 5, text = mfireversal ? str.tostring(math.round(mfismahighest, 2)) : str.tostring(math.round(mfihighest, 2)), bgcolor = aqua, text_color = white)
    table.cell(techtable, 3, 5, text = mfireversal ? str.tostring(math.round(mfismalowest, 2)) : str.tostring(math.round(mfilowest, 2)), bgcolor = aqua, text_color=white)
    table.cell(techtable, 4, 5, text = str.tostring(math.round(mfisma, 2)), bgcolor=aqua, text_color=white)
    table.cell(techtable, 5, 5, text = str.tostring(math.round(mfi, 2)), bgcolor = aqua, text_color = white)
// Highs 
table.cell(techtable, 2, 6, text = str.tostring(math.round(maxhi, 2)), bgcolor = aqua, text_color=white) 
table.cell(techtable, 3, 6, text = str.tostring(math.round(minhi, 2)), bgcolor = aqua, text_color=white) 
table.cell(techtable, 4, 6, text = str.tostring(math.round(hisma, 2)), bgcolor = aqua, text_color=white) 
table.cell(techtable, 5, 6, text = str.tostring(math.round(predicted_high, 2)), bgcolor = aqua, text_color=white) 
// Lows
table.cell(techtable, 2, 7, text = str.tostring(math.round(maxlo, 2)), bgcolor = aqua, text_color=white) 
table.cell(techtable, 3, 7, text = str.tostring(math.round(minlo, 2)), bgcolor = aqua, text_color=white) 
table.cell(techtable, 4, 7, text = str.tostring(math.round(losma, 2)), bgcolor = aqua, text_color=white) 
table.cell(techtable, 5, 7, text = str.tostring(math.round(predicted_low, 2)), bgcolor = aqua, text_color=white) 

//Range Table 
if reversaltable 
    table.cell(techtable, 6,1, text = "Current Range", bgcolor = black, text_color = white)
    if showrsi 
        table.cell(techtable, 6, 2, text = rsireversal and rsibearishreversalsma ? str.tostring(bear) : rsireversal and rsibullishreversalsma ? str.tostring(bull) : rsibearishreversal ? str.tostring(bear) : rsibullishreversal ? str.tostring(bull) : str.tostring(nothing), bgcolor = rsireversal and rsibearishreversalsma ? red : rsireversal and rsibullishreversalsma ? green : rsibearishreversal ? red : rsibullishreversal ? green : black, text_color = white)
    if showsto
        table.cell(techtable, 6, 3, text = storeversal and stobearishreversalsma ? str.tostring(bear) : storeversal and stobullishreversalsma ? str.tostring(bull) : stobearishreversal ? str.tostring(bear) : stobullishreversal ? str.tostring(bull) : str.tostring(nothing), bgcolor = storeversal and stobearishreversalsma ? red : storeversal and stobullishreversalsma ? green : stobearishreversal ? red : stobullishreversal ? green : black, text_color = white)
    if showz
        table.cell(techtable, 6, 4, text = zreversal and zbearishreversalsma ? str.tostring(bear) : zreversal and zbullishreversalsma ? str.tostring(bull) : zbearishreversal ? str.tostring(bear) : zbullishreversal ? str.tostring(bull) : str.tostring(nothing), bgcolor =  zreversal and zbearishreversalsma ? red : zreversal and zbullishreversalsma ? green : zbearishreversal ? red : zbullishreversal ? green : black, text_color = white)
    if showmfi
        table.cell(techtable, 6, 5, text = mfireversal and mfibearishreversalsma ? str.tostring(bear) : mfireversal and mfibullishreversalsma ? str.tostring(bull) : mfibearishreversal ? str.tostring(bear) : mfibullishreversal ? str.tostring(bull) : str.tostring(nothing), bgcolor = mfireversal and mfibearishreversalsma ? red : mfireversal and mfibullishreversalsma ? green : mfibearishreversal ? red : mfibullishreversal ? green : black, text_color = white)
    table.cell(techtable, 6, 6, text = highachieved ? "Predicted High Obtained" : "Predicted High Unrealized", bgcolor = highachieved ? green : black, text_color=white) 
    table.cell(techtable, 6, 7, text = lowachieved ? "Predicted Low Obtained" : "Predicted Low Unrealized", bgcolor = lowachieved ? green : black, text_color=white) 

