 TIG's Market Internals Clouds Indicator v2.0
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © That Indicator Guy (TIG)
// @version = 5


// Blank title so we can overwrite with whatever we're using
indicator(title=" ", overlay=false)


/////////////////////////////////////////////////
// SET UP
/////////////////////////////////////////////////


// User inputs


var oGroup0 = "WELCOME TO TIG'S MARKET INTERNALS CLOUD INDICATOR!"

oInternal       = input.string("VIX", "Use Built-In Market Internal?     ", options = ["ADD", "TICK", "TRIN", "VIX", "VOLD"], group = oGroup0)
oCustomInternal = input.string("", "(or Custom Market Internal?)", group = oGroup0, tooltip = "leave blank to use built-in internal")


var oGroup1 = "FAST CLOUD            EMA                   LINE WIDTH"

oFastCloudShort_Length   = input.int(3, "Super Fast Line ", minval = 1, inline = "11", group = oGroup1)
oFastCloudShortThickness = input.int(1, " ",  options = [1, 2, 3, 4, 5], inline = "11", group = oGroup1)

oFastCloudLong_Length    = input.int(30, "Fast Line       ", minval = 1, inline = "12", group = oGroup1)
oFastCloudLongThickness  = input.int(3, " ", options = [1, 2, 3, 4, 5], inline = "12", group = oGroup1)


var oGroup2 = "FAST CLOUD         SHOW         UPTRENDING   DOWNTRENDING"


oShowFastCloudLines  = input.string("Yes please!", "Lines           ", options = ["Yes please!", "No thanks!", "Dots for the win!"], inline = "21", group = oGroup2)
oFastLineColorGreen  = input.color(color.rgb(64,255,64,0),    " ", inline = "21", group = oGroup2)
oFastLineColorRed    = input.color(color.rgb(255, 64, 64, 0), " ", inline = "21", group = oGroup2)

oShowFastCloud       = input.string("Yes please!", "Cloud           ", options = ["Yes please!", "No thanks!"], inline = "22", group = oGroup2)
oFastCloudColorGreen = input.color(color.rgb(0, 255, 0, 70), " ", inline = "22", group = oGroup2)
oFastCloudColorRed   = input.color(color.rgb(255, 0, 0, 60), " ", inline = "22", group = oGroup2)


var oGroup3 = "SLOW CLOUD            EMA                   LINE WIDTH"

oSlowCloudShort_Length   = input.int(150, "Slow Line       ", minval = 1, inline = "31", group = oGroup3)
oSlowCloudShortThickness = input.int(1, " ",  options = [1, 2, 3, 4, 5], inline = "31", group = oGroup3)

oSlowCloudLong_Length    = input.int(600, "Super Slow Line ", minval = 1, inline = "32", group = oGroup3)
oSlowCloudLongThickness  = input.int(1, " ", options = [1, 2, 3, 4, 5], inline = "32", group = oGroup3)


var oGroup4 = "SLOW CLOUD         SHOW         UPTRENDING   DOWNTRENDING"

oShowSlowCloudLines  = input.string("No thanks!", "Lines           ", options = ["Yes please!", "No thanks!", "Dots for the win!"], inline = "41", group = oGroup4)
oSlowLineColorGreen  = input.color(color.rgb(64, 255, 64, 50), " ", inline = "41", group = oGroup4)
oSlowLineColorRed    = input.color(color.rgb(255, 64, 64, 50), " ", inline = "41", group = oGroup4)

oShowSlowCloud       = input.string("Yes please!", "Cloud            ", options = ["Yes please!", "No thanks!"], inline = "42", group = oGroup4)
oSlowCloudColorGreen = input.color(color.rgb(0, 255, 0, 80), " ", inline = "42", group = oGroup4)
oSlowCloudColorRed   = input.color(color.rgb(255, 0, 0, 70), " ", inline = "42", group = oGroup4)


var oGroup5 = "OTHER RANDOM STUFF"

oTextColor = input.color(color.rgb(128, 128, 128, 0), "                                Text Color", inline = "51", group = oGroup5)

oShowLevelLines = input.bool(true, "Show Level Lines?", inline = "52", group = oGroup5)
oLevelLinesColor = input.color(color.rgb(128, 128, 128, 0), "If so, Level Lines Color", inline = "52", group = oGroup5)

oTickLine1 = input.int(-350, "TICK Lines    ", inline = "53", group = oGroup5)
oTickLine2 = input.int(   0, "", inline = "53", group = oGroup5)
oTickLine3 = input.int( 350, "", inline = "53", group = oGroup5)

oTrinLine1 = input.float(0.6, "TRIN Lines    ", inline = "54", group = oGroup5)
oTrinLine2 = input.float(1.8, "", inline = "54", group = oGroup5)

