ICT True Day Range [MK]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © malk1903

// @version=5
indicator(title="ICT True Day Range [MK]", shorttitle="True Day Range [MK]", overlay=true, max_lines_count=500)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Inputs
mid_hl = input.bool(defval=true, title="Daily Range + Days of Week", inline='2', group="Enable Disable Sections--------------------------------------")
monds = input.bool(true, "Monday H/L/Mid", inline='3', group="Enable Disable Sections--------------------------------------")
i_hline = input.bool(true, "Midnight Open Line", inline='4', group="Enable Disable Sections--------------------------------------")
i_hline2 = input.bool(true, "08:30 Open Line", inline='4', group="Enable Disable Sections--------------------------------------")
wkOPN = input.bool(title='Week Open', defval=true, inline='3', group="Enable Disable Sections--------------------------------------")
tzone = input.string("GMT-4", "Timezone", options=["GMT+0", "GMT+1", "GMT+2", "GMT+3","GMT+4","GMT+5","GMT+6","GMT+7","GMT+8","GMT+9","GMT+10","GMT+11","GMT+12","GMT-1", "GMT-2", "GMT-3","GMT-4","GMT-5","GMT-6","GMT-7","GMT-8","GMT-9","GMT-10","GMT-11","GMT-12"], inline='5', group="Enable Disable Sections--------------------------------------")
i_maxtf_dr             = input.int         (60, "Max Timeframe", 1, 240, inline='5', group="Enable Disable Sections--------------------------------------")
disp_dr                = timeframe.isintraday and timeframe.multiplier <= i_maxtf_dr
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Days of Week
dow_colour = input.color(color.new(color.silver,0), title='Days of Week', inline='01', group="Days of the Week--------------------------------")
var minuteFix = 0
if timeframe.ismonthly or timeframe.isweekly or timeframe.isdaily
    minuteFix := 59
    minuteFix
    
plotshape(mid_hl and disp_dr ? hour == 11 and minute == minuteFix and dayofweek == dayofweek.monday : false, text='Monday', color=color.new(color.white, 100), offset=0, style=shape.diamond, textcolor=dow_colour, size=size.normal, location=location.bottom)
plotshape(mid_hl and disp_dr ? hour == 11 and minute == minuteFix and dayofweek == dayofweek.tuesday : false, text='Tuesday', color=color.new(color.white, 100), offset=0, style=shape.diamond, textcolor=dow_colour, size=size.normal, location=location.bottom)
plotshape(mid_hl and disp_dr ? hour == 11 and minute == minuteFix and dayofweek == dayofweek.wednesday : false, text='Wednesday', color=color.new(color.white, 100), offset=0, style=shape.diamond, textcolor=dow_colour, size=size.normal, location=location.bottom)
plotshape(mid_hl and disp_dr ? hour == 11 and minute == minuteFix and dayofweek == dayofweek.thursday : false, text='Thursday', color=color.new(color.white, 100), offset=0, style=shape.diamond, textcolor=dow_colour, size=size.normal, location=location.bottom)
plotshape(mid_hl and disp_dr ? hour == 11 and minute == minuteFix and dayofweek == dayofweek.friday : false, text='Friday/Sunday', color=color.new(color.white, 100), offset=0, style=shape.diamond, textcolor=dow_colour, size=size.normal, location=location.bottom)
plotshape(mid_hl and disp_dr ? hour == 11 and minute == minuteFix and dayofweek == dayofweek.saturday : false, text='Saturday', color=color.new(color.white, 100), offset=0, style=shape.diamond, textcolor=dow_colour, size=size.normal, location=location.bottom)
plotshape(mid_hl and disp_dr ? hour == 11 and minute == minuteFix and dayofweek == dayofweek.sunday : false, text='Sunday', color=color.new(color.white, 100), offset=0, style=shape.diamond, textcolor=dow_colour, size=size.normal, location=location.bottom) 

//////////////////////////////////////////////////////////////////////////////////////////////Vline for Days of the Week
//Vertical Day Seperator EST midnight
// === Used By Both Methods Below ===
openHourk2      = 23
openMinutek2    = 00
isHourk2        = hour == openHourk2
isMinutek2      = minute == openMinutek2
vline_colour    = input.color(color.new(color.silver,0), title='Day Seperator', inline='01', group="Day Seperator")
i_vline_style   = input.string(defval="Solid", title="", options=["Solid", "Dotted", "Dashed"], inline='01', group="Day Seperator")
vwidth          = input.int(1, title="Width", inline='01', group="Day Seperator")
vline_style     = i_vline_style ==   "Solid" ? line.style_solid : i_vline_style == "Dotted" ? line.style_dotted : line.style_dashed

