Ticker Correlation Reference Indicator
// 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("Ticker Correlation Reference Indicator")

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                             Tooltips                                                                                ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

tip1 = "This is the lookback period of the correlation assessment. It is defaulted to 14. The longer the lookback period, the more rigorous the results will be at determining the consistency of a significant relationship"
tip2 = "This will show you the average correlation over a defined period of time"
tip3 = "This will plot the correlation result you wish to see plotted. It is defaulted to the correlation of the Close price. However, if you wish for it to plot the correlation of High, Low or Open you can select as such. Additionally, you may choose to select the smoothing option which will plot the SMA instead of the raw correlation score."
tip4 = "Smoothed Correlation will plot the SMA of your desired correlation result (defaulted to the Close price). Unsmoothed will plot the raw correlation score of the desired correlation result. You can modify which correlation is plotted with the Plot Correlation Type function."
tip5 = "This function will permit you to convert price from Ticker 1 to Ticker 2. You can also plot in your desired price to see what that would equal on Ticker 2."
tip6 = "This allows the user to select which price they wish to convert. You can convert High to High, Low to Low, Close to Close, etc. If you want to know what a close, low, high or open price on Ticker 1 would translate to on Ticker 2, you can use this function."
tip7 = "This allows the user to convert a manual price from Ticker 1 to Ticker 2"
tip8 = "Input the Price you wish to convert to Ticker2. If you do not select this, it will default to convert the current close price of Ticker 1."
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            User Inputs                                                                              ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tickerinput = input.symbol("", title="Ticker 1", group="Ticker") 
tickerinput2 = input.symbol("BATS:SPY", title="Ticker 2", group="Ticker")
len = input.int(14, title="Correlation Lookback Period", group="Correlation Assessments", tooltip = tip1) 
smalen = input.int(14, title="SMA Length", tooltip= tip2,  group = "Correlation Assessments")
smatype = input.string("Close", "Plot Correlation Type", options=["Close", "Open", "High", "Low"], tooltip = tip3, group="Correlation Assessments")
smooth = input.bool(true, title="Show Smoothed Correlation", group="Correlation Assessments", tooltip = tip4)
conversion = input.bool(false, title="Permit Manual Conversion", group="Conversion", tooltip=tip5)

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                            Request Security Functions                                                               ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

tickerc = request.security(tickerinput, "", close)
tickero = request.security(tickerinput, "", open)
tickerh = request.security(tickerinput, "", high)
tickerl = request.security(tickerinput, "", low)

current_tickerc = request.security(tickerinput2, "", close)
current_tickero = request.security(tickerinput2, "", open)
current_tickerh = request.security(tickerinput2, "", high)
current_tickerl = request.security(tickerinput2, "", low)

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

bull         =color.new(color.green, 0)
bear         = color.new(color.red, 0)  
blue        = color.rgb(20, 123, 134, 25)
white       = color.new(color.white, 0)
aqua        = color.new(color.aqua, 85) 
orange      = color.new(color.orange, 0) 
purple      = color.new(color.rgb(128, 0, 128, 50), 15) 
black       = color.new(color.black, 15) 
pink        = color.new(color.rgb(250, 128, 114, 50), 15)

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                           Correlation Assessments                                                                    ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
corc = ta.correlation(tickerc, current_tickerc, len) 
corcsma = ta.sma(corc, smalen)
coro = ta.correlation(tickero, current_tickero, len) 
corosma = ta.sma(coro, smalen) 
corh = ta.correlation(tickerh, current_tickerh, len) 
corhsma = ta.sma(corh, smalen) 
corl = ta.correlation(tickerl, current_tickerl, len) 
corlsma = ta.sma(corl, smalen) 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                           Correlation Plots                                                                         ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

float corsmaplot = 0.0 

if smooth and smatype == "Close"
    corsmaplot := corcsma 

if smatype == "Close" 
    corsmaplot := corc 

if smooth and smatype == "Open" 
    corsmaplot := corosma 

if smatype == "Open" 
    corsmaplot := coro 

if smooth and smatype == "High" 
    corsmaplot := corhsma 

if smatype =="High"
    corsmaplot := corh

if smooth and smatype == "Low" 
    corsmaplot := corlsma

if smatype == "Low"
    corsmaplot := corl


plot(corsmaplot, "Close Correlation", color=pink, linewidth=3)


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                       Z-Score Conversion of Ticker for Standardization                                                              ///
///This standardizes both tickers into Z-Score Format which provides direct, side-by-side comparison on the same scale and plots results as a line plot.///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

