Candle Levels
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © syntaxgeek

//@version=5
indicator("Candle Levels", overlay=true)

// <inputs>
i_candleTime = input.time(0, "Candle Time", confirm=true)
i_timeframe = input.timeframe("", "Timeframe", confirm=true)
i_note = input.string("", "Note", tooltip="Provide short note to display on label if desired.", confirm=true)
i_bullishHigh = input.color(color.green, "Bullish High", group="Style Bullish")
i_bullishLow = input.color(color.red, "Bullish Low", group="Style Bullish")
i_bearishHigh = input.color(color.red, "Bearish High", group="Style Bearish")
i_bearishLow = input.color(color.green, "Bearish Low", group="Style Bearish")
i_closeColor = input.color(color.blue, "Close", group="Style Neutral", inline="close")
i_closeTextColor = input.color(color.white, "Text", group="Style Neutral", inline="close")
i_openColor = input.color(color.lime, "Open", group="Style Neutral", inline="open")
i_openTextColor = input.color(color.white, "Text", group="Style Neutral", inline="open")
i_bodyMidColor = input.color(color.orange, "Body Mid", group="Style Neutral", inline="bodyMid")
i_bodyMidTextColor = input.color(color.white, "Text", group="Style Neutral", inline="bodyMid")
i_midColor = input.color(color.white, "Mid", group="Style Neutral", inline="mid")
i_midTextColor = input.color(color.black, "Text", group="Style Neutral", inline="mid")
i_highQuarterMidColor = input.color(color.olive, "High Quarter Mid", group="Style Neutral", inline="highQuarterMid")
i_highQuarterMidTextColor = input.color(color.white, "Text", group="Style Neutral", inline="highQuarterMid")
i_lowQuarterMidColor = input.color(color.olive, "Low Quarter Mid", group="Style Neutral", inline="lowQuarterMid")
i_lowQuarterMidTextColor = input.color(color.white, "Text", group="Style Neutral", inline="lowQuarterMid")
i_highWickMidColor = input.color(color.purple, "High Wick Mid", group="Style Neutral", inline="highWickMid")
i_highWickMidTextColor = input.color(color.white, "Text", group="Style Neutral", inline="highWickMid")
i_lowWickMidColor = input.color(color.purple, "Low Wick Mid", group="Style Neutral", inline="lowWickMid")
i_lowWickMidTextColor = input.color(color.white, "Text", group="Style Neutral", inline="lowWickMid")
i_showLabels = input.bool(false, "Show Labels?", confirm=true, group="Labels")
i_showTime = input.bool(false, "Show Time In Labels?", confirm=true, group="Labels")
i_showPrice = input.bool(true, "Show Price In Labels?", confirm=true, group="Labels")
i_showHighLabel = input.bool(true, "Show High Label?", group="Labels")
i_showLowLabel = input.bool(true, "Show Low Label?", group="Labels")
i_showCloseLabel = input.bool(true, "Show Close Label?", group="Labels")
i_showOpenLabel = input.bool(true, "Show Open Label?", group="Labels")
i_showBodyMidLabel = input.bool(true, "Show Body Mid Label?", group="Labels")
i_showMidLabel = input.bool(true, "Show Mid Label?", group="Labels")
i_showHighQuarterMidLabel = input.bool(true, "Show High Quarter Mid Label?", group="Labels")
i_showLowQuarterMidLabel = input.bool(true, "Show Low Quarter Mid Label?", group="Labels")
i_showHighWickMidLabel = input.bool(true, "Show High Wick Mid Label?", group="Labels")
i_showLowWickMidLabel = input.bool(true, "Show Low Wick Mid Label?", group="Labels")
// </inputs>

// <funcs>
f_sourceFromBarOnTimeframe(exp) =>
    indexHighTF = barstate.isrealtime ? 1 : 0
    indexCurrTF = barstate.isrealtime ? 0 : 1
    request.security(ticker.modify(syminfo.tickerid, session=session.extended), i_timeframe, exp[indexHighTF])[indexCurrTF]

f_plotLabel(y, displayText, identifier, color, textColor) =>
    formattedLabelText = identifier + " " + displayText
    if i_note != ""
        formattedLabelText := formattedLabelText + " (" + i_note + ")"

    formattedLabelText := formattedLabelText + " @ " + str.tostring(y)

    var lbl = label.new(bar_index, y, style=label.style_label_lower_left, text=formattedLabelText, color=color, textcolor=textColor)
    label.set_xy(lbl, bar_index, y)
    label.set_color(lbl, color)
    label.set_text(lbl, formattedLabelText)

