Show Extended Hours (Futures & Crypto)
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © liquid-trader

// This indicator mimics TradingViews "Extended trading hours" background color settings.
// It is most useful on symbols that do not conventionally have extended hours, but are available to trade during
// those hours (ie. Futures and Crypto).
// More here: https://www.tradingview.com/script/B7EzfHLP-Show-Extended-Hours-Futures-Crypto/

//@version=5
indicator("Show Extended Hours (Futures & Crypto)", "Ext. Hrs.", true)

// Base Colors
clr1 = color.new(color.orange, 92), clr2 = color.new(color.blue, 92), clr3 = color.new(color.gray, 90)

// Group Labels
g1 = "Market Segments", g2 = "Market Hours"

// Premarket Settings
pm = input.bool(true, "Premarket               ", inline="pm", group=g1, display=display.none)
pmClr = input.color(clr1, "", inline="pm", group=g1, display=display.none)

// After Hours Settings
ah = input.bool(true, "After Hour               ", inline="ah", group=g1, display=display.none)
ahClr = input.color(clr2, "", inline="ah", group=g1, display=display.none)

// Near Open Settings
no = input.bool(true, "Near Market Open ", inline="no", group=g1, display=display.none)
noClr = input.color(clr3, "", inline="no", group=g1, display=display.none)
noMin  = input.int(60, "", 0, tooltip="The number of minutes before the market opens to change the charts background color, as a visual reminder it's about to open.", group=g1, inline="no", display=display.none)

// Near Close Settings
nc = input.bool(true, "Near Market Close ", inline="nc", group=g1, display=display.none)
ncClr = input.color(clr3, "", inline="nc", group=g1, display=display.none)
ncMin = input.int(60, "", 0, tooltip="The number of minutes before the market closes to change the charts background color, as a visual reminder it's about to close.", group=g1, inline="nc", display=display.none)

// Midday Settings
md = input.bool(false, "Midday Range        ", inline="md", group=g1, display=display.none)
mdClr = input.color(clr3, "", inline="md", group=g1, display=display.none)
mdMin = input.session("1100-1300", "", tooltip = "The time range considered \"midday\" in a 24 hour format, where 1100 is 11:00 AM, 1330 is 1:30 PM, etc.", group=g1, inline="md", display=display.none)

// Market Hour Settings
mktHrs = input.session("0930-1600", "Start / End Time", tooltip = "A 24 hour format, where 0930 is 9:30 AM, 1600 is 4:00 PM, etc.", group=g2, display=display.none)
timezone = input("America/New_York", "Time Zone", "Any IANA time zone ID. Ex: America/New_York", group=g2, display=display.none)

// Normalize times.
startTime = str.substring(mktHrs, 0, 4), var endTime = str.substring(mktHrs, 5, 9), var st = str.tonumber(startTime), var et = str.tonumber(endTime)

normalizeTime(t) =>
    str = str.tostring(t)
    while str.length(str) < 4
        str := "0" + str
    str
setTimeNearOC(t) =>
    r = switch t
        st  => noMin
        et => ncMin
    h = math.floor(t / 100)
    m = t % 100, m := m - r
    if m < 0
        while m < 0
            h -= 1
            m += 60
    normalizeTime(h * 100 + m)

nearStartTime = setTimeNearOC(st)
nearEndTime   = setTimeNearOC(et)

// Define Market Hours
pmHrs  = "0000-" + startTime
aftHrs = endTime + "-2400"
nearMktOpen  = nearStartTime + "-" + startTime
nearMktClose = nearEndTime + "-" + endTime
minutesInDay = "1440"

// Evaluate if the current time is within the premarket or after hours.
premarket  = not na(time(minutesInDay, pmHrs, timezone)) and pm
afterhours = not na(time(minutesInDay, aftHrs, timezone)) and ah
nearOpen   = not na(time(minutesInDay, nearMktOpen, timezone)) and no
midday     = not na(time(minutesInDay, mdMin, timezone)) and md 
nearClose  = not na(time(minutesInDay, nearMktClose, timezone)) and nc

// Change the charts background color.
bgcolor(premarket  ? pmClr : na, 0, false)
bgcolor(afterhours ? ahClr : na, 0, false)
bgcolor(nearOpen   ? noClr : na, 0, false)
bgcolor(midday     ? mdClr : na, 0, false)
bgcolor(nearClose  ? ncClr : na, 0, false)