opavg = ta.sma(tickero, len) 
opsd = ta.stdev(tickero, len) 
clavg = ta.sma(tickerc, len) 
clsd = ta.stdev(tickerc, len) 
hiavg = ta.sma(tickerh, len) 
hisd = ta.stdev(tickerh, len)
loavg = ta.sma(tickerl, len) 
losd = ta.stdev(tickerl, len) 

opz = (tickero - opavg) / opsd 
clz = (tickerc - clavg) / clsd 
hiz = (tickerh - hiavg) / hisd 
loz = (tickerl - loavg) / losd 



co = ta.sma(current_tickero, len) 
cosd = ta.stdev(current_tickero, len)
ccl = ta.sma(current_tickerc, len) 
cclsd = ta.stdev(current_tickerc, len) 
chi = ta.sma(current_tickerh, len) 
chisd = ta.stdev(current_tickerh, len)
clo = ta.sma(current_tickerl, len) 
closd = ta.stdev(current_tickerl, len)

coz = (current_tickero - co) / cosd 
cclz = (current_tickerc - ccl) / cclsd 
chiz = (current_tickerh - chi) / chisd 
cloz = (current_tickerl - clo) / closd 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                     Correlation Assessments for Colour                                                              ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


bool sameopen = coro >= 0.9 and coro <= 1.0 or coro <= -0.9 and coro >= -1.0
bool sameclose = corc >= 0.9 and corc <= 1.0 or coro <= -0.9 and coro >= -1.0 
bool samehigh = corh >= 0.9 and corh <= 1.0 or corh <= -0.9 and corh >= -1.0 
bool samelow = corl >= 0.9 and corl <= 1.0 or corl <= -0.9 and corl >= -1.0 

bool differentopen = coro <= 0.4 and coro >= 0 or coro >= -0.4 and coro <= 0 
bool differentclose = corc <= 0.4 and corc >= 0 or corc >= -0.4 and corc <= 0 
bool differenthigh = corh <= 0.4 and corh >= 0 or corh >= -0.4 and corh <= 0 
bool differentlow = corl <= 0.4 and corl >= 0 or corl >= -0.4 and corl <= 0 

color sameop = sameopen ? color.green : differentopen ? color.red : color.white 
color samecl = sameclose ? color.green :differentclose ? color.red : color.white
color samehi = samehigh ? color.green : differenthigh ? color.red : color.white 
color samelo = samelow ? color.green : differentlow ? color.red : color.white 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                     Line plot of Ticker Z-Score                                                                     ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

plot(opz, "Ticker 1 Open", linewidth=2)
plot(clz, "Ticker 1 Close", linewidth=2)
plot(hiz, "Ticker 1 High", linewidth=2)
plot(loz, "Ticker 1 Low", linewidth=2) 


plot(coz, "Ticker 2 Open", color=sameop, linewidth=2)
plot(cclz, "Ticker 2 Close", color=samecl, linewidth=2) 
plot(chiz, "Ticker 2 High", color=samehi, linewidth=2) 
plot(cloz, "Ticker 2 Low", color=samelo, linewidth=2) 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                     Manual Ticker Conversion                                                                        ///
///This code permits the user to manually calculcate the predicted close price of Ticker 2 using a regresion analysis between Ticker 1 and Ticker 2.    ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// User defined inputs 
contype = input.string("Close", "Conversion Price", options=["Close", "Open", "High", "Low"], tooltip = tip6, group="Conversion")
mancon = input.bool(false, title="Allow Manual Price Input", tooltip = tip7, group="Conversion")
manconfloat = input.float(100, title="Manual Conversion Price Input", tooltip = tip8, group="Conversion")

float convticker1 = 0.0 
float convticker2 = 0.0 

if contype == "Close" 
    convticker1 := tickerc 
    convticker2 := current_tickerc 

if contype == "Open" 
    convticker1 := tickero
    convticker2 := current_tickero 

if contype == "High" 
    convticker1 := tickerh
    convticker2 := current_tickerh 

if contype == "Low" 
    convticker1 := tickerl 
    convticker2 := current_tickerl 

//y Variable
a = convticker2[1]
b = convticker2[2]
c = convticker2[3]
d = convticker2[4]
e = convticker2[5]
f = convticker2[6]
g = convticker2[7] 
h = convticker2[8]
i = convticker2[9]
j = convticker2[10] 

a2 = math.pow(a, 2)
b2 = math.pow(b, 2) 
c2 = math.pow(c, 2) 
d2 = math.pow(d, 2) 
e2 = math.pow(e, 2) 
f2 = math.pow(f, 2) 
g2 = math.pow(g, 2) 
h2 = math.pow(h, 2) 
i2 = math.pow(i, 2) 
j2 = math.pow(j, 2) 

y = (a + b + c + d + e + f + g + h + i + j) 
y2 = (a2 + b2 + c2 + d2 + e2 + f2 + g2 + h2 + i2 + j2) 

