Previous Levels With Custom TimeZone
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © LudoGH68

//@version=5
indicator("Previous Levels", overlay = true)
import LudoGH68/SessionAndTimeFct_public/1 as sat
import LudoGH68/Drawings_public/1 as d

getLineStyle(lineOption) =>
    lineOption == "┈" ? line.style_dotted : lineOption == "╌" ? line.style_dashed : line.style_solid

// Select Timezone to get data
timeZone = input.string("GMT-5", title="Time Zone", options=["GMT-10", "GMT-9", "GMT-8", "GMT-7", "GMT-6", "GMT-5", "GMT-4", "GMT-3", "GMT-2", "GMT-1", "GMT-0", "GMT+1", "GMT+2", "GMT+3", "GMT+4", "GMT+5", "GMT+6", "GMT+7", "GMT+8", "GMT+9", "GMT+10"], group="Time Zone")

// Daily Open
isDailyOpenToShow =  input(true, title='Display line', group="Daily Open")
isDailyOpenLabelToShow = input(true, title='Display label', group="Daily Open")
dailyOpenColor = input(color.lime, 'Color', group="Daily Open")
dailyOpenLineStyleOption = input.string("─", title="Style", group="Daily Open", options=["─", "┈", "╌"])
dailyOpenLineStyle = getLineStyle(dailyOpenLineStyleOption)
dailyOpenLineWidth = input.int(1, title="Width", group="Daily Open", minval=1, maxval=5)

// Daily High & Low
isDhlToShow =  input(true, title='Display line', group="Daily High & Low")
isDhlLabelToShow = input(true, title='Display label', group="Daily High & Low")
dhlColor = input(color.lime, 'Color', group="Daily High & Low")
dhlLineStyleOption = input.string("─", title="Style", group="Daily High & Low", options=["─", "┈", "╌"])
dhlLineStyle = getLineStyle(dhlLineStyleOption)
dhlLineWidth = input.int(1, title="Width", group="Daily High & Low", minval=1, maxval=5)

// Previous Daily High & Low
isPdhlToShow =  input(true, title='Display lines', group="Previous Daily High & Low") 
isPdhlLabelToShow = input(true, title='Display labels', group="Previous Daily High & Low")
pdhlColor = input(color.orange, 'Color', group="Previous Daily High & Low")
pdhlLineStyleOption = input.string("╌", title="Style", group="Previous Daily High & Low", options=["─", "┈", "╌"])
pdhlLineStyle = getLineStyle(pdhlLineStyleOption)
pdhlLineWidth = input.int(1, title="Width", group="Previous Daily High & Low", minval=1, maxval=5)

// Previous Weekly High & Low
isPwhlToShow =  input(true, title='Display lines', group="Previous Weekly High & Low")
isPwhlLabelToShow = input(true, title='Display labels', group="Previous Weekly High & Low")
pwhlColor = input(color.red, 'Color', group="Previous Weekly High & Low")
pwhlLineStyleOption = input.string("╌", title="Style", group="Previous Weekly High & Low", options=["─", "┈", "╌"])
pwhlLineStyle = getLineStyle(pwhlLineStyleOption)
pwhlLineWidth = input.int(1, title="Width", group="Previous Weekly High & Low", minval=1, maxval=5)

// Previous Monthly High & Low
isPmhlToShow =  input(true, title='Display lines', group="Previous Monthly High & Low")
isPmhlLabelToShow = input(true, title='Display labels', group="Previous Monthly High & Low")
pmhlColor = input(color.green, 'Color', group="Previous Monthly High & Low")
pmhlLineStyleOption = input.string("╌", title="Style", group="Previous Monthly High & Low", options=["─", "┈", "╌"])
pmhlLineStyle = getLineStyle(pmhlLineStyleOption)
pmhlLineWidth = input.int(1, title="Width", group="Previous Monthly High & Low", minval=1, maxval=5)

// Price variable
var float pmh = 0.0
var float pml = 0.0
var float pwh = 0.0
var float pwl = 0.0
var float pdh = 0.0
var float pdl = 0.0
var float monthlyHigh = 0.0
var float monthlyLow = 0.0
var float weeklyHigh = 0.0
var float weeklyLow = 0.0
var float dailyHigh = 0.0
var float dailyLow = 0.0
var float dailyOpen = 0.0

