Session Zones
// 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("Session Zones", "SZ", overlay=true, scale=scale.none)

// <inputs>
i_timezone = input.string("America/New_York", title="Timezone")

// session 1
i_session1Name = input.string("US Session", title="Identifier", group="Session 1")
i_session1 = input.session("0930-1600", title="Range", group="Session 1")
i_session1BgColor = input.color(color.new(color.gray, 80), title="Background", group="Session 1", inline="color")
i_session1Enabled = input.bool(true, "Display?", group="Session 1")
i_session1Alerts = input.bool(true, "Alert Entry/Exit?", group="Session 1")

// session 2
i_session2Name = input.string("EU Session", title="Identifier", group="Session 2")
i_session2 = input.session("0300-1230", title="Range", group="Session 2")
i_session2BgColor = input.color(color.new(color.aqua, 80), title="Background", group="Session 2", inline="color")
i_session2Enabled = input.bool(true, "Display?", group="Session 2")
i_session2Alerts = input.bool(true, "Alert Entry/Exit?", group="Session 2")

// session 3
i_session3Name = input.string("HK Session", title="Identifier", group="Session 3")
i_session3 = input.session("2130-0400", title="Range", group="Session 3")
i_session3BgColor = input.color(color.new(color.fuchsia, 80), title="Background", group="Session 3", inline="color")
i_session3Enabled = input.bool(true, "Display?", group="Session 3")
i_session3Alerts = input.bool(true, "Alert Entry/Exit?", group="Session 3")

// session 4
i_session4Name = input.string("JP Session", title="Identifier", group="Session 4")
i_session4 = input.session("2000-0200", title="Range", group="Session 4")
i_session4BgColor = input.color(color.new(color.blue, 80), title="Background", group="Session 4", inline="color")
i_session4Enabled = input.bool(true, "Display?", group="Session 4")
i_session4Alerts = input.bool(true, "Alert Entry/Exit?", group="Session 4")

// session 5
i_session5Name = input.string("US ORB", title="Identifier", group="Session 5")
i_session5 = input.session("0930-0945", title="Range", group="Session 5")
i_session5BgColor = input.color(color.new(color.lime, 80), title="Background", group="Session 5", inline="color")
i_session5Enabled = input.bool(true, "Display?", group="Session 5")
i_session5Alerts = input.bool(true, "Alert Entry/Exit?", group="Session 5")

i_hideSessionTable = input.bool(false, "Hide Session Table?")
// </inputs>

// <funcs>
f_timeInRange(_session) => not na(time(timeframe.period, _session + ":23456", i_timezone)) ? 1 : 0

f_isNewTimeframeBar(_res) =>
    t = time(_res)
    not na(t) and (na(t[1]) or t > t[1])

f_calculateSessionTableRows() =>
    count = 0

    if i_session1Enabled
        count := count + 1
    
    if i_session2Enabled
        count := count + 1

    if i_session3Enabled
        count := count + 1

    if i_session4Enabled
        count := count + 1

    if i_session5Enabled
        count := count + 1

    count

f_isSessionEnabled(_session) =>
    switch _session
        1 => i_session1Enabled
        2 => i_session2Enabled
        3 => i_session3Enabled
        4 => i_session4Enabled
        5 => i_session5Enabled
        => false

f_sessionName(_session) =>
    switch _session
        1 => i_session1Name
        2 => i_session2Name
        3 => i_session3Name
        4 => i_session4Name
        5 => i_session5Name
        => ''

f_sessionBgColor(_session) =>
    switch _session
        1 => i_session1BgColor
        2 => i_session2BgColor
        3 => i_session3BgColor
        4 => i_session4BgColor
        5 => i_session5BgColor
        => color.new(color.white, 100)

f_addSessionTableRow(_sessionTable, _sessionTableRows, _session, _inSession) =>
    if f_isSessionEnabled(_session)
        v_row = _sessionTableRows + 1

        table.cell(_sessionTable, row=v_row, column=0, text=f_sessionName(_session), text_color=color.black, bgcolor=color.white)
        table.cell(_sessionTable, row=v_row, column=1, text="   ", bgcolor=color.new(f_sessionBgColor(_session), 0))
        table.cell(_sessionTable, row=v_row, column=2, text=_inSession ? "In" : "Out", bgcolor=color.white)

        v_row
    else
        _sessionTableRows