// === Method Line ===
vline2(BarIndex, Color, LineStyle, LineWidth) => // Verticle Line Function, ≈50-54 lines maximum allowable per indicator
    reTurn = line.new(BarIndex, low - ta.tr, BarIndex, high + ta.tr, xloc.bar_index, extend.both, Color, LineStyle, LineWidth) // Suitable for study(overlay=true)
if(mid_hl and isHourk2 and isMinutek2) and disp_dr 
    vline2(bar_index,vline_colour, vline_style, vwidth) // Variable assignment not required

inSession(sessionTime, sessionTimeZone=syminfo.timezone) =>
    not na(time(timeframe.period, sessionTime, sessionTimeZone))

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Monday High/Low/Mid

var market_open_day_of_week = input.string(title='What day of the week does the market open?', options=['Sunday', 'Monday'], defval='Sunday', group="Monday High/Low/Mid")  // Some exchanges open sunday evening vs crypto std monday
var bars_extended_to_week_end = input(title='Extend bars to end of week?', defval=false, inline='2')
monmid = input.bool(defval=true, title="Show Midline", inline='2')
var bars_extent = input.int(title='Length of bars', defval=150, minval=1, maxval=300)
var line_colour = input.color(color.new(color.fuchsia,0), title='Line Color', inline='01')
mline_style = input.string(defval="dashed (╌)", title="", options=["solid (─)", "dotted (┈)", "dashed (╌)"], inline='01')
mondaywidth = input.int(2, title="Width", inline='01')


monday_open_time = request.security(syminfo.tickerid, 'D', time('D'), lookahead=barmerge.lookahead_on)
monday_high = request.security(syminfo.tickerid, 'D', high, lookahead=barmerge.lookahead_on)
monday_low = request.security(syminfo.tickerid, 'D', low, lookahead=barmerge.lookahead_on)
monday_midpoint = math.avg(monday_high, monday_low)

is_monday() =>
    dayofweek(time('D')) == (market_open_day_of_week == 'Sunday' ? dayofweek.sunday : dayofweek.monday) and close ? true : false

var can_show_monday_range = not timeframe.isweekly and not timeframe.ismonthly and not timeframe.isseconds  // dont show above daily or below minutes

// Function the converts string inputs to line style code
line_style_function(input_var) =>
    switch input_var
        "dotted (┈)" => line.style_dotted
        "dashed (╌)" => line.style_dashed
        => line.style_solid

i_mline_style = line_style_function(mline_style)

line_end_bars = if bars_extended_to_week_end
    // Calculate the bars until the end of the week
    // timeframe.multiplier is either daily or minutes
    if timeframe.isdaily
        7
    else
        1440 / timeframe.multiplier * 7  // (mins in  day / multiplier) * days in a week
else
    bars_extent


line_end_right = monday_open_time + (time - time[1]) * line_end_bars  // extend line until the end of the week or number of bars chosen

if is_monday() and monds and disp_dr
    // Monday high
    monday_high_text = 'MH    '
    var monday_high_line = line.new(x1=monday_open_time, x2=line_end_right, y1=monday_high, y2=monday_high, color=line_colour, width=mondaywidth, xloc=xloc.bar_time, style=i_mline_style)
    var monday_high_label = label.new(x=line_end_right, y=monday_open_time, text=monday_high_text, style=label.style_none, textcolor=line_colour, size=size.small, xloc=xloc.bar_time)

    line.set_x1(monday_high_line, monday_open_time)
    line.set_x2(monday_high_line, line_end_right)
    line.set_y1(monday_high_line, monday_high)
    line.set_y2(monday_high_line, monday_high)
    label.set_x(monday_high_label, line_end_right)
    label.set_y(monday_high_label, monday_high)

    // Monday low
    monday_low_text = 'ML    '
    var monday_low_line = line.new(x1=monday_open_time, x2=line_end_right, y1=monday_low, y2=monday_low, color=line_colour, width=mondaywidth, xloc=xloc.bar_time, style=i_mline_style)
    var monday_low_label = label.new(x=line_end_right, y=monday_open_time, text=monday_low_text, style=label.style_none, textcolor=line_colour, size=size.small, xloc=xloc.bar_time)

    line.set_x1(monday_low_line, monday_open_time)
    line.set_x2(monday_low_line, line_end_right)
    line.set_y1(monday_low_line, monday_low)
    line.set_y2(monday_low_line, monday_low)
    label.set_x(monday_low_label, line_end_right)
    label.set_y(monday_low_label, monday_low)

    // Monday mid
    if monmid
        monday_mid_text = 'MID     '
        var monday_mid_line = line.new(x1=monday_open_time, x2=line_end_right, y1=monday_midpoint, y2=monday_midpoint, color=line_colour, width=mondaywidth, xloc=xloc.bar_time, style=i_mline_style)
        var monday_mid_label = label.new(x=line_end_right, y=monday_open_time, text=monday_mid_text, style=label.style_none, textcolor=line_colour, size=size.small, xloc=xloc.bar_time)

        line.set_x1(monday_mid_line, monday_open_time)
        line.set_x2(monday_mid_line, line_end_right)
        line.set_y1(monday_mid_line, monday_midpoint)
        line.set_y2(monday_mid_line, monday_midpoint)
        label.set_x(monday_mid_label, line_end_right)
        label.set_y(monday_mid_label, monday_midpoint)

