MTF Commodity Oddity Index (CCI+)
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © tvenn

//@version=5
indicator(title="MTF Commodity Oddity Index (CCI+)", shorttitle="CCI+", overlay = true, max_bars_back = 1000, max_lines_count = 400, max_labels_count = 400)

//=Constants
green = #95BD5F
red = #EA1889

// =MTF CCI
//==================================================================================================================================

grp_CCI = "General settings"
ccisrc = input(hlc3, title="CCI source", group=grp_CCI)
ccilen = input(20, title="CCI length", group=grp_CCI)
cci_val = ta.cci(ccisrc, ccilen) // CCI
cciRibbonPosition       = input.string('Bottom', title="CCI ribbon position", options=['Top', 'Bottom'], group=grp_CCI)

grp_MTFCCI1             = "MTF CCI #1"
enableOBOSCCI           = input(true, title="Enable MTF CCI OB/OS ribbon", group=grp_MTFCCI1)
useBgColorMTFCCIOBOS    = input(true, title="Color background where MTF #1 OB/OS", group=grp_MTFCCI1, tooltip="This will color the background to indicate the overbought / oversold state of the CCI on all 3x selected timeframes together at the same time.")
useBarColorMTFcciOBOS_1 = input(false, title="Color candles where MTF #1 OB/OS", group=grp_MTFCCI1, tooltip="This will color the candles to indicate the overbought / oversold state of the CCI on all 3x selected timeframes together at the same time.")
overboughtColor_1       = input(red, title="CCI overbought color", group=grp_MTFCCI1)
oversoldColor_1        = input(green, title="CCI oversold color", group=grp_MTFCCI1)


includeCurrentTFOBOSCCI = input(false, title="Include current timeframe OB/OS in ribbon", group="Current timeframe [Timeframe] [OS level] [OB level]", tooltip="this will include in the ribbon indications where the CCI is overbought or oversold on the current timeframe")
CCITF_1 = input.string("Chart", title="CTF", options=["Chart"], group="Current timeframe [Timeframe] [OS level] [OB level]", inline="tf1")
CCITF_OSTHRESH_1 = input(-150, title="", group="Current timeframe [Timeframe] [OS level] [OB level]", inline="tf1")
CCITF_OBTHRESH_1 = input(150, title="", group="Current timeframe [Timeframe] [OS level] [OB level]", inline="tf1")

