dmn's ICT Toolkit
// This source code is subjectsubject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © fxdmn
// @version=5
indicator(title="dmn's ICT Toolkit", shorttitle="dmn's ICT Toolkit", overlay=true, max_lines_count=500, max_boxes_count=500)
// ███████╗██╗  ██╗██████╗ ███╗   ███╗███╗   ██╗
// ██╔════╝╚██╗██╔╝██╔══██╗████╗ ████║████╗  ██║
// █████╗   ╚███╔╝ ██║  ██║██╔████╔██║██╔██╗ ██║
// ██╔══╝   ██╔██╗ ██║  ██║██║╚██╔╝██║██║╚██╗██║
// ██║     ██╔╝ ██╗██████╔╝██║ ╚═╝ ██║██║ ╚████║
// ╚═╝     ╚═╝  ╚═╝╚═════╝ ╚═╝     ╚═╝╚═╝  ╚═══╝
                                      

//{ Constants
var CBDR_SESSION                    = "1400-2000"
var FLOUT_SESSION                   = "1500-2400"
var ASIA_SESSION                    = "2000-2400"
var TRUEDAY_SESSION                 = "0000-0100"
var SUNDAY_SESSION                  = "1700-1701:1"
var DAILY_OPEN_SESSION              = "1700-1704"
var GMT_OPEN_SESSION                = "1900-1901"
var FOUR_OPEN_SESSION               = "0400-0401"
var LONDON_OPEN_KILLZONE_SESSION    = "0200-0500"
var NY_OPEN_KILLZONE_SESSION        = "0700-0900"
var LONDON_CLOSE_KILLZONE_SESSION   = "1030-1200"
var ASIAN_OPEN_KILLZONE_SESSION     = "2000-2200"
var NY_LUNCH_SESSION                = "1200-1300"
var CBDR_LABEL_NAME                 = "CBDR"
var FLOUT_LABEL_NAME                = "Flout"
var ASIA_LABEL_NAME                 = "AR"

var NEW_YORK_MIDNIGHT_LABEL_TEXT    = "NY Midnight Open"
var NEW_YORK_MIDNIGHT_LABEL_SHORT   = "NYM"
var GMT_LABEL_TEXT                  = "GMT Midnight Open"
var GMT_LABEL_SHORT                 = "GMT"
var FOUR_OPEN_LABEL_TEXT            = "4am Open"
var FOUR_OPEN_LABEL_SHORT           = "4am"
var DAILY_OPEN_LABEL_TEXT           = "Daily Open"
var DAILY_OPEN_LABEL_SHORT          = "DO"
var PDH_LABEL_TEXT                  = "Previous Day High"
var PDH_LABEL_SHORT                 = "PDH"
var PDL_LABEL_TEXT                  = "Previous Day Low"
var PDL_LABEL_SHORT                 = "PDL"
var PMH_LABEL_TEXT                  = "Previous Month High"
var PMH_LABEL_SHORT                 = "PMH"
var PML_LABEL_TEXT                  = "Previous Month Low"
var PML_LABEL_SHORT                 = "PML"
var PWH_LABEL_TEXT                  = "Previous Week High"
var PWH_LABEL_SHORT                 = "PWH"
var PWL_LABEL_TEXT                  = "Previous Week Low"
var PWL_LABEL_SHORT                 = "PWL"


var TT_KILLZONE_OLD                 = "Original look of the killzones (note: text labels unavailable)"
var TT_AUTO_TZ                      = "Overrides the manual option and sets the timezone automatically."