//////Midnight Line

i_time              = '0000-0001:1234567'//input.session     ('0000-0001:1234567', "New York", tooltip="Different exchanges will have difference time zones so change accordingly.", group="Opening Line")
i_time2             = '0830-0831:1234567'//input.session     ('0830-0831:1234567', "New York", tooltip="Different exchanges will have difference time zones so change accordingly.", group="Opening Line")
opening = "Opening Lines--------------------------------------"
i_linecol           = input.color       (#0064ff, "Midnight Line", inline="in1", group=opening)
i_linecol2          = input.color       (color.new(color.yellow,25), "08:30 Line", inline="in2", group=opening)
i_linestyle         = input.string      ("Solid", "", options=["Solid", "Dotted", "Dashed"], inline="in1", group=opening)
i_linestyle2        = input.string      ("Dashed", "", options=["Solid", "Dotted", "Dashed"], inline="in2", group=opening)
mid_w               = input.int         (defval=2, title="Width", inline="in1", group=opening)
eight_w             = input.int         (defval=2, title="Width", inline="in2", group=opening)
i_ex                = "None"

// MISC
nymid               = time              ("1", i_time, tzone)
open_830            = time              ("1", i_time2, tzone)
linestyle           = i_linestyle ==    "Solid" ? line.style_solid : i_linestyle == "Dotted" ? line.style_dotted : line.style_dashed
linestyle2          = i_linestyle2 ==   "Solid" ? line.style_solid : i_linestyle2 == "Dotted" ? line.style_dotted : line.style_dashed
ex                  = "None" 
htime               = i_ex        ==    "+1 Day" ? 172800000 : 86400000//extends 00:00 line to midnight - for midnight sessions
htime2              = i_ex        ==    "+1 Day" ? 172800000 : 55800000//extends 0830 line to midnight - for midnight sessions
dow                 = dayofweek   ==    dayofweek.friday ? 259200000 : 86400000
dow2                = dayofweek   ==    dayofweek.friday ? 172800000 : 86400000 //this is for asia coming out of weekend
dow3                = dayofweek   ==    dayofweek.friday ? 172800000  : 0

var openprice       = 0.0
if nymid
    if not nymid[1]
        openprice := open
    else
        openprice := math.max(open, openprice)

// OBJECTS
var label lb = na
if openprice != openprice[1] and i_hline and disp_dr
    var line lne = na
    line.set_x2(lne, nymid)
    line.set_extend(lne, extend.none)
    lne := line.new(nymid, openprice, nymid + htime + dow3, openprice, xloc.bar_time, extend=extend.none, color=i_linecol, style=linestyle, width=mid_w)

//0830 Line

var openprice2       = 0.0
if open_830
    if not open_830[1]
        openprice2 := open
    else
        openprice2 := math.max(open, openprice2)

// OBJECTS
var label lb2 = na
if openprice2 != openprice2[1] and i_hline2 and disp_dr
    var line lne2 = na
    // line.set_x2(lne2, open_830)
    line.set_extend(lne2, extend.none)
    lne2 := line.new(open_830, openprice2, open_830 + htime2 + dow3, openprice2, xloc.bar_time, extend=extend.none, color=i_linecol2, style=linestyle2, width=eight_w)

////////////////////////////////////////////////////////////////////////////////////////Session High/Lows
//------------------------------------------------------------------------------
//Settings
//-----------------------------------------------------------------------------{
reghl_c = input.color(color.new(color.white,50), 'High/Low Lines' , inline = '1', group ="Session H/L------------------------------")
i_hl_style         = input.string      ("Solid", "", options=["Solid", "Dotted", "Dashed"], inline = '1', group ="Session H/L------------------------------")
reghl_w = input.int(defval=1, title='Width', inline = '1', group ="Session H/L------------------------------")
hl_style = i_hl_style ==   "Solid" ? line.style_solid : i_hl_style == "Dotted" ? line.style_dotted : line.style_dashed
//-----------------------------------------------------------------------------}
//UDT's
//-----------------------------------------------------------------------------{
type session_range
    line max
    line min

//-----------------------------------------------------------------------------}
//Methods
//-----------------------------------------------------------------------------{
n = bar_index

//Method for setting session range maximum/minimum
method set_range(session_range id)=>
    max = math.max(high, id.max.get_y2())
    min = math.min(low, id.min.get_y2())

    id.max.set_xy2(n, max)
    id.max.set_y1(max)

    id.min.set_xy2(n, min)
    id.min.set_y1(min)

//-----------------------------------------------------------------------------}
//Variables
//-----------------------------------------------------------------------------{
var chartCss = color.new(color.white,50)
var session_range sesr = na

//-----------------------------------------------------------------------------}
//New session - NY Midnight Hours
//-----------------------------------------------------------------------------{

//On new session
if(isHourk2 and isMinutek2) and mid_hl and disp_dr
    //Set delimiter
    line.new(n, high + syminfo.mintick
      , n, low - syminfo.mintick
      , color = chartCss
      , style = line.style_dashed
      , extend = extend.both)

    //Set new range
    sesr := session_range.new(
      line.new(n, high, n, high, color = chartCss, style=hl_style, width=reghl_w)
      , line.new(n, low, n, low, color = chartCss, style=hl_style, width=reghl_w))

//Set range
else if not na(sesr)
    sesr.set_range()

    //Set range lines color
    sesr.max.set_color(reghl_c)
    sesr.min.set_color(reghl_c)


wkOPN_clr = input.color(color.new(color.orange, 0), title="Week Open Line", group="Week Open-------------------------------------------------------", inline = "4")
WkStyle   = input.string  ("Solid", "", options=["Solid", "Dotted", "Dashed"], group="Week Open-------------------------------------------------------", inline = "4")
linewidths = input.int(defval=2, title="Width", group="Week Open-------------------------------------------------------", inline = "4")

//linestyles
_WkStyle   = WkStyle ==    "Solid" ? line.style_solid : WkStyle == "Dotted" ? line.style_dotted : line.style_dashed

//Fri_PM = input.session(defval="0830-1600", title="Friday hours to show 20-30% levels")//input.session(title='Display Period', defval='1300-1600:6', inline="2", group="Friday Only-------------------------------------------------------", tooltip="20-30% box will only be shown during this session period, default is to only show during friday PM session")
Wk_sess = '1800-1700'

//Weekly New Bar
is_newbar2(sess) =>
    t = time('W', sess, tzone)
    na(t[1]) and not na(t) or t[1] < t


is_session2(sess) =>
    not na(time('W', sess, tzone))

//New Week
WeekNewbar = is_newbar2(Wk_sess)
WeekSession = is_session2(Wk_sess)

///////new weekbox high low and level boxes
if WeekSession and disp_dr
    ///////////////////////////////////////////
    float WkOpen = na
    WkOpen := if WeekSession
        if WeekNewbar
            open
        else
            WkOpen[1]

    /////////////////////////////////////////
    int WkStart = na
    WkStart := if WeekSession
        if WeekNewbar
            time
        else
            math.min(WkStart[1], time)
    else
        na
    
    int WkEnd = na
    WkEnd := if WeekSession
        if WeekNewbar
            time_close
        else
            math.max(WkEnd[1], time_close)
    else
        na
  
    weeklyopen = if WeekNewbar
        weeklyopen = wkOPN ? line.new(WkStart, WkOpen, WkEnd, WkOpen, xloc = xloc.bar_time, style = _WkStyle, width = linewidths, color = wkOPN_clr) : na
    
    if not WeekNewbar
        line.set_x2(weeklyopen[1], WkEnd)
        line.set_y1(weeklyopen[1], WkOpen)
        line.set_y2(weeklyopen[1], WkOpen)



 