//MTF CCI confluences
CCIMTF_1 = input.string("1", title="TF1", options=["Chart", "1", "2", "3", "4", "5", "8", "10", "15", "20", "30", "45", "60", "120", "240"], group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf1")
CCIMTF_2 = input.string("5", title="TF2", options=["Chart", "1", "2", "3", "4", "5", "8", "10", "15", "20", "30", "45", "60", "120", "240"], group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf2")
CCIMTF_3 = input.string("15", title="TF3", options=["Chart", "1", "2", "3", "4", "5", "8", "10", "15", "20", "30", "45", "60", "120", "240"], group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf3")

CCIMTF_OSTHRESH_1 = input(-150, title="", group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf1")
CCIMTF_OSTHRESH_2 = input(-150, title="", group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf2")
CCIMTF_OSTHRESH_3 = input(-150, title="", group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf3")

CCIMTF_OBTHRESH_1 = input(150, title="", group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf1")
CCIMTF_OBTHRESH_2 = input(150, title="", group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf2")
CCIMTF_OBTHRESH_3 = input(150, title="", group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf3")


CCIMTF1 = request.security(syminfo.tickerid, CCIMTF_1 == "Chart" ? "" : CCIMTF_1, cci_val, barmerge.gaps_off)
CCIMTF2 = request.security(syminfo.tickerid, CCIMTF_2 == "Chart" ? "" : CCIMTF_2, cci_val, barmerge.gaps_off)
CCIMTF3 = request.security(syminfo.tickerid, CCIMTF_3 == "Chart" ? "" : CCIMTF_3, cci_val, barmerge.gaps_off)

allMTFCCIOB_1 = (CCIMTF1 > CCIMTF_OBTHRESH_1 and CCIMTF2 > CCIMTF_OBTHRESH_2 and CCIMTF3 > CCIMTF_OBTHRESH_3)
allMTFCCIOS_1 = (CCIMTF1 < CCIMTF_OSTHRESH_1 and CCIMTF2 < CCIMTF_OSTHRESH_2 and CCIMTF3 < CCIMTF_OSTHRESH_3)

obColorCCI = (cci_val > CCITF_OBTHRESH_1+20 ? color.new(overboughtColor_1, 50) : cci_val > CCITF_OBTHRESH_1 ? color.new(overboughtColor_1, 70) : na)
osColorCCI = (cci_val < CCITF_OSTHRESH_1-20 ? color.new(oversoldColor_1, 50) : cci_val < CCITF_OSTHRESH_1 ? color.new(oversoldColor_1, 70) : na)

allOBColor_1 = (allMTFCCIOB_1 ? overboughtColor_1 : na)
allOSColor_1 = (allMTFCCIOS_1 ? oversoldColor_1 : na)

_cciRibbonPosition = switch cciRibbonPosition
    "Top" => location.top
    "Bottom" => location.bottom

plotchar(cci_val, title="Current TF overbought", color=(enableOBOSCCI and includeCurrentTFOBOSCCI ? obColorCCI : na), char="■", location=_cciRibbonPosition, size=size.auto)
plotchar(cci_val, title="Current TF oversold", color=(enableOBOSCCI and includeCurrentTFOBOSCCI ? osColorCCI : na), char="■", location=_cciRibbonPosition, size=size.auto)
plotchar(cci_val, title="All overbought", color=(enableOBOSCCI ? allOBColor_1 : na), char="■", location=_cciRibbonPosition, size=size.auto)
plotchar(cci_val, title="All oversold", color=(enableOBOSCCI ? allOSColor_1 : na), char="■", location=_cciRibbonPosition, size=size.auto)

bgcolor((useBgColorMTFCCIOBOS and allMTFCCIOB_1 ? color.new(allOBColor_1, 80) : (useBgColorMTFCCIOBOS and allMTFCCIOS_1 ? color.new(allOSColor_1, 80) : na)), title='CCI OB/OS background color')

barcolor(useBarColorMTFcciOBOS_1 and allMTFCCIOB_1 ? allOBColor_1 : (useBarColorMTFcciOBOS_1 and allMTFCCIOS_1 ? allOSColor_1 : na))

//Secondary MTF CCI confluences
grp_MTFCCI2             = "MTF CCI #2"
enableOBOS_2            = input(true, title="Show MTF #2 CCI OB/OS in ribbon", group=grp_MTFCCI2)
useBgColorMTFCCIOBOS_2  = input(false, title="Color background where MTF #2 CCI OB/OS", group=grp_MTFCCI2, tooltip="This will color the background to indicate the overbought / oversold state of the CCI on all 3x selected timeframes together at the same time.")
useBarColorMTFcciOBOS_2 = input(false, title="Color candles where MTF #2 OB/OS", group=grp_MTFCCI2, tooltip="This will color the candles to indicate the overbought / oversold state of the CCI on all 3x selected timeframes together at the same time.")
overboughtColor_2       = input.color(color.rgb(255, 68, 68, 50), title="CCI overbought color", group=grp_MTFCCI2)
oversoldColor_2         = input.color(color.rgb(43, 117, 46, 50), title="CCI oversold color", group=grp_MTFCCI2)

grp_MTFSRSI2_= "CCI MTF #2 [Timeframe] [OS level] [OB level]"
CCIMTF_1_2      = input.string("15", title="TF1", options=["Chart", "1", "2", "3", "4", "5", "8", "10", "15", "20", "30", "45", "60", "120", "240"], group=grp_MTFSRSI2_, inline="mtf1")
CCIMTF_2_2      = input.string("30", title="TF2", options=["Chart", "1", "2", "3", "4", "5", "8", "10", "15", "20", "30", "45", "60", "120", "240"], group=grp_MTFSRSI2_, inline="mtf2")
CCIMTF_3_2      = input.string("120", title="TF3", options=["Chart", "1", "2", "3", "4", "5", "8", "10", "15", "20", "30", "45", "60", "120", "240"], group=grp_MTFSRSI2_, inline="mtf3")

CCIMTF_OSTHRESH_1_2 = input(-150, title="", group=grp_MTFSRSI2_, inline="mtf1")
CCIMTF_OSTHRESH_2_2 = input(-150, title="", group=grp_MTFSRSI2_, inline="mtf2")
CCIMTF_OSTHRESH_3_2 = input(-150, title="", group=grp_MTFSRSI2_, inline="mtf3")

CCIMTF_OBTHRESH_1_2 = input(150, title="", group=grp_MTFSRSI2_, inline="mtf1")
CCIMTF_OBTHRESH_2_2 = input(150, title="", group=grp_MTFSRSI2_, inline="mtf2")
CCIMTF_OBTHRESH_3_2 = input(150, title="", group=grp_MTFSRSI2_, inline="mtf3")

CCIMTF1_2 = request.security(syminfo.tickerid, CCIMTF_1_2 == "Chart" ? "" : CCIMTF_1_2, cci_val, barmerge.gaps_off)
CCIMTF2_2 = request.security(syminfo.tickerid, CCIMTF_2_2 == "Chart" ? "" : CCIMTF_2_2, cci_val, barmerge.gaps_off)
CCIMTF3_2 = request.security(syminfo.tickerid, CCIMTF_3_2 == "Chart" ? "" : CCIMTF_3_2, cci_val, barmerge.gaps_off)

allMTFCCIOB_2 = (CCIMTF1_2 > CCIMTF_OBTHRESH_1_2 and CCIMTF2_2 > CCIMTF_OBTHRESH_2_2 and CCIMTF3_2 > CCIMTF_OBTHRESH_3_2)
allMTFCCIOS_2 = (CCIMTF1_2 < CCIMTF_OSTHRESH_1_2 and CCIMTF2_2 < CCIMTF_OSTHRESH_2_2 and CCIMTF3_2 < CCIMTF_OSTHRESH_3_2)

allOBColor_2 = (allMTFCCIOB_2 ? overboughtColor_2 : na)
allOSColor_2 = (allMTFCCIOS_2 ? oversoldColor_2 : na)


plotchar(cci_val, title="3x TF all overbought", color=(enableOBOS_2 ? allOBColor_2 : na), char="■", location=location.bottom)
plotchar(cci_val, title="3x TF all oversold", color=(enableOBOS_2 ? allOSColor_2 : na), char="■", location=location.bottom)

bgcolor((useBgColorMTFCCIOBOS_2 and allMTFCCIOB_2 ? color.new(allOBColor_2, 90) : (useBgColorMTFCCIOBOS_2 and allMTFCCIOS_2 ? color.new(allOSColor_2, 90) : na)), title='CCI OB/OS background colour')

barcolor(useBarColorMTFcciOBOS_2 and allMTFCCIOB_2 ? allOBColor_2 : (useBarColorMTFcciOBOS_2 and allMTFCCIOS_2 ? allOSColor_2 : na))


//Alerts
alertcondition((allMTFCCIOB_1 and not allMTFCCIOB_1[1]) or (allMTFCCIOS_1 and not allMTFCCIOS_1[1]), title="MTF #1 CCI OB/OS Detected in COI+", message="MTF #1 CCI OB/OS Detected in COI+")
alertcondition(allMTFCCIOB_1 and not allMTFCCIOB_1[1], title="MTF #1 CCI Overbought Detected in COI+", message="MTF #1 CCI Overbought Detected in COI+")
alertcondition(allMTFCCIOS_1 and not allMTFCCIOS_1[1], title="MTF #1 CCI Oversold Detected in COI+", message="MTF #1 CCI Oversold Detected in COI+")

alertcondition((allMTFCCIOB_2 and not allMTFCCIOB_2[1]) or (allMTFCCIOS_2 and not allMTFCCIOS_2[1]), title="MTF #2 CCI OB/OS Detected in COI+", message="MTF #2 CCI OB/OS Detected in COI+")
alertcondition(allMTFCCIOB_2 and not allMTFCCIOB_2[1], title="MTF #2 CCI Overbought Detected in COI+", message="MTF #2 CCI Overbought Detected in COI+")
alertcondition(allMTFCCIOS_2 and not allMTFCCIOS_2[1], title="MTF #2 CCI Oversold Detected in COI+", message="MTF #2 CCI Oversold Detected in COI+")


//Oscillator value table
grp_TABLE       = "MTF Table"
showMTFVals     = input(false, title="Show MTF table for", group=grp_TABLE, inline="table")
MTFTableType    = input.string("MTF #1 & #2", options=["MTF #1", "MTF #2", "MTF #1 & #2"], title="", group=grp_TABLE, inline="table")
dashboardSize   = input.string(title='', defval='Mobile', options=['Mobile', 'Desktop'], group=grp_TABLE, inline="table")
labelPos        = input.string(title="Table position", defval='Top right', options=['Top right', 'Top left', 'Bottom right', 'Bottom left'], group=grp_TABLE)
MTFTableColor   = input(color.new(color.white, 100), title="Table color", group=grp_TABLE)
labelColor      = color.new(color.white, 70)
valueColor      = color.new(color.white, 20)

_MTF1labelColor(val, ob, os) =>
    val > ob ? overboughtColor_1 : (val < os ? oversoldColor_1 : valueColor)

_MTF2labelColor(val, ob, os) =>
    val > ob ? overboughtColor_2 : (val < os ? oversoldColor_2 : valueColor)
    
_labelPos = switch labelPos
    "Top right" => position.top_right
    "Top left" => position.top_left
    "Bottom right" => position.bottom_right
    "Bottom left" => position.bottom_left

_size = switch dashboardSize
    "Mobile" => size.small
    "Desktop" => size.normal


var table label = table.new(_labelPos, 4, 4, bgcolor = MTFTableColor, frame_width = 0, frame_color = color.new(color.gray, 100))
// We only populate the table on the last bar.
if barstate.islast and showMTFVals
    if (MTFTableType=="MTF #1")
        table.cell(label, 0, 0, text="CCI", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 0, 1, text=CCIMTF_1+"m", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 1, 1, text=str.tostring(math.floor(CCIMTF1)), width=3, text_color=_MTF1labelColor(CCIMTF1, CCIMTF_OBTHRESH_1, CCIMTF_OSTHRESH_1), text_halign=text.align_right, text_size=_size, bgcolor=color.new(#000000, 100))
        table.cell(label, 0, 2, text=CCIMTF_2+"m", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 1, 2, text=str.tostring(math.floor(CCIMTF2)), width=3, text_color=_MTF1labelColor(CCIMTF2, CCIMTF_OBTHRESH_2, CCIMTF_OSTHRESH_2), text_halign=text.align_right, text_size=_size, bgcolor=color.new(#000000, 100))
        table.cell(label, 0, 3, text=CCIMTF_3+"m", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 1, 3, text=str.tostring(math.floor(CCIMTF3)), width=3, text_color=_MTF1labelColor(CCIMTF3, CCIMTF_OBTHRESH_3, CCIMTF_OSTHRESH_3), text_halign=text.align_right, text_size=_size, bgcolor=color.new(#000000, 100))
    else if (MTFTableType=="MTF #2")
        table.cell(label, 0, 0, text="CCI", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 0, 1, text=CCIMTF_1_2+"m", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 1, 1, text=str.tostring(math.floor(CCIMTF1_2)), width=3, text_color=_MTF2labelColor(CCIMTF1_2, CCIMTF_OBTHRESH_1_2, CCIMTF_OSTHRESH_1_2), text_halign=text.align_right, text_size=_size, bgcolor=color.new(#000000, 100))
        table.cell(label, 0, 2, text=CCIMTF_2_2+"m", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 1, 2, text=str.tostring(math.floor(CCIMTF2_2)), width=3, text_color=_MTF2labelColor(CCIMTF2_2, CCIMTF_OBTHRESH_2_2, CCIMTF_OSTHRESH_2_2), text_halign=text.align_right, text_size=_size, bgcolor=color.new(#000000, 100))
        table.cell(label, 0, 3, text=CCIMTF_3_2+"m", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 1, 3, text=str.tostring(math.floor(CCIMTF3_2)), width=3, text_color=_MTF2labelColor(CCIMTF3_2, CCIMTF_OBTHRESH_3_2, CCIMTF_OSTHRESH_3_2), text_halign=text.align_right, text_size=_size, bgcolor=color.new(#000000, 100))
    else if (MTFTableType=="MTF #1 & #2")
        table.cell(label, 0, 0, text="CCI", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 0, 1, text=CCIMTF_1+"m", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 1, 1, text=str.tostring(math.floor(CCIMTF1)), width=3, text_color=_MTF1labelColor(CCIMTF1, CCIMTF_OBTHRESH_1, CCIMTF_OSTHRESH_1), text_halign=text.align_right, text_size=_size, bgcolor=color.new(#000000, 100))
        table.cell(label, 0, 2, text=CCIMTF_2+"m", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 1, 2, text=str.tostring(math.floor(CCIMTF2)), width=3, text_color=_MTF1labelColor(CCIMTF2, CCIMTF_OBTHRESH_2, CCIMTF_OSTHRESH_2), text_halign=text.align_right, text_size=_size, bgcolor=color.new(#000000, 100))
        table.cell(label, 0, 3, text=CCIMTF_3+"m", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 1, 3, text=str.tostring(math.floor(CCIMTF3)), width=3, text_color=_MTF1labelColor(CCIMTF3, CCIMTF_OBTHRESH_3, CCIMTF_OSTHRESH_3), text_halign=text.align_right, text_size=_size, bgcolor=color.new(#000000, 100))

        table.cell(label, 2, 1, text=CCIMTF_1_2+"m", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 3, 1, text=str.tostring(math.floor(CCIMTF1_2)), width=3, text_color=_MTF2labelColor(CCIMTF1_2, CCIMTF_OBTHRESH_1_2, CCIMTF_OSTHRESH_1_2), text_halign=text.align_right, text_size=_size, bgcolor=color.new(#000000, 100))
        table.cell(label, 2, 2, text=CCIMTF_2_2+"m", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 3, 2, text=str.tostring(math.floor(CCIMTF2_2)), width=3, text_color=_MTF2labelColor(CCIMTF2_2, CCIMTF_OBTHRESH_2_2, CCIMTF_OSTHRESH_2_2), text_halign=text.align_right, text_size=_size, bgcolor=color.new(#000000, 100))
        table.cell(label, 2, 3, text=CCIMTF_3_2+"m", text_color=labelColor, text_halign=text.align_left, text_size=size.small, bgcolor=color.new(#000000, 100))
        table.cell(label, 3, 3, text=str.tostring(math.floor(CCIMTF3_2)), width=3, text_color=_MTF2labelColor(CCIMTF3_2, CCIMTF_OBTHRESH_3_2, CCIMTF_OSTHRESH_3_2), text_halign=text.align_right, text_size=_size, bgcolor=color.new(#000000, 100))