oCustomLine1 = input.float(0, "Custom Lines  ", inline = "55", group = oGroup5)
oCustomLine2 = input.float(0, "", inline = "55", group = oGroup5)
oCustomLine3 = input.float(0, "", inline = "55", group = oGroup5)


var oGroup6 = "THIS IS AN EXPERIMENTAL FEATURE - USE AT OWN RISK :)"

oShowCorrT = input.string("No thanks!", "Show Correlation between Internal and Price Action?", options = ["Let's give it a whirl", "No thanks!"], inline = "61", group = oGroup6)
oShowCorr = oShowCorrT == "No thanks!" ? false : true
oLookback = input.int(30, "Correlaton lookback length (bars)                 ", minval = 2, inline = "62", group = oGroup6)


// Other Intial Variables

oColorNone     = color.rgb(0, 0, 0, 255)

var oBarCount  = 0
var oFastSpx   = 0.0

var oSpxArray  = array.new_float(oLookback)
var oFastArray = array.new_float(oLookback)



/////////////////////////////////////////////////
// DO SOME CALCULATIONS
/////////////////////////////////////////////////


// Intialize for a new session


oCashSession = time(timeframe.period, "0930-1600", "America/New_York")
oNewSession = (oCashSession and not(oCashSession[1])) or (oCashSession and (dayofweek != dayofweek[1]))

oShow = (oCashSession and not(oNewSession))




if oNewSession
    oBarCount := 0

    array.clear(oSpxArray)
    array.clear(oFastArray)

oBarCount += 1



/////////////////////////////////////////////////
// MARKET DATA
/////////////////////////////////////////////////


// Main Internal

oReading = request.security(oInternal, timeframe.period, close)
oCustomReading = request.security(oCustomInternal, timeframe.period, close)

oReading := oCustomInternal != "" ? oCustomReading : oReading



oAdvancingIssues = request.security("ADVN.NY", timeframe.period, close)
oDecliningIssues = request.security("DECL.NY", timeframe.period, close)
oUpVolume = request.security("UPVOL.NY", timeframe.period, close)
oDownVolume = request.security("DNVOL.NY", timeframe.period, close)

if oInternal == "TRIN"
    oReading := (oAdvancingIssues / oDecliningIssues) / (oUpVolume / oDownVolume)

if oInternal == "VOLD"
    oReading := oReading / 1000000
    


/////////////////////////////////////////////////
// EMA LINES AND CLOUDS
/////////////////////////////////////////////////


// EMA calculations

var oFastCloudShort = 0.0
var oFastCloudLong = 0.0
var oSlowCloudShort = 0.0
var oSlowCloudLong = 0.0

oFastShortMulti = (2 / (math.min(oBarCount, oFastCloudShort_Length) + 1))
oFastLongMulti  = (2 / (math.min(oBarCount, oFastCloudLong_Length) + 1))
oSlowShortMulti = (1.6 / (math.min(oBarCount, oSlowCloudShort_Length) + 1))
oSlowLongMulti  = (1.2 / (math.min(oBarCount, oSlowCloudLong_Length) + 1))

oFastCloudShort := oBarCount == 1 ? oReading : oReading * oFastShortMulti + oFastCloudShort[1] * (1 - oFastShortMulti)
oFastCloudLong  := oBarCount == 1 ? oReading : oReading * oFastLongMulti  + oFastCloudLong[1]  * (1 - oFastLongMulti)
oSlowCloudShort := oBarCount == 1 ? oReading : oReading * oSlowShortMulti + oSlowCloudShort[1] * (1 - oSlowShortMulti)
oSlowCloudLong  := oBarCount == 1 ? oReading : oReading * oSlowLongMulti  + oSlowCloudLong[1]  * (1 - oSlowLongMulti)

oFastCloudShort_Color = oShowFastCloudLines == "No thanks!" or oBarCount == 1 ? oColorNone : oFastCloudShort > oFastCloudShort[1] ? oFastLineColorGreen : oFastLineColorRed
oFastCloudLong_Color  = oShowFastCloudLines == "No thanks!" or oBarCount == 1 ? oColorNone : oFastCloudLong  > oFastCloudLong[1]  ? oFastLineColorGreen : oFastLineColorRed
oSlowCloudShort_Color = oShowSlowCloudLines == "No thanks!" or oBarCount == 1 ? oColorNone : oSlowCloudShort > oSlowCloudShort[1] ? oSlowLineColorGreen : oSlowLineColorRed
oSlowCloudLong_Color  = oShowSlowCloudLines == "No thanks!" or oBarCount == 1 ? oColorNone : oSlowCloudLong  > oSlowCloudLong[1]  ? oSlowLineColorGreen : oSlowLineColorRed


// Plot the lines and the clouds