f_timeframePrettyPrint(tf) =>
    v_printed = str.tostring(year(tf)) + "-" + str.tostring(month(tf), "00") + "-" + str.tostring(dayofmonth(tf), "00")
    if i_showTime
        v_printed := v_printed + " " + str.tostring(hour(tf), "00") + ":" + str.tostring(minute(tf), "00") + ":" + str.tostring(second(tf), "00")
    v_printed
// </funcs>

// <vars>
v_candleClose = f_sourceFromBarOnTimeframe(ta.valuewhen(time == i_candleTime, close, 0))
v_candleOpen  = f_sourceFromBarOnTimeframe(ta.valuewhen(time == i_candleTime, open, 0))
v_candleHigh  = f_sourceFromBarOnTimeframe(ta.valuewhen(time == i_candleTime, high, 0))
v_candleLow   = f_sourceFromBarOnTimeframe(ta.valuewhen(time == i_candleTime, low, 0))
v_candleHighWickMid = v_candleClose > v_candleOpen ? ((v_candleHigh - v_candleClose) / 2) + v_candleClose : ((v_candleHigh - v_candleOpen) / 2) + v_candleOpen
v_candleLowWickMid = v_candleClose > v_candleOpen ? ((v_candleOpen - v_candleLow) / 2) + v_candleLow : ((v_candleClose - v_candleLow) / 2) + v_candleLow
v_candleBodyMid = v_candleClose > v_candleOpen ? v_candleClose - ((v_candleClose - v_candleOpen) / 2) : v_candleOpen - ((v_candleOpen - v_candleClose) / 2)
v_candleMid = v_candleHigh - ((v_candleHigh - v_candleLow) / 2)
v_candleHighQuarterMid = v_candleMid + ((v_candleHigh - v_candleMid) / 2)
v_candleLowQuarterMid = v_candleMid - ((v_candleMid - v_candleLow) / 2)
v_candleIsBullish = v_candleClose > v_candleOpen
v_candleHighColor = v_candleIsBullish ? i_bullishHigh : i_bearishHigh
v_candleLowColor = v_candleIsBullish ? i_bullishLow : i_bearishLow
var v_timeframePrettyPrint = f_timeframePrettyPrint(i_candleTime)
// </vars>

// <plots>
if i_showLabels
    if i_showHighLabel
        f_plotLabel(v_candleHigh, v_timeframePrettyPrint, "High", v_candleHighColor, color.white)
    
    if i_showLowLabel
        f_plotLabel(v_candleLow, v_timeframePrettyPrint, "Low", v_candleLowColor, color.white)
    
    if i_showCloseLabel
        f_plotLabel(v_candleClose, v_timeframePrettyPrint, "Close", i_closeColor, i_closeTextColor)

    if i_showOpenLabel
        f_plotLabel(v_candleOpen, v_timeframePrettyPrint, "Open", i_openColor, i_openTextColor)
    
    if i_showBodyMidLabel
        f_plotLabel(v_candleBodyMid, v_timeframePrettyPrint, "Body Mid", i_bodyMidColor, i_bodyMidTextColor)

    if i_showMidLabel
        f_plotLabel(v_candleMid, v_timeframePrettyPrint, "Mid", i_midColor, i_midTextColor)

    if i_showHighQuarterMidLabel
        f_plotLabel(v_candleHighQuarterMid, v_timeframePrettyPrint, "High Quarter Mid", i_highQuarterMidColor, i_highQuarterMidTextColor)

    if i_showLowQuarterMidLabel
        f_plotLabel(v_candleLowQuarterMid, v_timeframePrettyPrint, "Low Quarter Mid", i_lowQuarterMidColor, i_lowQuarterMidTextColor)

    if i_showHighWickMidLabel
        f_plotLabel(v_candleHighWickMid, v_timeframePrettyPrint, "High Wick Mid", i_highWickMidColor, i_highWickMidTextColor)

    if i_showLowWickMidLabel
        f_plotLabel(v_candleLowWickMid, v_timeframePrettyPrint, "Low Wick Mid", i_lowWickMidColor, i_lowWickMidTextColor)

plot(v_candleHigh, "High", color=v_candleHighColor)
plot(v_candleLow, "Low", color=v_candleLowColor)
plot(v_candleClose, "Close", color=i_closeColor)
plot(v_candleOpen, "Open", color=i_openColor)
plot(v_candleBodyMid, "Body Mid", color=i_bodyMidColor)
plot(v_candleMid, "Mid", color=i_midColor)
plot(v_candleHighQuarterMid, "High Quarter Mid", color=i_highQuarterMidColor)
plot(v_candleLowQuarterMid, "Low Quarter Mid", color=i_lowQuarterMidColor)
plot(v_candleHighWickMid, "High Wick Mid", color=i_highWickMidColor)
plot(v_candleLowWickMid, "Low Wick Mid", color=i_lowWickMidColor)
// </plots>