// Index variable
var int pmhIndex = 0
var int pmlIndex = 0
var int pwhIndex = 0
var int pwlIndex = 0
var int pdhIndex = 0
var int pdlIndex = 0
var int monthlyHighIndex = 0
var int monthlyLowIndex = 0
var int weeklyHighIndex = 0
var int weeklyLowIndex = 0
var int dailyHighIndex = 0
var int dailyLowIndex = 0
var int dailyOpenIndex = 0

// Line variable
var line pmhLine = na
var line pmlLine = na
var line pwhLine = na
var line pwlLine = na
var line pdhLine = na
var line pdlLine = na
var line dailyHighLine = na
var line dailyLowLine = na
var line dailyOpenLine = na

// Label variable
var label pmhLabel = na
var label pmlLabel = na
var label pwhLabel = na
var label pwlLabel = na
var label pdhLabel = na
var label pdlLabel = na
var label dailyHighLabel = na
var label dailyLowLabel = na
var label dailyOpenLabel = na

// MONTHLY PROCESS
if(sat.is_new_month(timeZone) and sat.is_element_to_show_with_tf_up('m', 3) and sat.is_element_to_show_with_tf_down('M', 1))

    // Remove previous PMH/PMH lines
    d.delete_line(pmlLine, pmlLabel)
    d.delete_line(pmhLine, pmhLabel)

    // Update price and index data
    pmh       := monthlyHigh
    pml       := monthlyLow
    pmhIndex  := monthlyHighIndex
    pmlIndex  := monthlyLowIndex
    monthlyHigh := high
    monthlyLow  := low
    monthlyHighIndex := bar_index
    monthlyLowIndex := bar_index

    // Create new lines
    pmhLine  := isPmhlToShow ? line.new(pmhIndex, pmh, bar_index, pmh, xloc=xloc.bar_index, extend=extend.right, color=pmhlColor, style=pmhlLineStyle, width=pmhlLineWidth) : na
    pmlLine  := isPmhlToShow ? line.new(pmlIndex, pml, bar_index, pml, xloc=xloc.bar_index, extend=extend.right, color=pmhlColor, style=pmhlLineStyle, width=pmhlLineWidth) : na
    pmhLabel := isPmhlToShow and isPmhlLabelToShow ? label.new(bar_index + 20, pmh, text="PMH", style=label.style_none, textcolor=pmhlColor) : na
    pmlLabel := isPmhlToShow and isPmhlLabelToShow ? label.new(bar_index + 20, pml, text="PML", style=label.style_none, textcolor=pmhlColor) : na
else

    // Update highest / lowest daily price if necessary
    if(high > monthlyHigh)
        monthlyHigh := high
        monthlyHighIndex := bar_index
    else if(low < monthlyLow)
        monthlyLow  := low
        monthlyLowIndex := bar_index

    // Update labels position
    d.update_label_coordinates(pmhLabel, pmh)
    d.update_label_coordinates(pmlLabel, pml)


// WEEKLY PROCESS
if(sat.is_new_week(timeZone) and sat.is_element_to_show_with_tf_up('m', 1) and sat.is_element_to_show_with_tf_down('W', 1))

    // Remove previous PDH/PDH lines
    d.delete_line(pwlLine, pwlLabel)
    d.delete_line(pwhLine, pwhLabel)

    // Update price and index data
    pwh       := weeklyHigh
    pwl       := weeklyLow
    pwhIndex  := weeklyHighIndex
    pwlIndex  := weeklyLowIndex
    weeklyHigh := high
    weeklyLow  := low
    weeklyHighIndex := bar_index
    weeklyLowIndex := bar_index

    // Create new lines
    pwhLine := isPwhlToShow ? line.new(pwhIndex, pwh, bar_index, pwh, xloc=xloc.bar_index, extend=extend.right, color=pwhlColor, style=pwhlLineStyle, width=pwhlLineWidth) : na
    pwlLine := isPwhlToShow ? line.new(pwlIndex, pwl, bar_index, pwl, xloc=xloc.bar_index, extend=extend.right, color=pwhlColor, style=pwhlLineStyle, width=pwhlLineWidth) : na
        
    // Create labels
    pwhLabel := isPwhlToShow and isPwhlLabelToShow ? label.new(bar_index + 20, pwh, text="PWH", style=label.style_none, textcolor=pwhlColor) : na
    pwlLabel := isPwhlToShow and isPwhlLabelToShow ? label.new(bar_index + 20, pwl, text="PWL", style=label.style_none, textcolor=pwhlColor) : na