// X Variable

aa = convticker1[1]
bb = convticker1[2]
cc = convticker1[3]
dd = convticker1[4]
ee = convticker1[5]
ff = convticker1[6]
gg = convticker1[7] 
hh = convticker1[8]
ii = convticker1[9]
jj = convticker1[10] 


aa2 = math.pow(aa, 2)
bb2 = math.pow(bb, 2) 
cc2 = math.pow(cc, 2) 
dd2 = math.pow(dd, 2) 
ee2 = math.pow(ee, 2) 
ff2 = math.pow(ff, 2) 
gg2 = math.pow(gg, 2) 
hh2 = math.pow(hh, 2) 
ii2 = math.pow(ii, 2) 
jj2 = math.pow(jj, 2) 

x = (aa + bb + cc + dd + ee + ff + gg + hh + ii + jj) 
x2 = (aa2 + bb2 + cc2 + dd2 + ee2 + ff2 + gg2 + hh2 + ii2 + jj2) 

//xy 

xy = (a * aa) + (b * bb) + (c * cc) + (d * dd) + (e * ee) + (f * ff) + (g * gg) + (h * hh) + (i * ii) + (j * jj)

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

slope = (b1 / bbb2)


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


float manualconversionresult = 0.0 

if conversion 
    manualconversionresult := (convticker1 * slope) + abc1 

if conversion and mancon 
    manualconversionresult := (manconfloat * slope) + abc1 

// Manual Standard Error 
se10 = manualconversionresult[10] - convticker2[10]
se9 = manualconversionresult[9] - convticker2[9]
se8 = manualconversionresult[8] - convticker2[8]
se7 = manualconversionresult[7] - convticker2[7]
se6 = manualconversionresult[6] - convticker2[6]
se5 = manualconversionresult[5] - convticker2[5]
se4 = manualconversionresult[4] - convticker2[4]
se3 = manualconversionresult[3] - convticker2[3]
se2 = manualconversionresult[2] - convticker2[2]
se1 = manualconversionresult[1] - convticker2[1]

se10rt = math.pow(se10, 2)
se9rt = math.pow(se9, 2) 
se8rt = math.pow(se8, 2) 
se7rt = math.pow(se7, 2) 
se6rt = math.pow(se6, 2) 
se5rt = math.pow(se5, 2) 
se4rt = math.pow(se4, 2) 
se3rt = math.pow(se3, 2) 
se2rt = math.pow(se2, 2) 
se1rt = math.pow(se1, 2) 

rtadd = (se10rt + se9rt + se7rt + se6rt + se5rt + se4rt + se3rt + se2rt + se1rt) 

r1 = rtadd / (10 - 2) 
r2 = math.sqrt(r1) 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                              Assessment of Relationship                                                             ///
///This code determines the significance of the relationship over time and whether or not a statistically significant relationship exists.              ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

corclowest = ta.lowest(corc, 100)
corchighest = ta.highest(corc, 100) 
variance = corchighest - corclowest 

bool sigpos = corc >= 0.5 and corcsma >= 0.5 and corclowest >= 0.5 
bool signeg = corc <= - 0.5 and corcsma <= -0.5 and corchighest <= -0.5 
bool unstablepos = corc >= 0.5 and corcsma >= 0.5 and variance >= 1 
bool unstableneg = corc <= -0.5 and corcsma <= -0.5 and variance >= 1 
bool unstablepos2 = corc < 0.5 and corcsma >= 0.5 and variance >= 1 
bool unstableneg2 = corc > -0.5 and corcsma <= -0.5 and variance >= 1 
bool punstablepos = corc >= 0.5 and corcsma >= 0.5 and variance < 1
bool punstableneg = corc <= -0.5 and corcsma <= -0.5 and variance < 1 

string sigposS = "Significant Positive Correlation that is stable over time with a variance of: " + str.tostring(math.round(variance,2))
string signegS = "Significant Negative Correlation that is stable over time with a variance of: " + str.tostring(math.round(variance,2))
string unstableposS = "Unstable Positive Correlation marked by frequent deviations over time and correlations as low as: " + str.tostring(math.round(corclowest, 2)) + " and as high as: " + str.tostring(math.round(corchighest, 2)) + ". A variance of: " + str.tostring(math.round(variance,2))
string unstablenegS = "Unstable Negative Correlation marked by frequent deviations over time and correlations as low as: " + str.tostring(math.round(corclowest, 2)) + " and as high as: " + str.tostring(math.round(corchighest, 2)) + ". A variance of: " + str.tostring(math.round(variance,2))
string punstableposS = "Significant Postitive Correlation marked by occational deviations over time where correlation drops as low as: " + str.tostring(math.round(corclowest, 2)) + " and as high as: " + str.tostring(math.round(corchighest, 2)) + ". A variance of: " + str.tostring(math.round(variance,2))
string punstablenegS = "Significiant Negative Correlation marked by occational deviations over time where correlation drops as low as: " + str.tostring(math.round(corclowest, 2)) + " and as high as: " + str.tostring(math.round(corchighest, 2)) + ". A variance of: " + str.tostring(math.round(variance,2))
string norelationshipS = "No Statistically Singificant Relationship Observed"

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