oFastCloudShort_Plot = plot(oFastCloudShort, linewidth = oFastCloudShortThickness, color = oFastCloudShort_Color, style = oShowFastCloudLines == "Dots for the win!" ? plot.style_circles : plot.style_line)
oFastCloudLong_Plot  = plot(oFastCloudLong,  linewidth = oFastCloudLongThickness,  color = oFastCloudLong_Color,  style = oShowFastCloudLines == "Dots for the win!" ? plot.style_circles : plot.style_line)

fill(oFastCloudShort_Plot, oFastCloudLong_Plot, color = oShowFastCloud == "No thanks!" or oBarCount == 1 ? oColorNone :  oFastCloudShort < oFastCloudLong ? oFastCloudColorRed : oFastCloudColorGreen)


oSlowCloudShort_Plot = plot(oSlowCloudShort, linewidth = oSlowCloudShortThickness, color = oSlowCloudShort_Color, style = oShowSlowCloudLines == "Dots for the win!" ? plot.style_circles : plot.style_line)
oSlowCloudLong_Plot  = plot(oSlowCloudLong,  linewidth = oSlowCloudLongThickness,  color = oSlowCloudLong_Color,  style = oShowSlowCloudLines == "Dots for the win!" ? plot.style_circles : plot.style_line)

fill(oSlowCloudShort_Plot, oSlowCloudLong_Plot, color = oShowSlowCloud == "No thanks!" or oBarCount == 1 ? oColorNone : oSlowCloudShort < oSlowCloudLong ? oSlowCloudColorRed : oSlowCloudColorGreen)


/////////////////////////////////////////////////
// OTHER DISPLAY STUFF
/////////////////////////////////////////////////


// Study Title

oStudyTitle = oCustomInternal !="" ? oCustomInternal : oInternal

var table oTable2 = table.new(position.top_left, 1, 1)
table.cell(oTable2, 0, 0, "    " + oStudyTitle +" Cloud", text_color = oTextColor, text_halign = text.align_left)


// Format the current value

oDisplayValue = ""

if oInternal == "ADD" or oInternal == "TICK" or oInternal == "VOLD"
    oDisplayValue := str.format("{0, number, #}", oReading)

if oInternal == "TRIN" or oInternal == "VIX"
    oDisplayValue := str.format("{0, number, #.##}", oReading)

if oInternal == "VOLD"
    oDisplayValue := oDisplayValue +"m"


// Display it in a box

var table oTable1 = table.new(position.bottom_right, 2, 1)
oAccuracy = oInternal == "TRIN" or oInternal == "VIX" ? 3 : 0
table.cell(oTable1, 0, 0, oDisplayValue, text_color = oTextColor)
oCellColor = oFastCloudShort_Color == oFastLineColorGreen ? oFastCloudColorGreen : oFastCloudColorRed
table.cell(oTable1, 1, 0, " ", bgcolor = oCellColor)


// Plot some reference lines

oLevel0 = 0.0
oLevel1 = 0.0
oLevel2 = 0.0


if oInternal == "VIX" and oCustomInternal == "" or not(oShowLevelLines)
    oLevel0 := oReading
    oLevel1 := oReading
    oLevel2 := oReading
    oLevelLinesColor := oColorNone

if oInternal == "TICK"
    oLevel0 := oTickLine1
    oLevel1 := oTickLine2
    oLevel2 := oTickLine3
    
if oInternal == "TRIN"
    oLevel0 := oTrinLine1
    oLevel1 := oTrinLine2
    oLevel2 := oTrinLine2
        
if oCustomInternal != "" and oShowLevelLines
    oLevel0 := oCustomLine1
    oLevel1 := oCustomLine2
    oLevel2 := oCustomLine3





plot(oLevel0, color = oLevelLinesColor)
plot(oLevel1, color = oLevelLinesColor)
plot(oLevel2, color = oLevelLinesColor)


/////////////////////////////////////////////////
// CORRELATION - THE GOOD STUFF
/////////////////////////////////////////////////


oSpx = close

oFastSpx  := oBarCount == 1 ? oSpx : oSpx * oFastLongMulti + oSpx[1]  * (1 - oFastLongMulti)

if oBarCount > oLookback
    array.shift(oSpxArray)
    array.shift(oFastArray)

array.push(oSpxArray, oFastSpx)
array.push(oFastArray, oFastCloudLong)

oCorrelation = array.covariance(oSpxArray, oFastArray) / (array.stdev(oSpxArray) * array.stdev(oFastArray))
oPearsons = oCorrelation * oCorrelation

var table oTable3 = table.new(position.top_right, 1, 2)
table.cell(oTable3, 0, 0, str.format("{0, number, #}", oLookback) + "-bar PC", text_color = oShowCorr ? oTextColor : oColorNone, text_halign = text.align_right)
table.cell(oTable3, 0, 1, str.format("{0, number, #.##}", oPearsons), text_color = oShowCorr ? oTextColor : oColorNone, text_halign = text.align_right)