var TT_ADR_LOOKBACK_INPUT           = "Number of closed candles used to calculate the ADR"
var TT_SESSION_ZONE_INPUT           = "Change if not displaying New York midnight correctly"
var TT_TABLE_LOC_INPUT              = "Shows x days average daily range, current daily range, CBDR range and Asian range"
var TT_ADR_DYNAMIC_TEXT             = "Colors the ADR box information dynamically based on the ranges. Readable using most sensible background colors. Disabling this option will make the text black or white depending on percieved brighness of the background color"
var TT_TIMEFRAME_INPUT              = "The default 1 hour should provide the most accurate projections"
var TT_WEEKDAY_OFFSET_INPUT         = "Set this to position the weekday text where you want it during the day"
var DECIMALS = int(math.log10(1/syminfo.mintick))                                   // get number of decimals of the ticker
var PIP = math.pow(10, DECIMALS-1)                                                  // get the pip position of the ticker
//END CONSTANTS}
//{ Inputs
sessionZoneInput                = input.string('GMT-5', title='New York Time Zone', tooltip=TT_SESSION_ZONE_INPUT, options=['GMT-11', 'GMT-10', 'GMT-9', 'GMT-8', 'GMT-7', 'GMT-6', 'GMT-5', 'GMT-4', 'GMT-3', 'GMT-2', 'GMT-1', 'GMT', '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="tz")
sessionZoneAutoToggleInput      = input.bool(true, "Automatic", TT_AUTO_TZ, inline="tz")

//{ ADR inputs
adrLookbackInput                = input.int(5, "ADR Lookback", 1, tooltip=TT_ADR_LOOKBACK_INPUT)
tableToggleInput                = input.bool(true, "Stats box", "", inline="table2")
tableDynamicTextInputToggle     = input.bool(true, "Dynamic Text Color", TT_ADR_DYNAMIC_TEXT, inline="table2")
tableBgInput                    = input.color(color.new(#ffffff, 5), "", inline="table")
tableLocInput                   = input.string("Top Right", "", ["Top Left", "Bottom Left", "Top Right", "Bottom Right", "Top Center", "Bottom Center"], TT_TABLE_LOC_INPUT, inline="table")
tableOrientationInput           = input.string("Vertical", "", ["Horizontal", "Vertical"], inline="table")
//}
useWicksToggleInput             = input.string("Bodies", "Range calculation source", ["Bodies", "Wicks"])
timeframeInput                  = input.timeframe("60", "Range calculation timeframe", tooltip=TT_TIMEFRAME_INPUT)
//{ CBDR Box inputs
cbdrBoxColorInput               = input.color(color.new(color.green, 85), "", group="CBDR", inline="CBDR_show")
cbdrBoxToggleInput              = input.bool(true,"Box", group="CBDR", inline="CBDR_show")
cbdrHistoryInput                = input.bool(true, "History", group="CBDR", inline="CBDR_show")
cbdrBorderColorInput            = input.color(color.green, "", group="CBDR", inline="CBDR_border")
cbdrBorderSizeInput             = input.int(1, "Border", minval=0, maxval=3, group="CBDR", inline="CBDR_border")
cbdrBorderTypeInput             = input.string("Dotted", "", options=['Solid', 'Dotted', 'Dashed'],group="CBDR", inline="CBDR_border")
cbdrLabelColorInput             = input.color(color.green, "", group="CBDR", inline="CBDR_label")
cbdrRangeToggleInput            = input.bool(true,"Pips", group="CBDR", inline="CBDR_label")
cbdrNameToggleInput             = input.bool(false,"Name", group="CBDR", inline="CBDR_label")
cbdrProjectionColorInput        = input.color(color.green, "", group="CBDR", inline="CBDR_ext")
cbdrProjectionToggleInput       = input.bool(false, "Std. Deviations", group="CBDR", inline="CBDR_ext")
cbdrProjectionHistoryInput      = input.bool(false, "History", group="CBDR", inline="CBDR_ext")
cbdrLineWidthInput              = input.int(1, "Std. dev. Line Width", minval=1, maxval=3, group="CBDR", inline="CBDR_ext2")
cbdrLineStyleInput              = input.string("Solid", "", options=['Solid', 'Dotted', 'Dashed'],group="CBDR", inline="CBDR_ext2")
//}
//{ Flout Box inputs
floutBoxColorInput              = input.color(color.rgb(76, 122, 175, 85), "", group="flout", inline="flout_show")
floutToggleInput                = input.bool(false,"Box", group="flout", inline="flout_show")
floutHistoryToggleInput         = input.bool(true, "History", group="flout", inline="flout_show")
floutBorderColorInput           = input.color(color.rgb(76, 122, 175), "", group="flout", inline="flout_border")
floutBorderSizeInput            = input.int(1, "Border", minval=0, maxval=3, group="flout", inline="flout_border")
floutBorderTypeInput            = input.string("Dotted", "", options=['Solid', 'Dotted', 'Dashed'],group="flout", inline="flout_border")
floutLabelColorInput            = input.color(color.rgb(76, 122, 175), "", group="flout", inline="flout_label")
floutRangeToggleInput           = input.bool(true,"Pips", group="flout", inline="flout_label")
floutNameToggleInput            = input.bool(false,"Name", group="flout", inline="flout_label")
floutProjectionColorInput       = input.color(color.rgb(76, 122, 175), "", group="flout", inline="floutExt")
floutProjectionToggleInput      = input.bool(false, "Std. Deviations", group="flout", inline="floutExt")
floutProjectionHistoryInput     = input.bool(false, "History", group="flout", inline="floutExt")
floutLineWidthInput             = input.int(1, "Std. dev. Line Width", minval=1, maxval=3, group="flout", inline="floutExt2")
floutLineStyleInput             = input.string("Solid", "", options=['Solid', 'Dotted', 'Dashed'],group="flout", inline="floutExt2")
//}
//{ Asia Box inputs
asiaBoxColorInput               = input.color(color.new(color.purple, 85), "", group="AR", inline="asia_show")
asiaToggleInput                 = input.bool(true,"Box", group="AR", inline="asia_show")
asiaHistoryInput                = input.bool(true, "History", group="AR", inline="asia_show")
asiaBorderColorInput            = input.color(color.purple, "", group="AR", inline="AR_border")
asiaBorderSizeInput             = input.int(1, "Border", minval=0, maxval=3,group="AR", inline="AR_border")
asiaBorderTypeInput             = input.string("Dotted", "", options=['Solid', 'Dotted', 'Dashed'],group="AR", inline="AR_border")
asiaLabelColorInput             = input.color(color.purple, "", group="AR", inline="asia_label")
asiaRangeToggleInput            = input.bool(true,"Pips", group="AR", inline="asia_label")
asiaNameToggleInput             = input.bool(false,"Name", group="AR", inline="asia_label")
asiaProjectionColorInput        = input.color(color.purple, "", group="AR", inline="asiaExt")
asiaProjectionToggle            = input.bool(false, "Std. Deviations", group="AR", inline="asiaExt")
asiaProjectionHistoryInput      = input.bool(false, "History", group="AR", inline="asiaExt")
asiaLineWidthInput              = input.int(1, "Std. dev. Line Width", minval=1, maxval=3, group="AR", inline="asiaExt2")
asiaLineStyleInput              = input.string("Solid", "", options=['Solid', 'Dotted', 'Dashed'],group="AR", inline="asiaExt2")
//END Asia Box inputs}
//{ Trueday inputs
levelLabelsShortFormatInput     = input.bool(false, "Short format Name Labels", group="Levels and Lines", inline="trueDay3")
staticLabelColorInput           = input.bool(false, "Colored", group="Levels and Lines", inline="trueDay3")
truedayColorInput               = input.color(color.new(#838383, 18), "", group="Levels and Lines", inline="trueDay")
truedayToggleInput              = input.bool(true,"True Day", group="Levels and Lines", inline="trueDay")
sundayLineToggleInput           = input.bool(true,"Sunday Line", group="Levels and Lines", inline="trueDay")
truedayHistoryToggleInput       = input.bool(true, "History", group="Levels and Lines", inline="trueDay")
truedayWidthInput               = input.int(1, "", 1, 3, group="Levels and Lines", inline="trueDay2")
truedayLineStyleInput           = input.string("Dashed", "", options=['Solid', 'Dotted', 'Dashed'],group="Levels and Lines", inline="trueDay2")

midnightColorInput              = input.color(color.new(#ffcb3b, 5), "", group="Levels and Lines", inline="midnight")
midnightToggleInput             = input.bool(true,"Midnight", group="Levels and Lines", inline="midnight")
midnightHistoryToggleInput      = input.bool(true, "History", group="Levels and Lines", inline="midnight")
midnightLabelToggleInput        = input.bool(false, "Name", group="Levels and Lines", inline="midnight")
midnightWidthInput              = input.int(2, "", 1, 3, group="Levels and Lines", inline="midnight2")
midnightLineStyleInput          = input.string("Solid", "", options=['Solid', 'Dotted', 'Dashed'],group="Levels and Lines", inline="midnight2")

dailyOpenColorInput             = input.color(color.new(#e75845, 5), "", group="Levels and Lines", inline="daily")
dailyOpenToggleInput            = input.bool(false,"Daily Open", inline="daily", group="Levels and Lines")
dailyOpenHistoryToggleInput     = input.bool(true, "History", group="Levels and Lines", inline="daily")
dailyOpenLabelToggleInput       = input.bool(false, "Name", group="Levels and Lines", inline="daily")
dailyOpenWidthInput             = input.int(2, "", 1, 3, group="Levels and Lines", inline="daily2")
dailyOpenLineStyleInput         = input.string("Solid", "", options=['Solid', 'Dotted', 'Dashed'],group="Levels and Lines", inline="daily2")


gmtOpenColorInput               = input.color(color.new(#45c1e7, 5), "", group="Levels and Lines", inline="gmt")
gmtOpenToggleInput              = input.bool(false,"GMT Midnight", group="Levels and Lines", inline="gmt")
gmtOpenHistoryToggleInput       = input.bool(true, "History", group="Levels and Lines", inline="gmt")
gmtOpenLabelToggleInput         = input.bool(false, "Name", group="Levels and Lines", inline="gmt")
gmtOpenWidthInput               = input.int(2, "", 1, 3, group="Levels and Lines", inline="gmt2")
gmtOpenLineStyleInput           = input.string("Solid", "", options=['Solid', 'Dotted', 'Dashed'],group="Levels and Lines", inline="gmt2")

fourOpenColorInput               = input.color(color.new(#3c49ff, 5), "", group="Levels and Lines", inline="four")
fourOpenToggleInput              = input.bool(false,"4am ", group="Levels and Lines", inline="four")
fourOpenHistoryToggleInput       = input.bool(true, "History", group="Levels and Lines", inline="four")
fourOpenLabelToggleInput         = input.bool(false, "Name", group="Levels and Lines", inline="four")
fourOpenWidthInput               = input.int(2, "", 1, 3, group="Levels and Lines", inline="four2")
fourOpenLineStyleInput           = input.string("Solid", "", options=['Solid', 'Dotted', 'Dashed'],group="Levels and Lines", inline="four2")

//}
//{ HTF Levels
pdhColorInput                   = input.color(color.new(#663cff, 5), "", "Note: This is the previous true day high, not the actual chart's previous daily high", group="HTF Levels", inline="pdh")
pdhToggleInput                  = input.bool(false,"PDH ", group="HTF Levels", inline="pdh")
pdhHistoryToggleInput           = input.bool(false, "History", group="HTF Levels", inline="pdh")
pdhLabelToggleInput             = input.bool(true, "Name", group="HTF Levels", inline="pdh")
pdhWidthInput                   = input.int(2, "", 1, 3, group="HTF Levels", inline="pdh2")
pdhLineStyleInput               = input.string("Solid", "", options=['Solid', 'Dotted', 'Dashed'],group="HTF Levels", inline="pdh2")

var TT_PDL                      = "Note: This is the previous true day low, not the actual chart's previous daily low"
pdlColorInput                   = input.color(color.new(#663cff, 5), "", TT_PDL, group="HTF Levels", inline="pdl")
pdlToggleInput                  = input.bool(false,"PDL ", group="HTF Levels", inline="pdl")
pdlHistoryToggleInput           = input.bool(false, "History", group="HTF Levels", inline="pdl")
pdlLabelToggleInput             = input.bool(true, "Name", group="HTF Levels", inline="pdl")
pdlWidthInput                   = input.int(2, "", 1, 3, group="HTF Levels", inline="pdl2")
pdlLineStyleInput               = input.string("Solid", "", options=['Solid', 'Dotted', 'Dashed'],group="HTF Levels", inline="pdl2")

pmhColorInput                   = input.color(color.new(#663cff, 5), "", group="HTF Levels", inline="pmh")
pmhToggleInput                  = input.bool(false,"PMH ", group="HTF Levels", inline="pmh")
pmhHistoryToggleInput           = input.bool(false, "History", group="HTF Levels", inline="pmh")
pmhLabelToggleInput             = input.bool(true, "Name", group="HTF Levels", inline="pmh")
pmhWidthInput                   = input.int(2, "", 1, 3, group="HTF Levels", inline="pmh2")
pmhLineStyleInput               = input.string("Solid", "", options=['Solid', 'Dotted', 'Dashed'],group="HTF Levels", inline="pmh2")

pmlColorInput                   = input.color(color.new(#663cff, 5), "", group="HTF Levels", inline="pml")
pmlToggleInput                  = input.bool(false,"PML ", group="HTF Levels", inline="pml")
pmlHistoryToggleInput           = input.bool(false, "History", group="HTF Levels", inline="pml")
pmlLabelToggleInput             = input.bool(true, "Name", group="HTF Levels", inline="pml")
pmlWidthInput                   = input.int(2, "", 1, 3, group="HTF Levels", inline="pml2")
pmlLineStyleInput               = input.string("Solid", "", options=['Solid', 'Dotted', 'Dashed'],group="HTF Levels", inline="pml2")

// END HTF Levels}
//{ Killzone inputs
killzoneLineWidthInput          = input.float(2, "Size", 0.1, 20, 0.1, group="Killzones", inline="kzToggle")
killzoneToggleInput             = input.bool(true, "Killzones", group="Killzones", inline="kzToggle")
killzoneOldStyleToggleInput     = input.bool(false, "Old style", group="Killzones", inline="kzToggle", tooltip=TT_KILLZONE_OLD)
killzoneYoffsetInput            = input.int(4, "Y-offset", 1, 200 , tooltip="Higher value = closer to price", group="Killzones", inline="kzToggle2")


killzoneHistoryToggleInput      = input.bool(true, "History", group="Killzones", inline="kzToggle2")
killzoneTextToggleInput         = input.bool(true, "Text Labels", group="Killzones", inline="kzToggle2")

killzoneLondonOpenColorInput    = input.color(color.new(#515cbb, 5), "", group="Killzones", inline="kzLO")
killzoneLondonOpenSessionInput  = input.session(LONDON_OPEN_KILLZONE_SESSION, "", group="Killzones", inline="kzLO")
killzoneLondonOpenToggleInput   = input.bool(true, "London", group="Killzones", inline="kzLO")
killzoneNyColorInput            = input.color(color.new(#f3c547, 5), "", group="Killzones", inline="kzNY")
killzoneNyOpenSessionInput      = input.session(NY_OPEN_KILLZONE_SESSION, "", group="Killzones", inline="kzNY")
killzoneNyToggleInput           = input.bool(true, "New York", group="Killzones", inline="kzNY")
killzoneLondonCloseColorInput   = input.color(color.new(#515cbb, 5), "", group="Killzones", inline="kzLC")
killzoneLondonCloseSessionInput = input.session(LONDON_CLOSE_KILLZONE_SESSION, "", group="Killzones", inline="kzLC")
killzoneLondonCloseToggleInput  = input.bool(true, "London Close", group="Killzones", inline="kzLC")
killzoneAsianOpenColorInput     = input.color(color.purple, "", group="Killzones", inline="kzAO")
killzoneAsianOpenSessionInput   = input.session(ASIAN_OPEN_KILLZONE_SESSION, "", group="Killzones", inline="kzAO")
killzoneAsianOpenToggleInput    = input.bool(true, "Asian Open", group="Killzones", inline="kzAO")
killzoneNyLunchColorInput     = input.color(color.red, "", group="Killzones", inline="kzNyL")
killzoneNyLunchSessionInput   = input.session(NY_LUNCH_SESSION, "", group="Killzones", inline="kzNyL")
killzoneNyLunchToggleInput    = input.bool(false, "New York Lunch", group="Killzones", inline="kzNyL")

//}
//{ Weekday input
weekdaysColorInput              = input.color(color.gray, "", group="weekdays", inline="weekdays")
weekdaysLocationInput           = input.string("Bottom", "", ["Top", "Bottom"], group="weekdays", inline="weekdays")
weekdaysToggleInput             = input.bool(true, "Weekdays", group="weekdays", inline="weekdays")
weekdaysShortFormatToggleInput  = input.bool(false, "Short format", group="weekdays", inline="weekdays")
weekdayOffsetInput              = input.int(0, "Horizontal position offset", tooltip=TT_WEEKDAY_OFFSET_INPUT)
//END Weekday input}
//{ Session Times input
cbdrSessionInput                = input.session(CBDR_SESSION, "CBDR", group="Session Times Customization")
floutSessionInput               = input.session(FLOUT_SESSION, "Flout", group="Session Times Customization")
asiaSessionInput                = input.session(ASIA_SESSION, "Asian Range", group="Session Times Customization")
stdvNumLinesInput               = input.int(4, "Standard Deviations", 1, 10, group="Session Times Customization")

//}
//END Inputs}
//{ Functions
hours(int h, int m=0) =>
    //@function     Returns UNIX time a certain number hours from now.
    //@param h      (int) number of hours
    //@param m      (int) (optional) number of minutes
    time+(3600000*h)+(60000*m) 

stringToHour(s) =>
    //@function     Converts session input strings to integers for using with the hours() function
    //@param s      session string
    //@return       (int) hours part of the session string input parameter
    math.round(str.tonumber(str.substring(s, 0, 2)))

stringToMinutes(s) =>
    //@function     Converts session input strings to integers for using with the hours() function
    //@param s      session string
    //@return       (int) minutes part of the session string input parameter
    math.round(str.tonumber(str.substring(s, 2, 4)))

averageRange(h, l, n) =>
    //@function     Calculate the average range in pips of a number of bars 
    //@param        h = high, l = low, n = number of bars
    r = 0.0
    for i = 1 to n
        r += h[i]-l[i]
    PIP*r/n

addLines(a, x1, x2, y, c, n, s, w) =>
    //@function     Adds horizonal lines to a line array
    //@param        a = array id, x1 & x2 = x coordinates, y = y coordinate, c = color, n = number of lines
    for i=0 to n-1 
        array.push(a, line.new(x1, y, x2, y, xloc=xloc.bar_time, color=c, style=s, width=w))

delLines(a) =>
    //@function     Delete all lines in a line array
    //@param        a = line array
    if array.size(a) > 0
        for i=0 to array.size(a)-1
            line.delete(array.get(a, i))

setLineArrayY(a, y, spacing, m) =>                                         
    //@function     moves all lines in a line array and space them based on a range, starting at y, m=1 for upward spacing, -1 for downward
    //@param        a = line array, y = y coordinate to start from, spacing = distance between lines, m = upward or downward spacing (+/-1)
    for [i, l] in a
        float step=(i+1) * spacing * m
        line.set_y1(l, y+step)
        line.set_y2(l, y+step)


lineset_y(l, y) =>
    //@function     Makes a line horizontal at a location
    //@param        l = line id, y = y coordinate
    line.set_y1(l, y)
    line.set_y2(l, y) 



inSession(sessionTime, sessionTimeZone=syminfo.timezone) =>
    //@function     Checks if a session is active
    //@param        SessionTime = session start and end, sessionTimeZone = optional timezone parameter 
    not na(time(timeframe.period, sessionTime, sessionTimeZone))

 
getBrightness(color c) =>
    //@function         Calculates percieved brightness of a color
    //@param c          (color) 
    //@returns          (float) brightness of c between 0 and 255
    r = color.r(c)
    g = color.g(c)
    b = color.b(c)
    math.sqrt(r*r*0.241 + g*g*0.691 + b*b*0.068)

blackOrWhiteText(c) =>
    if getBrightness(c) > 130
        color.black
    else
        color.white

getLineStyle(s) =>
    switch(s)
        "Solid" => line.style_solid
        "Dotted" => line.style_dotted
        "Dashed" => line.style_dashed
//END Functions}

var useWicks                    = useWicksToggleInput == "Bodies" ? false : true
var sessionZone                 = sessionZoneAutoToggleInput ? "America/New_York" : sessionZoneInput
//{ CBDR vars
var cbdrHighPrice               = 0.0
var cbdrLowPrice                = 0.0
var cbdrRange                   = 0.0
var box cbdrBox                 = na
var cbdrBorderStyle             = getLineStyle(cbdrBorderTypeInput)
var label cbdrLabel             = na
var cbdrLabelText               = cbdrNameToggleInput and cbdrRangeToggleInput ? CBDR_LABEL_NAME + ": " : cbdrNameToggleInput ? CBDR_LABEL_NAME : ""
var array<line> cbdrLinesHi     = array.new<line>()
var array<line> cbdrLinesLo     = array.new<line>()
var cbdrLineStyle               = getLineStyle(cbdrLineStyleInput)
var cbdrLineWidth               = cbdrLineWidthInput
//END CBDR vars}
//{ Flout vars
var floutHighPrice              = 0.0
var floutLowPrice               = 0.0
var floutRange                  = 0.0
var box floutBox                = na
var floutBorderStyle            = getLineStyle(floutBorderTypeInput)
var label floutLabel            = na
var floutLabelText              = floutNameToggleInput and floutRangeToggleInput ? FLOUT_LABEL_NAME + ": " : floutNameToggleInput ? FLOUT_LABEL_NAME : ""
var line floutLineMid           = na
var array<line> floutLinesHi    = array.new<line>()
var array<line> floutLinesLo    = array.new<line>()
var floutLineStyle              = getLineStyle(floutLineStyleInput)
var floutLineWidth              = floutLineWidthInput
//END Flout vars}
//{ Asian vars
var asiaHighPrice               = 0.0
var asiaLowPrice                = 0.0
var asiaRange                   = 0.0
var box asiaBox                 = na
var asiaBorderStyle             = getLineStyle(asiaBorderTypeInput)
var label asiaLabel             = na
var asiaLabelText               = asiaNameToggleInput and asiaRangeToggleInput ? ASIA_LABEL_NAME + ": " : asiaNameToggleInput ? ASIA_LABEL_NAME : ""
var array<line> asiaLinesHi     = array.new<line>()
var array<line> asiaLinesLo     = array.new<line>()
var asiaLineStyle               = getLineStyle(asiaLineStyleInput)
var asiaLineWidth               = asiaLineWidthInput
//END Asian vars}
//{ Trueday vars
var killzoneHighPrice           = 0.0
var killzoneLowPrice            = 0.0
var line kzLoLine1              = na
var line kzLoLine2              = na
var line kzNYLine1              = na
var line kzNYLine2              = na
var line kzLCLine1              = na
var line kzLCLine2              = na
var line kzAOLine1              = na
var line kzAOLine2              = na
var line kzNyLLine1             = na
var line kzNyLLine2             = na

var box kzLoBox1                = na
var box kzLoBox2                = na
var box kzNyBox1                = na
var box kzNyBox2                = na
var box kzLcBox1                = na
var box kzLcBox2                = na
var box kzAoBox1                = na
var box kzAoBox2                = na
var box kzNyLBox1               = na
var box kzNyLBox2               = na

var line dailyOpenLine          = na
var line fourOpenLine           = na
var line gmtOpenLine            = na
var line midnightLine           = na
var line truedayLine            = na
var line pdhLine                = na
var line pdlLine                = na
var line pmhLine                = na
var line pmlLine                = na

var label dailyOpenLabel        = na
var label fourOpenLabel         = na
var label gmtOpenLabel          = na
var label midnightLabel         = na
var label pdhLabel              = na
var label pdlLabel              = na
var label pmhLabel              = na
var label pmlLabel              = na


var levelsLabelTextSize         = size.small

var color dailyOpenLabelColor   = dailyOpenColorInput
var color fourOpenLabelColor    = fourOpenColorInput
var color gmtOpenLabelColor     = gmtOpenColorInput
var color midnightLabelColor    = midnightColorInput
var color pdhLabelColor         = pdhColorInput
var color pdlLabelColor         = pdlColorInput
var color pmhLabelColor         = pmhColorInput
var color pmlLabelColor         = pmlColorInput

var dailyOpenStyle              = getLineStyle(dailyOpenLineStyleInput)
var fourOpenStyle               = getLineStyle(fourOpenLineStyleInput)
var gmtOpenStyle                = getLineStyle(gmtOpenLineStyleInput)
var midnightStyle               = getLineStyle(midnightLineStyleInput)
var truedayStyle                = getLineStyle(truedayLineStyleInput)
var pdhStyle                    = getLineStyle(pdhLineStyleInput)
var pdlStyle                    = getLineStyle(pdlLineStyleInput)
var pmhStyle                    = getLineStyle(pmhLineStyleInput)
var pmlStyle                    = getLineStyle(pmlLineStyleInput)

var tdHigh          = high
var tdLow           = low
var float ptdHigh   = na
var float ptdLow    = na
var int tdLowX      = na
var int tdHighX     = na
var int ptdHighX    = na
var int ptdLowX     = na

//END Trueday vars}
//{ Killzone vars
var LONDON_OPEN_KILLZONE_START      = str.substring(killzoneLondonOpenSessionInput, 0, 4)
var LONDON_OPEN_KILLZONE_END        = str.substring(killzoneLondonOpenSessionInput, 5, 9)
var NY_OPEN_KILLZONE_START          = str.substring(killzoneNyOpenSessionInput, 0, 4)
var NY_OPEN_KILLZONE_END            = str.substring(killzoneNyOpenSessionInput, 5, 9)
var LONDON_CLOSE_KILLZONE_START     = str.substring(killzoneLondonCloseSessionInput, 0, 4)
var LONDON_CLOSE_KILLZONE_END       = str.substring(killzoneLondonCloseSessionInput, 5, 9)
var ASIAN_OPEN_KILLZONE_START       = str.substring(killzoneAsianOpenSessionInput, 0, 4)
var ASIAN_OPEN_KILLZONE_END         = str.substring(killzoneAsianOpenSessionInput, 5, 9)
var ASIAN_RANGE_START               = str.substring(ASIA_SESSION, 0,4)
var NY_LUNCH_START                  = str.substring(killzoneNyLunchSessionInput, 0, 4)
var NY_LUNCH_END                  = str.substring(killzoneNyLunchSessionInput, 5, 9)
//END Killzone vars}
//{ Weekday vars 
var weekdaysLocation                = weekdaysLocationInput == "Top" ? location.top : location.bottom
var invisible                       = color.rgb(0,0,0,100)
var weekdayCondition                = weekdaysToggleInput and timeframe.isintraday and timeframe.multiplier <= 60
var weekdayOffset                   = weekdayOffsetInput/timeframe.multiplier                                                    
//END Weekday vars}
//{ Calculation Timeframe 
[tfOpen, tfClose, tfHigh, tfLow] = request.security(syminfo.tickerid, timeframeInput, [open, close, high, low], lookahead=barmerge.lookahead_on)
//[pdhigh, pdLow] = request.security(syminfo.tickerid, "D", [high[1], low[1]], lookahead=barmerge.lookahead_on)
[pmHigh, pmLow] = request.security(syminfo.tickerid, "M", [high[1], low[1]], lookahead=barmerge.lookahead_on)
//END Calculation Timeframe}
//{ Colorize static Labels
if not staticLabelColorInput
    var color c = getBrightness(chart.bg_color) >130 ? color.black : color.white
    gmtOpenLabelColor   := c
    fourOpenLabelColor  := c
    dailyOpenLabelColor := c
    midnightLabelColor  := c
    pdhLabelColor       := c
    pdlLabelColor       := c
    pmhLabelColor       := c
    pmlLabelColor       := c
//} END Colorize static Labels

//{ Session Start checks
inCbdrSession = inSession(cbdrSessionInput, sessionZone) and timeframe.isintraday
cbdrStart = inCbdrSession and not inCbdrSession[1]

inFloutSession = inSession(floutSessionInput, sessionZone) and timeframe.isintraday
floutStart = inFloutSession and not inFloutSession[1]

inasiaSession = inSession(asiaSessionInput, sessionZone) and timeframe.isintraday
asiaStart = inasiaSession and not inasiaSession[1]

intruedaySession = inSession(TRUEDAY_SESSION, sessionZone) and timeframe.isintraday
truedayStart = intruedaySession and not intruedaySession[1]

insundaySession = inSession(SUNDAY_SESSION, sessionZone) and timeframe.isintraday
sundayStart = insundaySession and not insundaySession[1]

indailyOpenSession = inSession(DAILY_OPEN_SESSION, sessionZone) and timeframe.isintraday
dailyOpenStart = indailyOpenSession and not indailyOpenSession[1]

ingmtOpenSession = inSession(GMT_OPEN_SESSION, sessionZone) and timeframe.isintraday
gmtOpenStart = ingmtOpenSession and not ingmtOpenSession[1]

infourOpenSession = inSession(FOUR_OPEN_SESSION, sessionZone) and timeframe.isintraday
fourOpenStart = infourOpenSession and not infourOpenSession[1]

inkzLOSession = inSession(killzoneLondonOpenSessionInput, sessionZone) and timeframe.isintraday
kzLOStart = inkzLOSession and not inkzLOSession[1]

inkzNySession = inSession(killzoneNyOpenSessionInput, sessionZone) and timeframe.isintraday
kzNyStart = inkzNySession and not inkzNySession[1]

inkzLcSession = inSession(killzoneLondonCloseSessionInput, sessionZone) and timeframe.isintraday
kzLcStart = inkzLcSession and not inkzLcSession[1]

inkzAoSession = inSession(killzoneAsianOpenSessionInput, sessionZone) and timeframe.isintraday
kzAoStart = inkzAoSession and not inkzAoSession[1]

inKzNyLunchSession = inSession(killzoneNyLunchSessionInput, sessionZone) and timeframe.isintraday
kzNyLunchStart = inKzNyLunchSession and not inKzNyLunchSession[1]

if cbdrStart                                                            //are we at the start of a CBDR?
    if not cbdrHistoryInput                                             //is CBDR history off?
        box.delete(cbdrBox)                                             //
        label.delete(cbdrLabel)                                         //then delete previous boxes and labels

    if not cbdrProjectionHistoryInput or not cbdrHistoryInput           //is CBDR Projection history off OR CBDR history off?
        delLines(cbdrLinesHi)                                           //
        delLines(cbdrLinesLo)                                           //then delete previous CBDR projections
    
    array.clear(cbdrLinesHi)                                            //
    array.clear(cbdrLinesLo)                                    //Clean up the CBDR Line arrays
    
    cbdrHighPrice := tfOpen                                              //
    cbdrLowPrice  := tfOpen                                                //Set the initial high and low of the CBDR
    
    cbdrRange := 0.0                                                    //
    asiaRange := 0.0                                                    //Reset the range of the CBDR and Asian Range
else if inCbdrSession                                                   //are we in the CBDR session?
    if useWicks
        cbdrHighPrice := math.max(cbdrHighPrice, tfHigh)
        cbdrLowPrice := math.min(cbdrLowPrice, tfLow)
    else
        cbdrHighPrice := math.max(cbdrHighPrice, math.max(tfOpen,tfClose))                      //   
        cbdrLowPrice  := math.min(cbdrLowPrice, math.min(tfOpen, tfClose))                        //check for new high and low
    cbdrRange := (PIP*(cbdrHighPrice-cbdrLowPrice))                     //calculate the CBDR and convert to pips
if floutStart
    if not floutHistoryToggleInput                                      //is flout history off?
        box.delete(floutBox)                                            //
        label.delete(floutLabel)                                        //then delete previous boxes and labels

    if not floutProjectionHistoryInput or not floutHistoryToggleInput   //is flout Projection history off OR flout history off?
        line.delete(floutLineMid)
        delLines(floutLinesHi)                                          //
        delLines(floutLinesLo)                                          //then delete previous flout projections
    
    array.clear(floutLinesHi)                                           //
    array.clear(floutLinesLo)                                           //Clean up the flout Line arrays

    floutHighPrice := tfOpen                                              //
    floutLowPrice  := tfOpen                                               //reset flout high and low
else if inFloutSession                                                  //are we already in the flout?
    if useWicks
        floutHighPrice := math.max(floutHighPrice, tfHigh)                    //check for new flout high
        floutLowPrice  := math.min(floutLowPrice, tfLow)                      //check for new flout low
    else
        floutHighPrice := math.max(floutHighPrice, math.max(tfOpen,tfClose))
        floutLowPrice  := math.min(floutLowPrice, math.min(tfOpen, tfClose))
    floutRange := PIP*(floutHighPrice-floutLowPrice)                    //calculate current flout range and convert to pips
if asiaStart                                                            //are we at the start of a new asian range?
    if not asiaHistoryInput                                             //is asian range history off?
        box.delete(asiaBox)                                             //
        label.delete(asiaLabel)                                         //then delete previous boxes and labels

    if not asiaProjectionHistoryInput or not asiaHistoryInput           //is asian range projection history off OR asian range history off?
        delLines(asiaLinesHi)                                           //
        delLines(asiaLinesLo)                                           //then delete previous asian range projections
    
    array.clear(asiaLinesHi)                                            //
    array.clear(asiaLinesLo)                                            //Clean up the asian Line arrays
    asiaHighPrice := tfOpen                                               //
    asiaLowPrice  := tfOpen                                                //reset asian range high and low
else if inasiaSession                                                   //are we already in the asian range?
    if useWicks
        asiaHighPrice := math.max(asiaHighPrice, tfHigh)                      //check for new asian range high
        asiaLowPrice  := math.min(asiaLowPrice, tfLow)                        //check for new asian range low
    else
        asiaHighPrice  := math.max(asiaHighPrice, math.max(tfOpen, tfClose))
        asiaLowPrice  := math.min(asiaLowPrice, math.min(tfOpen, tfClose))
    asiaRange := (PIP*(asiaHighPrice-asiaLowPrice))                     //calculate current asian range and convert to pips

if dailyOpenStart
    label.delete(pmhLabel)
    label.delete(pmlLabel)
    
    if not pmhHistoryToggleInput
        line.delete(pmhLine)
    if pmhToggleInput
        pmhLine := line.new(time, pmHigh, dayofweek(time) == 6 ? hours(72) : hours(24), pmHigh, xloc=xloc.bar_time, color=pmhColorInput, style=pmhStyle, width=pmhWidthInput)
        if pmhLabelToggleInput
            pmhLabel := label.new(dayofweek(time) == 6 ? hours(72) : hours(24), pmHigh, levelLabelsShortFormatInput ? PMH_LABEL_SHORT : PMH_LABEL_TEXT, xloc.bar_time, yloc.price, invisible, label.style_none, pmhLabelColor, levelsLabelTextSize)    
    
    if not pmlHistoryToggleInput
        line.delete(pmlLine)
    if pmlToggleInput
        pmlLine := line.new(time, pmLow, dayofweek(time) == 6 ? hours(72) : hours(24), pmLow, xloc=xloc.bar_time, color=pmlColorInput, style=pmlStyle, width=pmlWidthInput)
        if pmlLabelToggleInput
            pmlLabel := label.new(dayofweek(time) == 6 ? hours(72) : hours(24), pmLow, levelLabelsShortFormatInput ? PML_LABEL_SHORT : PML_LABEL_TEXT, xloc.bar_time, yloc.price, invisible, label.style_none, pmlLabelColor, levelsLabelTextSize)    
    
    
    if not dailyOpenHistoryToggleInput
        line.delete(dailyOpenLine)
        label.delete(dailyOpenLabel)
    if dailyOpenToggleInput
        dailyOpenLine := line.new(time, open, dayofweek(time) == 6 ? hours(72) : hours(24), open, xloc=xloc.bar_time, color=dailyOpenColorInput, style=dailyOpenStyle, width=dailyOpenWidthInput)        
        if dailyOpenLabelToggleInput
            dailyOpenLabel := label.new(dayofweek(time) == 6 ? hours(72) : hours(24), open, levelLabelsShortFormatInput ? DAILY_OPEN_LABEL_SHORT : DAILY_OPEN_LABEL_TEXT, xloc.bar_time, yloc.price, invisible, label.style_none, dailyOpenLabelColor, levelsLabelTextSize)
if fourOpenStart
    if not fourOpenHistoryToggleInput
        line.delete(fourOpenLine)
        label.delete(fourOpenLabel)
    if fourOpenToggleInput
        fourOpenLine := line.new(time, open, dayofweek(time) == 6 ? hours(72) : hours(24), open, xloc=xloc.bar_time, color=fourOpenColorInput, style=fourOpenStyle, width=fourOpenWidthInput)        
        if fourOpenLabelToggleInput
            fourOpenLabel := label.new(dayofweek(time) == 6 ? hours(72) : hours(24), open, levelLabelsShortFormatInput ? FOUR_OPEN_LABEL_SHORT : FOUR_OPEN_LABEL_TEXT, xloc.bar_time, yloc.price, invisible, label.style_none, fourOpenLabelColor, levelsLabelTextSize)            
if gmtOpenStart
    if not gmtOpenHistoryToggleInput
        line.delete(gmtOpenLine)
        label.delete(gmtOpenLabel)
    if gmtOpenToggleInput
        gmtOpenLine := line.new(time, open, dayofweek(time) == 6 ? hours(72) : hours(24), open, xloc=xloc.bar_time, color=gmtOpenColorInput, style=gmtOpenStyle, width=gmtOpenWidthInput)
        if gmtOpenLabelToggleInput
            gmtOpenLabel := label.new(dayofweek(time) == 6 ? hours(72) : hours(24), open, levelLabelsShortFormatInput ? GMT_LABEL_SHORT : GMT_LABEL_TEXT, xloc.bar_time, yloc.price, invisible, label.style_none, gmtOpenLabelColor, levelsLabelTextSize)



//{ True day Start}  
if truedayStart                                                         //New True Day
    ptdHigh         := tdHigh                                           //Save high, low and x coordinates to previous day's variables before resetting
    ptdLow          := tdLow
    tdHigh          := high                                             // reset true day high
    tdLow           := low                                              // reset true day low
    ptdHighX        := tdHighX
    ptdLowX         := tdLowX
    tdLowX          := time
    tdHighX         := time
    _s = dayofweek == dayofweek.friday ? hours(54) : hours(6)
    _h = dayofweek == dayofweek.friday ? hours(72) : hours(24)
    
    if not pdhHistoryToggleInput
        label.delete(pdhLabel)
        line.delete(pdhLine)
    if pdhToggleInput
        pdhLine := line.new(ptdHighX, ptdHigh, _h, ptdHigh, xloc=xloc.bar_time, color=pdhColorInput, style=pdhStyle, width=pdhWidthInput)
        if pdhLabelToggleInput
            pdhLabel := label.new(_h, ptdHigh, levelLabelsShortFormatInput ? PDH_LABEL_SHORT : PDH_LABEL_TEXT, xloc.bar_time, yloc.price, invisible, label.style_none, pdhLabelColor, levelsLabelTextSize)            
    if not pdlHistoryToggleInput
        label.delete(pdlLabel)
        line.delete(pdlLine)
    if pdlToggleInput
        pdlLine := line.new(ptdLowX, ptdLow, _h, ptdLow, xloc=xloc.bar_time, color=pdlColorInput, style=pdlStyle, width=pdlWidthInput)
        if pdlLabelToggleInput
            pdlLabel := label.new(_h, ptdLow, levelLabelsShortFormatInput ? PDL_LABEL_SHORT : PDL_LABEL_TEXT, xloc.bar_time, yloc.price, invisible, label.style_none, pdlLabelColor, levelsLabelTextSize)            
    
    if not midnightHistoryToggleInput       // is midnight level history off?
        line.delete(midnightLine)               // delete old midnight level lines
        label.delete(midnightLabel)             // delete old midnight level labels
    if not truedayHistoryToggleInput        // is true day vertical line history off?
        line.delete(truedayLine)                // delete old true day vertical lines
    if not killzoneHistoryToggleInput       // is killzone history off?
        if killzoneOldStyleToggleInput      // is old style killzone display on?
            line.delete(kzLoLine1)              //
            line.delete(kzLoLine2)              //
            line.delete(kzLCLine1)              //
            line.delete(kzLCLine2)              //
            line.delete(kzNYLine1)              //
            line.delete(kzNYLine2)              // then delete previous killzone lines
            line.delete(kzAOLine1)              //
            line.delete(kzAOLine2)              //
            line.delete(kzNyLLine1)             //
            line.delete(kzNyLLine2)             //
        else                                // is new style killzone boxes in use?
            box.delete(kzLoBox1)                //
            box.delete(kzLoBox2)                //
            box.delete(kzNyBox1)                //
            box.delete(kzNyBox2)                //
            box.delete(kzLcBox1)                //
            box.delete(kzLcBox2)                // then delete previous killzone boxes
            box.delete(kzAoBox1)                //
            box.delete(kzAoBox2)                //
            box.delete(kzNyLBox1)               //
            box.delete(kzNyLBox2)               //

    killzoneHighPrice := high               // reset killzone high
    killzoneLowPrice := low                 // reset killzone low
    if killzoneToggleInput                  //are killzones enabled?
        if killzoneLondonOpenToggleInput    // is london killzone enabled?
            if killzoneOldStyleToggleInput
                kzLoLine1 := line.new(hours(stringToHour(LONDON_OPEN_KILLZONE_START), stringToMinutes(LONDON_OPEN_KILLZONE_START)),
                                         killzoneHighPrice,
                                         hours(stringToHour(LONDON_OPEN_KILLZONE_END), stringToMinutes(LONDON_OPEN_KILLZONE_END)),
                                         killzoneHighPrice, xloc=xloc.bar_time, color=killzoneLondonOpenColorInput, style=line.style_solid, width=math.round(killzoneLineWidthInput))
                kzLoLine2 := line.copy(kzLoLine1)                           //draw london open killzone lines from it's start to end
            else
                kzLoBox1 := box.new(hours(stringToHour(LONDON_OPEN_KILLZONE_START), stringToMinutes(LONDON_OPEN_KILLZONE_START)),
                                       killzoneHighPrice, 
                                       hours(stringToHour(LONDON_OPEN_KILLZONE_END), stringToMinutes(LONDON_OPEN_KILLZONE_END)),
                                       killzoneHighPrice, xloc=xloc.bar_time, bgcolor=killzoneLondonOpenColorInput, border_width=0)
                kzLoBox2 := box.copy(kzLoBox1)

        if killzoneNyToggleInput                                        //is new york killzone enabled?
            if killzoneOldStyleToggleInput
                kzNYLine1 := line.new(hours(stringToHour(NY_OPEN_KILLZONE_START), stringToMinutes(NY_OPEN_KILLZONE_START)),
                                         killzoneHighPrice,
                                         hours(stringToHour(NY_OPEN_KILLZONE_END), stringToMinutes(NY_OPEN_KILLZONE_END)),
                                         killzoneHighPrice, xloc=xloc.bar_time, color=killzoneNyColorInput, style=line.style_solid, width=math.round(killzoneLineWidthInput))
                kzNYLine2 := line.copy(kzNYLine1)                           //draw new york open killzone lines from it's start to end
            else
                kzNyBox1 := box.new(hours(stringToHour(NY_OPEN_KILLZONE_START), stringToMinutes(NY_OPEN_KILLZONE_START)),
                                       killzoneHighPrice, 
                                       hours(stringToHour(NY_OPEN_KILLZONE_END), stringToMinutes(NY_OPEN_KILLZONE_END)),
                                       killzoneHighPrice, xloc=xloc.bar_time, bgcolor=killzoneNyColorInput, border_width=0)
                kzNyBox2 := box.copy(kzNyBox1)
                
        if killzoneLondonCloseToggleInput                               //is london close killzone enabled?
            if killzoneOldStyleToggleInput
                kzLCLine1 := line.new(hours(stringToHour(LONDON_CLOSE_KILLZONE_START), stringToMinutes(LONDON_CLOSE_KILLZONE_START)),
                                         killzoneHighPrice,
                                         hours(stringToHour(LONDON_CLOSE_KILLZONE_END), stringToMinutes(LONDON_CLOSE_KILLZONE_END)),
                                         killzoneHighPrice, xloc=xloc.bar_time, color=killzoneLondonCloseColorInput, style=line.style_solid, width=math.round(killzoneLineWidthInput))
                kzLCLine2 := line.copy(kzLCLine1)                           //draw london close killzone lines from it's start to end
            else
                kzLcBox1 := box.new(hours(stringToHour(LONDON_CLOSE_KILLZONE_START), stringToMinutes(LONDON_CLOSE_KILLZONE_START)),
                                       killzoneHighPrice, 
                                       hours(stringToHour(LONDON_CLOSE_KILLZONE_END), stringToMinutes(LONDON_CLOSE_KILLZONE_END)),
                                       killzoneHighPrice, xloc=xloc.bar_time, bgcolor=killzoneLondonCloseColorInput, border_width=0)
                kzLcBox2 := box.copy(kzLcBox1)

        if killzoneAsianOpenToggleInput                            //is asian killzone enabled?
            if killzoneOldStyleToggleInput
                kzAOLine1 := line.new(hours(stringToHour(ASIAN_OPEN_KILLZONE_START), stringToMinutes(ASIAN_OPEN_KILLZONE_START)),
                                         killzoneHighPrice,
                                         hours(stringToHour(ASIAN_OPEN_KILLZONE_END), stringToMinutes(ASIAN_OPEN_KILLZONE_END)),
                                         killzoneHighPrice, xloc=xloc.bar_time, color=killzoneAsianOpenColorInput, style=line.style_solid, width=math.round(killzoneLineWidthInput))
                kzAOLine2 := line.copy(kzAOLine1)                           //draw asian open killzone lines from it's start to end
            else                    
                kzAoBox1 := box.new(hours(stringToHour(ASIAN_OPEN_KILLZONE_START), stringToMinutes(ASIAN_OPEN_KILLZONE_START)),
                                       killzoneHighPrice, 
                                       hours(stringToHour(ASIAN_OPEN_KILLZONE_END), stringToMinutes(ASIAN_OPEN_KILLZONE_END)),
                                       killzoneHighPrice, xloc=xloc.bar_time, bgcolor=killzoneAsianOpenColorInput, border_width=0, text_color=blackOrWhiteText(killzoneAsianOpenColorInput))
                kzAoBox2 := box.copy(kzAoBox1)      

        if killzoneNyLunchToggleInput                            //is asian killzone enabled?
            if killzoneOldStyleToggleInput
                kzNyLLine1 := line.new(hours(stringToHour(NY_LUNCH_START), stringToMinutes(NY_LUNCH_START)),
                                         killzoneHighPrice,
                                         hours(stringToHour(NY_LUNCH_END), stringToMinutes(NY_LUNCH_END)),
                                         killzoneHighPrice, xloc=xloc.bar_time, color=killzoneNyLunchColorInput, style=line.style_solid, width=math.round(killzoneLineWidthInput))
                kzNyLLine2 := line.copy(kzNyLLine1)                          
            else                    
                kzNyLBox1 := box.new(hours(stringToHour(NY_LUNCH_START), stringToMinutes(NY_LUNCH_START)),
                                       killzoneHighPrice, 
                                       hours(stringToHour(NY_LUNCH_END), stringToMinutes(NY_LUNCH_END)),
                                       killzoneHighPrice, xloc=xloc.bar_time, bgcolor=killzoneNyLunchColorInput, border_width=0)
                kzNyLBox2 := box.copy(kzNyLBox1)      
        if killzoneTextToggleInput
            c = blackOrWhiteText(killzoneLondonOpenColorInput)
            box.set_text(kzLoBox1, "LONDON OPEN KZ")
            box.set_text(kzLoBox2, "LONDON OPEN KZ")
            box.set_text_color(kzLoBox1, c)
            box.set_text_color(kzLoBox2, c)

            c := blackOrWhiteText(killzoneNyColorInput)
            box.set_text(kzNyBox1, "NEW YORK KZ")
            box.set_text(kzNyBox2, "NEW YORK KZ")
            box.set_text_color(kzNyBox1, c)             
            box.set_text_color(kzNyBox2, c)

            c := blackOrWhiteText(killzoneLondonCloseColorInput)
            box.set_text(kzLcBox1, "LONDON CLOSE KZ")
            box.set_text_color(kzLcBox1, c )
            box.set_text(kzLcBox2, "LONDON CLOSE KZ")
            box.set_text_color(kzLcBox2, c)

            c := blackOrWhiteText(killzoneAsianOpenColorInput)
            box.set_text(kzAoBox1, "ASIAN OPEN KZ")
            box.set_text(kzAoBox2, "ASIAN OPEN KZ")
            box.set_text_color(kzAoBox1, c)
            box.set_text_color(kzAoBox2, c)
            
            c := blackOrWhiteText(killzoneNyLunchColorInput)
            box.set_text(kzNyLBox1, "NEW YORK LUNCH")
            box.set_text(kzNyLBox2, "NEW YORK LUNCH")
            box.set_text_color(kzNyLBox1, c)
            box.set_text_color(kzNyLBox2, c)


    if midnightToggleInput                  //is true day open line enabled?
        midnightLine := line.new(time, open, dayofweek(time) == 6 ? hours(72) : hours(24), open, xloc=xloc.bar_time, color=midnightColorInput, style=midnightStyle, width=midnightWidthInput)
        if midnightLabelToggleInput
            midnightLabel := label.new(dayofweek(time) == 6 ? hours(72) : hours(24), open, levelLabelsShortFormatInput ? NEW_YORK_MIDNIGHT_LABEL_SHORT : NEW_YORK_MIDNIGHT_LABEL_TEXT, xloc.bar_time, yloc.price, invisible, label.style_none, midnightLabelColor, levelsLabelTextSize)
    if truedayToggleInput                   //draw the true day vertical line if enabled
        truedayLine := line.new(time, open, time, open+1, xloc=xloc.bar_time, extend=extend.both, color=truedayColorInput, style=truedayStyle, width=truedayWidthInput)

    
//END True day start}

if high > tdHigh                            // check for new high
    tdHigh          := high                     // set new high
    tdHighX         := time                     // set new high's x position
if low < tdLow                              // check for new low
    tdLow           := low                      // set new low
    tdLowX          := time                     // set new low's x position
//{ Sunday Start    
if sundayStart
    if not truedayHistoryToggleInput
        line.delete(truedayLine)
    if sundayLineToggleInput
        truedayLine := line.new(time, open, time, open+1, xloc=xloc.bar_time, extend=extend.both, color=truedayColorInput, style=truedayStyle, width=truedayWidthInput)
//END Sunday Start}
//END Session checks}
//{ Draw stuff
if cbdrStart and cbdrBoxToggleInput        
    cbdrBox := box.new(bar_index, na, na, na, cbdrBorderColorInput, cbdrBorderSizeInput, cbdrBorderStyle, bgcolor=cbdrBoxColorInput)
    cbdrLabel := label.new(bar_index, high, "", style=label.style_none, textcolor=cbdrLabelColorInput, textalign=text.align_center)
    if cbdrProjectionToggleInput
        s = dayofweek == dayofweek.friday ? hours(54) : hours(6)
        h = dayofweek == dayofweek.friday ? hours(72) : hours(24)             
        addLines(cbdrLinesHi, s, h, open, cbdrProjectionColorInput, stdvNumLinesInput, cbdrLineStyle, cbdrLineWidth)
        addLines(cbdrLinesLo, s, h, open, cbdrProjectionColorInput, stdvNumLinesInput, cbdrLineStyle, cbdrLineWidth)

if floutStart and floutToggleInput  
    floutBox := box.new(bar_index, na, na, na, floutBorderColorInput, floutBorderSizeInput, floutBorderStyle, bgcolor=floutBoxColorInput)
    floutLabel := label.new(bar_index, high, "", xloc.bar_time, style=label.style_none, textcolor=floutLabelColorInput, textalign=text.align_center)
    if floutProjectionToggleInput
        s = dayofweek == dayofweek.friday ? hours(57) : hours(9)
        h = dayofweek == dayofweek.friday ? hours(71) : hours(23)
        floutLineMid :=line.new(s, high, h, high, xloc.bar_time, color=floutProjectionColorInput, style=line.style_dashed, width=1)
        addLines(floutLinesHi, s, h, open, floutProjectionColorInput, stdvNumLinesInput, floutLineStyle, floutLineWidth)
        addLines(floutLinesLo, s, h, open, floutProjectionColorInput, stdvNumLinesInput, floutLineStyle, floutLineWidth)
        
if asiaStart and asiaToggleInput 
    asiaBox := box.new(bar_index, na, na, na, asiaBorderColorInput, asiaBorderSizeInput, asiaBorderStyle, bgcolor=asiaBoxColorInput)
    asiaLabel := label.new(bar_index, high, "", style=label.style_none, textcolor=asiaLabelColorInput, textalign=text.align_left)
    if asiaProjectionToggle 
        s =hours(4)                                                                                                        // length of asian range session in hours
        h =hours(18)                                                                          // hours until next asian rage session
        addLines(asiaLinesHi, s, h, high, asiaProjectionColorInput, stdvNumLinesInput, asiaLineStyle, asiaLineWidth)
        addLines(asiaLinesLo, s, h, high, asiaProjectionColorInput, stdvNumLinesInput, asiaLineStyle, asiaLineWidth)
    

//END Draw stuff}
//{ Update drawn stuff that changes with price
if inCbdrSession and cbdrBoxToggleInput
    true_cbdr = cbdrHighPrice-cbdrLowPrice
    box.set_top(cbdrBox, cbdrHighPrice)
    box.set_bottom(cbdrBox, cbdrLowPrice)
    box.set_right(cbdrBox, bar_index + 1)
    label.set_text(cbdrLabel, cbdrRangeToggleInput ? cbdrLabelText + str.tostring(cbdrRange) : cbdrLabelText)
    label.set_x(cbdrLabel, bar_index)
    label.set_y(cbdrLabel, cbdrHighPrice)
    setLineArrayY(cbdrLinesHi, cbdrHighPrice, true_cbdr, 1)
    setLineArrayY(cbdrLinesLo, cbdrLowPrice, true_cbdr, -1)

if inFloutSession and floutToggleInput
    true_flout = (floutHighPrice-floutLowPrice)/2
    box.set_top(floutBox, floutHighPrice)
    box.set_bottom(floutBox, floutLowPrice)
    box.set_right(floutBox, bar_index + 1)
    label.set_text(floutLabel, floutRangeToggleInput ? floutLabelText + str.tostring(floutRange) : floutLabelText)
    label.set_x(floutLabel, hours(-1))
    label.set_y(floutLabel, floutHighPrice)
    lineset_y(floutLineMid, floutHighPrice-true_flout)
    setLineArrayY(floutLinesHi, floutHighPrice, true_flout, 1)
    setLineArrayY(floutLinesLo, floutLowPrice, true_flout, -1)

if inasiaSession and asiaToggleInput
    true_asia = asiaHighPrice-asiaLowPrice
    box.set_top(asiaBox, asiaHighPrice)
    box.set_bottom(asiaBox, asiaLowPrice)
    box.set_right(asiaBox, bar_index + 1)
    label.set_text(asiaLabel, asiaRangeToggleInput ? asiaLabelText + str.tostring(asiaRange) : asiaLabelText)
    label.set_x(asiaLabel, bar_index-1)
    label.set_y(asiaLabel, asiaHighPrice)    
    setLineArrayY(asiaLinesHi, asiaHighPrice, true_asia, 1)
    setLineArrayY(asiaLinesLo, asiaLowPrice, true_asia, -1)
//END Update drawn stuff}
//{ Killzone lines
killzoneHighPrice := math.max(killzoneHighPrice, high)
killzoneLowPrice := math.min(killzoneLowPrice, low)
scaleModifier = DECIMALS == 0 ? 10 : 1
kzUpperBoxTop       = killzoneHighPrice+(killzoneHighPrice-killzoneLowPrice)/killzoneYoffsetInput + killzoneLineWidthInput/PIP/scaleModifier
kzUpperBoxBottom    = killzoneHighPrice+(killzoneHighPrice-killzoneLowPrice)/killzoneYoffsetInput
kzLowerBoxTop       = killzoneLowPrice-(killzoneHighPrice-killzoneLowPrice)/killzoneYoffsetInput
kzLowerBoxBottom    = killzoneLowPrice-(killzoneHighPrice-killzoneLowPrice)/killzoneYoffsetInput - killzoneLineWidthInput/PIP/scaleModifier
if killzoneOldStyleToggleInput
    lineset_y(kzLoLine1, killzoneHighPrice+(killzoneHighPrice-killzoneLowPrice)/killzoneYoffsetInput)
    lineset_y(kzLoLine2, killzoneLowPrice-(killzoneHighPrice-killzoneLowPrice)/killzoneYoffsetInput)
    
    lineset_y(kzNYLine1, killzoneHighPrice+(killzoneHighPrice-killzoneLowPrice)/killzoneYoffsetInput)
    lineset_y(kzNYLine2, killzoneLowPrice-(killzoneHighPrice-killzoneLowPrice)/killzoneYoffsetInput)

    lineset_y(kzLCLine1, killzoneHighPrice+(killzoneHighPrice-killzoneLowPrice)/killzoneYoffsetInput)
    lineset_y(kzLCLine2, killzoneLowPrice-(killzoneHighPrice-killzoneLowPrice)/killzoneYoffsetInput)

    lineset_y(kzAOLine1, killzoneHighPrice+(killzoneHighPrice-killzoneLowPrice)/killzoneYoffsetInput)
    lineset_y(kzAOLine2, killzoneLowPrice-(killzoneHighPrice-killzoneLowPrice)/killzoneYoffsetInput)

    lineset_y(kzNyLLine1, killzoneHighPrice+(killzoneHighPrice-killzoneLowPrice)/killzoneYoffsetInput)
    lineset_y(kzNyLLine2, killzoneLowPrice-(killzoneHighPrice-killzoneLowPrice)/killzoneYoffsetInput)

else 
    box.set_top(kzLoBox1, kzUpperBoxTop)
    box.set_bottom(kzLoBox1, kzUpperBoxBottom)
    box.set_top(kzLoBox2, kzLowerBoxTop)
    box.set_bottom(kzLoBox2, kzLowerBoxBottom)

    box.set_top(kzNyBox1, kzUpperBoxTop)
    box.set_bottom(kzNyBox1, kzUpperBoxBottom)
    box.set_top(kzNyBox2, kzLowerBoxTop)
    box.set_bottom(kzNyBox2, kzLowerBoxBottom)

    box.set_top(kzLcBox1, kzUpperBoxTop)
    box.set_bottom(kzLcBox1, kzUpperBoxBottom)
    box.set_top(kzLcBox2, kzLowerBoxTop)
    box.set_bottom(kzLcBox2, kzLowerBoxBottom)

    box.set_top(kzAoBox1, kzUpperBoxTop)
    box.set_bottom(kzAoBox1, kzUpperBoxBottom)
    box.set_top(kzAoBox2, kzLowerBoxTop)
    box.set_bottom(kzAoBox2, kzLowerBoxBottom)

    box.set_top(kzNyLBox1, kzUpperBoxTop)
    box.set_bottom(kzNyLBox1, kzUpperBoxBottom)
    box.set_top(kzNyLBox2, kzLowerBoxTop)
    box.set_bottom(kzNyLBox2, kzLowerBoxBottom)



//END Killzone lines}
//{ ADR Table
averageDailyRangeRounded = math.round(request.security(syminfo.tickerid, "1D", averageRange(high, low, adrLookbackInput)),1)                            //set average daily range for the past 'adrLookbackInput' number of days and round it
[currentDailyLow, currentDailyHigh] = request.security(syminfo.tickerid, "1D", [low, high])                                                             //get current daily high and low
currentDailyRangeRounded = math.round(PIP*(currentDailyHigh-currentDailyLow),1)                                                                         //set current daily range and round it

if tableToggleInput
    tablePosition                   = tableLocInput == "Top Left" ? position.top_left : tableLocInput == "Bottom Left" ? position.bottom_left : tableLocInput == "Top Right" ? position.top_right : tableLocInput == "Top Center" ? position.top_center : tableLocInput == "Bottom Center" ? position.bottom_center : position.bottom_right
    adrTable                        = table.new(tablePosition, tableOrientationInput == "Vertical" ? 2 : 4, tableOrientationInput == "Vertical" ? 4 : 1, tableBgInput, border_width = 1)
    bgBrightness                    = getBrightness(tableBgInput)
    //color staticTextColor           = bgBrightness > 130 ? color.black : color.white
    color staticTextColor           = blackOrWhiteText(tableBgInput)
    color dynamicGreen              = staticTextColor
    color dynamicRed                = staticTextColor
    color dynamicOrange             = staticTextColor
    color currentDailyRangeColor    = staticTextColor

    if tableDynamicTextInputToggle
        dynamicGreen                := bgBrightness > 130 ? color.green : color.rgb(0, 255, 0)
        dynamicRed                  := bgBrightness > 130 ? color.rgb(155, 0, 0) : color.rgb(255, 0, 0)
        dynamicOrange               := bgBrightness > 130 ? color.rgb(255, 152, 0) : color.rgb(255, 200, 0)
        currentDailyRangeColor      := currentDailyRangeRounded/averageDailyRangeRounded < 0.5 ? dynamicGreen : currentDailyRangeRounded/averageDailyRangeRounded < 1.0 ? dynamicOrange : dynamicRed
       
    if tableOrientationInput == "Vertical" and barstate.islast 
        table.cell(adrTable, 0, 0, str.tostring(adrLookbackInput) + "ADR:", text_color=staticTextColor, text_halign = text.align_right, text_size=size.small)
        table.cell(adrTable, 1, 0, str.tostring(averageDailyRangeRounded), text_color=staticTextColor, text_halign = text.align_left, text_size=size.small)
        table.cell(adrTable, 0, 1, "CDR:", text_color=currentDailyRangeColor, text_halign = text.align_right, text_size=size.small)
        table.cell(adrTable, 1, 1, str.tostring(currentDailyRangeRounded), text_color=currentDailyRangeColor, text_halign = text.align_left, text_size=size.small)
        table.cell(adrTable, 0, 2, "CBDR:", text_color=cbdrRange <= 40 ? dynamicGreen : dynamicRed, text_halign = text.align_right, text_size=size.small)
        table.cell(adrTable, 1, 2, str.tostring(cbdrRange), text_color=cbdrRange <= 40 ? dynamicGreen : dynamicRed, text_halign = text.align_left, text_size=size.small)
        table.cell(adrTable, 0, 3, "AR:", text_color=asiaRange <= 40 ? dynamicGreen : dynamicRed, text_halign = text.align_right, text_size=size.small)
        table.cell(adrTable, 1, 3, asiaRange == 0.0 ? "n/a" : str.tostring(asiaRange), text_color=asiaRange <= 40 ? dynamicGreen : dynamicRed, text_halign = text.align_left, text_size=size.small)
    else if barstate.islast
        table.cell(adrTable, 0, 0, str.tostring(adrLookbackInput) + "ADR: " + str.tostring(averageDailyRangeRounded), text_color=staticTextColor, text_halign = text.align_right, text_size=size.small)
        table.cell(adrTable, 1, 0, "CDR: " + str.tostring(currentDailyRangeRounded), text_color=currentDailyRangeColor, text_halign = text.align_right, text_size=size.small)
        table.cell(adrTable, 2, 0, "CBDR: " + str.tostring(cbdrRange), text_color=cbdrRange <= 40 ? dynamicGreen : dynamicRed, text_halign = text.align_right, text_size=size.small)  
        table.cell(adrTable, 3, 0, "AR: " + (asiaRange == 0.0 ? "n/a" : str.tostring(asiaRange)), text_color=asiaRange <= 40 ? dynamicGreen : dynamicRed, text_halign = text.align_right, text_size=size.small)
//END ADR Table }
//{ Plot Weekdays 

weekdaysShortFormat = weekdayCondition and weekdaysShortFormatToggleInput
plotshape(weekdaysShortFormat and hour == 12 and minute == 0 and dayofweek == dayofweek.monday, "", color=invisible, textcolor=weekdaysColorInput, location=weekdaysLocation, text="Mon", offset=weekdayOffset)
plotshape(weekdaysShortFormat and hour == 12 and minute == 0 and dayofweek == dayofweek.tuesday, "", color=invisible, textcolor=weekdaysColorInput, location=weekdaysLocation, text="Tue", offset=weekdayOffset)
plotshape(weekdaysShortFormat and hour == 12 and minute == 0 and dayofweek == dayofweek.wednesday, "", color=invisible, textcolor=weekdaysColorInput, location=weekdaysLocation, text="Wed", offset=weekdayOffset)
plotshape(weekdaysShortFormat and hour == 12 and minute == 0 and dayofweek == dayofweek.thursday, "", color=invisible, textcolor=weekdaysColorInput, location=weekdaysLocation, text="Thu", offset=weekdayOffset)
plotshape(weekdaysShortFormat and hour == 12 and minute == 0 and dayofweek == dayofweek.friday, "", color=invisible, textcolor=weekdaysColorInput, location=weekdaysLocation, text="Fri/Sun", offset=weekdayOffset)
plotshape(weekdaysShortFormat and hour == 19 and minute == 30 and dayofweek == dayofweek.sunday, "", color=invisible, textcolor=weekdaysColorInput, location=weekdaysLocation, text="Sun", offset=weekdayOffset)

weekdaysLongFormat = weekdayCondition and not weekdaysShortFormatToggleInput
plotshape(weekdaysLongFormat and hour == 12 and minute == 0 and dayofweek == dayofweek.monday, "", color=invisible, textcolor=weekdaysColorInput, location=weekdaysLocation, text="Monday", offset=weekdayOffset)
plotshape(weekdaysLongFormat and hour == 12 and minute == 0 and dayofweek == dayofweek.tuesday, "", color=invisible, textcolor=weekdaysColorInput, location=weekdaysLocation, text="Tuesday", offset=weekdayOffset)
plotshape(weekdaysLongFormat and hour == 12 and minute == 0 and dayofweek == dayofweek.wednesday, "", color=invisible, textcolor=weekdaysColorInput, location=weekdaysLocation, text="Wednesday", offset=weekdayOffset)
plotshape(weekdaysLongFormat and hour == 12 and minute == 0 and dayofweek == dayofweek.thursday, "", color=invisible, textcolor=weekdaysColorInput, location=weekdaysLocation, text="Thursday", offset=weekdayOffset)
plotshape(weekdaysLongFormat and hour == 12 and minute == 0 and dayofweek == dayofweek.friday, "", color=invisible, textcolor=weekdaysColorInput, location=weekdaysLocation, text="Friday/Sunday", offset=weekdayOffset)

// END Plot Weekdays }
//{ DEBUGGING
//debugTable = table.new(position.bottom_center, 1, 1, tableBgInput, border_width = 1)
//debugText = str.tostring(killzoneLineWidthInput/PIP) + " pip:" + str.tostring(PIP) + " dec: " + str.tostring(DECIMALS)
//table.cell(debugTable, 0, 0, debugText, text_halign = text.align_left)
//}