// </funcs>

// <vars>
var v_sessionTableTotalRows = f_calculateSessionTableRows()
var v_sessionTableRowsCreated = -1
var v_sessionTable = table.new(position=position.top_right, rows=v_sessionTableTotalRows, columns=3, border_width=1)
var v_in_session1 = false
var v_in_session2 = false
var v_in_session3 = false
var v_in_session4 = false
var v_in_session5 = false

v_in_session1 := f_timeInRange(i_session1)
v_in_session2 := f_timeInRange(i_session2)
v_in_session3 := f_timeInRange(i_session3)
v_in_session4 := f_timeInRange(i_session4)
v_in_session5 := f_timeInRange(i_session5)

if not i_hideSessionTable
    v_sessionTableRowsCreated := f_addSessionTableRow(v_sessionTable, v_sessionTableRowsCreated, 1, v_in_session1)
    v_sessionTableRowsCreated := f_addSessionTableRow(v_sessionTable, v_sessionTableRowsCreated, 2, v_in_session2)
    v_sessionTableRowsCreated := f_addSessionTableRow(v_sessionTable, v_sessionTableRowsCreated, 3, v_in_session3)
    v_sessionTableRowsCreated := f_addSessionTableRow(v_sessionTable, v_sessionTableRowsCreated, 4, v_in_session4)
    v_sessionTableRowsCreated := f_addSessionTableRow(v_sessionTable, v_sessionTableRowsCreated, 5, v_in_session5)

    if v_sessionTableRowsCreated == v_sessionTableTotalRows - 1
        v_sessionTableRowsCreated := -1
// </vars>

// <plots>
bgcolor(i_session1Enabled and (v_in_session1 or v_in_session1[1]) ? i_session1BgColor : na, editable=false)
bgcolor(i_session2Enabled and (v_in_session2 or v_in_session2[1]) ? i_session2BgColor : na, editable=false)
bgcolor(i_session3Enabled and (v_in_session3 or v_in_session3[1]) ? i_session3BgColor : na, editable=false)
bgcolor(i_session4Enabled and (v_in_session4 or v_in_session4[1]) ? i_session4BgColor : na, editable=false)
bgcolor(i_session5Enabled and (v_in_session5 or v_in_session5[1]) ? i_session5BgColor : na, editable=false)
// </plots>

// <alerts>
if i_session1Enabled and i_session1Alerts and v_in_session1 and not v_in_session1[1]
    alert("Entering " + i_session1Name, alert.freq_once_per_bar_close)

if i_session1Enabled and i_session1Alerts and v_in_session1[1] and not v_in_session1
    alert("Exiting " + i_session1Name, alert.freq_once_per_bar_close)

if i_session2Enabled and i_session2Alerts and v_in_session2 and not v_in_session2[1]
    alert("Entering " + i_session2Name, alert.freq_once_per_bar_close)

if i_session2Enabled and i_session2Alerts and v_in_session2[1] and not v_in_session2
    alert("Exiting " + i_session2Name, alert.freq_once_per_bar_close)

if i_session3Enabled and i_session3Alerts and v_in_session3 and not v_in_session3[1]
    alert("Entering " + i_session3Name, alert.freq_once_per_bar_close)

if i_session3Enabled and i_session3Alerts and v_in_session3[1] and not v_in_session3
    alert("Exiting " + i_session3Name, alert.freq_once_per_bar_close)

if i_session4Enabled and i_session4Alerts and v_in_session4 and not v_in_session4[1]
    alert("Entering " + i_session4Name, alert.freq_once_per_bar_close)

if i_session4Enabled and i_session4Alerts and v_in_session4[1] and not v_in_session4
    alert("Exiting " + i_session4Name, alert.freq_once_per_bar_close)

if i_session5Enabled and i_session5Alerts and v_in_session5 and not v_in_session5[1]
    alert("Entering " + i_session5Name, alert.freq_once_per_bar_close)

if i_session5Enabled and i_session5Alerts and v_in_session5[1] and not v_in_session5
    alert("Exiting " + i_session5Name, alert.freq_once_per_bar_close)
// </alerts>