showTable     = input.bool(true, "Show Table")
showSigTable    = input.bool(true, "Show Significance Table", tooltip = "This provides narrative interpreation results of significance")
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.")
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 dataTable = table.new(tablePos, columns = 4, rows = 10, border_color = color.black, border_width = 2)
if showTable
// Labels
    table.cell(dataTable, 1, 1, text = "Ticker:", bgcolor = black, text_color = color.white)
    table.cell(dataTable, 2, 1, text = "Correlation", bgcolor = black, text_color = color.white)
    table.cell(dataTable, 3, 1, text = "SMA", bgcolor = black, text_color = color.white)
    table.cell(dataTable, 1, 2, text = "Open Correlation", bgcolor = purple, text_color = color.white)
    table.cell(dataTable, 2, 2, text = str.tostring(math.round(coro,2)), bgcolor = coro >= 0.5 ? bull : coro <= -0.5 ? bull : bear, text_color = white)
    table.cell(dataTable, 3, 2, text = str.tostring(math.round(corosma,2)), bgcolor = corosma >= 0.5 ? bull : corosma <= -0.5 ? bull : bear, text_color = white)
    table.cell(dataTable, 1, 3, text = "High Correlation", bgcolor = purple, text_color = color.white)
    table.cell(dataTable, 2, 3, text = str.tostring(math.round(corh,2)), bgcolor = corh >= 0.5 ? bull : corh <= -0.5 ? bull : bear, text_color = white)
    table.cell(dataTable, 3, 3, text = str.tostring(math.round(corhsma,2)), bgcolor = corhsma >= 0.5 ? bull : corhsma <= -0.5 ? bull : bear, text_color = white)
    table.cell(dataTable, 1, 4, text = "Low Correlation", bgcolor = purple, text_color = color.white)
    table.cell(dataTable, 2, 4, text = str.tostring(math.round(corl,2)), bgcolor = corl >= 0.5 ? bull : corl <= -0.5 ? bull : bear, text_color = white)
    table.cell(dataTable, 3, 4, text = str.tostring(math.round(corlsma,2)), bgcolor = corlsma >= 0.5 ? bull : corlsma <= -0.5 ? bull : bear, text_color = white)
    table.cell(dataTable, 1, 5, text = "Close Correlation", bgcolor = purple, text_color = color.white)
    table.cell(dataTable, 2, 5, text = str.tostring(math.round(corc,2)), bgcolor = corc >= 0.5 ? bull : corc <= -0.5 ? bull : bear, text_color = white)
    table.cell(dataTable, 3, 5, text = str.tostring(math.round(corcsma,2)), bgcolor = corcsma >= 0.5 ? bull : corcsma <= -0.5 ? bull : bear, text_color = white)
if showTable and  conversion 
    table.cell(dataTable, 1, 6, text = "Conversion Result", bgcolor = black, text_color = white)
    table.cell(dataTable, 2, 6, text = str.tostring(math.round(manualconversionresult, 2)), bgcolor = aqua, text_color = white)
    table.cell(dataTable, 1, 7, text = "Standard Error", bgcolor = black, text_color = white)
    table.cell(dataTable, 2, 7, text = str.tostring(math.round(r2, 2)), bgcolor = aqua, text_color = white)

var sigtable = table.new(position.bottom_center, columns = 4, rows = 10, border_color = color.black, border_width = 2)
str.tostring(unstableposS)

color sigtablecolor = sigpos ? bull : signeg ? bull : unstablepos ? bear : unstableneg ? bear : unstablepos2 ? bear : unstableneg2 ? bear : punstablepos ? orange : punstableneg ? orange : bear 

if showSigTable
    table.cell(sigtable, 1, 1, text = sigpos ? str.tostring(sigposS) : signeg ? str.tostring(signegS) : unstablepos ? str.tostring(unstableposS) : unstableneg ? str.tostring(unstablenegS) : unstablepos2 ? str.tostring(unstableposS) : unstableneg2 ? str.tostring(unstablenegS) : punstablepos ? str.tostring(punstableposS) : punstableneg ? str.tostring(punstablenegS) : str.tostring(norelationshipS), bgcolor = black, text_color = sigtablecolor)