else

    // Update highest / lowest daily price if necessary
    if(high > weeklyHigh)
        weeklyHigh := high
        weeklyHighIndex := bar_index
    else if(low < weeklyLow)
        weeklyLow  := low
        weeklyLowIndex := bar_index

    d.update_label_coordinates(pwhLabel, pwh)
    d.update_label_coordinates(pwlLabel, pwl)

// DAILY PROCESS
if(sat.is_new_day(timeZone) and sat.is_element_to_show_with_tf_down('D', 1))

    // Remove previous PDH/PDH lines
    d.delete_line(pdlLine, pdlLabel)
    d.delete_line(pdhLine, pdhLabel)
    d.delete_line(dailyOpenLine, dailyOpenLabel)
    d.delete_line(dailyHighLine, dailyHighLabel)
    d.delete_line(dailyLowLine, dailyLowLabel)

    // Update price and index data
    pdh       := dailyHigh
    pdl       := dailyLow
    pdhIndex  := dailyHighIndex
    pdlIndex  := dailyLowIndex
    dailyHigh := high
    dailyLow  := low
    dailyOpen := open
    dailyHighIndex := bar_index
    dailyLowIndex  := bar_index
    dailyOpenIndex := bar_index

    // Create lines
    pdhLine       := isPdhlToShow ? line.new(pdhIndex, pdh, bar_index, pdh, xloc=xloc.bar_index, extend=extend.right, color=pdhlColor, style=pdhlLineStyle, width=pdhlLineWidth) : na
    pdlLine       := isPdhlToShow ? line.new(pdlIndex, pdl, bar_index, pdl, xloc=xloc.bar_index, extend=extend.right, color=pdhlColor, style=pdhlLineStyle, width=pdhlLineWidth) : na
    dailyOpenLine := isDailyOpenToShow ? line.new(dailyOpenIndex, dailyOpen, bar_index + 1, dailyOpen, xloc=xloc.bar_index, extend=extend.right, color=dailyOpenColor, style=dailyOpenLineStyle, width=dailyOpenLineWidth) : na
    dailyHighLine := isDhlToShow ? line.new(dailyHighIndex, dailyHigh, bar_index + 1, dailyHigh, xloc=xloc.bar_index, extend=extend.right, color=dhlColor, style=dhlLineStyle, width=dhlLineWidth) : na
    dailyLowLine  := isDhlToShow ? line.new(dailyLowIndex, dailyLow, bar_index + 1, dailyLow, xloc=xloc.bar_index, extend=extend.right, color=dhlColor, style=dhlLineStyle, width=dhlLineWidth) : na

    // Create labels
    pdhLabel       := isPdhlToShow and isPdhlLabelToShow ? label.new(bar_index + 20, pdh, text="PDH", style=label.style_none, textcolor=pdhlColor) : na
    pdlLabel       := isPdhlToShow and isPdhlLabelToShow ? label.new(bar_index + 20, pdl, text="PDL", style=label.style_none, textcolor=pdhlColor) : na
    dailyOpenLabel := isDailyOpenToShow and isDailyOpenLabelToShow ? label.new(bar_index + 20, dailyOpen, text="Daily open", style=label.style_none, textcolor=dailyOpenColor) : na
    dailyHighLabel := isDhlToShow and isDhlLabelToShow ? label.new(bar_index + 20, dailyHigh, text="Daily high", style=label.style_none, textcolor=dhlColor) : na
    dailyLowLabel  := isDhlToShow and isDhlLabelToShow ? label.new(bar_index + 20, dailyLow, text="Daily low", style=label.style_none, textcolor=dhlColor) : na
else

    // Update highest / lowest daily price if necessary
    if(high > dailyHigh)
        dailyHigh := high
        dailyHighIndex := bar_index
    else if(low < dailyLow)
        dailyLow  := low
        dailyLowIndex := bar_index

    // Update lines coordinates
    d.update_line_coordinates(dailyHighLine, dailyHighLabel, dailyHighIndex, dailyHigh, bar_index + 1, dailyHigh)
    d.update_line_coordinates(dailyLowLine, dailyLowLabel, dailyLowIndex, dailyLow, bar_index + 1, dailyLow)

    // Update labels position
    d.update_label_coordinates(pdhLabel, pdh)
    d.update_label_coordinates(pdlLabel, pdl)
    d.update_label_coordinates(dailyOpenLabel, dailyOpen)

plot(na)
