ICT Friday's Asian Range°
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © toodegrees

//@version=5
indicator("ICT Friday's Asian Range", shorttitle="Fri Asian Range°", overlay=true, max_bars_back=500, max_boxes_count=500, max_lines_count=500, max_labels_count=500)

if not(timeframe.in_seconds(timeframe.period) == timeframe.in_seconds("5") or timeframe.in_seconds(timeframe.period) == timeframe.in_seconds("15"))
    runtime.error("Go to the 5 Minute or 15 Minute Chart!")

//#region[GLOBAL]
tooUtils_lineStyle(string _style) =>
    style = switch _style
        "Dashed" => line.style_dashed
        "Dotted" => line.style_dotted
        "Solid"  => line.style_solid
    style

noColor = color.new(color.white,100)
//#endregion

//#region[USER INPUT]
showLast        =                       input.int(0                       , title="Historical Sessions" , minval=0                  , maxval=20)

arBodyBoxColor  =                     input.color(color.new(#000000, 80), title="Box"                 , group="Asian Range (Body)", inline='B')
arBodyLineColor =                     input.color(#000000               , title="Line"                , group="Asian Range (Body)", inline='B')
arBodyLineStyle = tooUtils_lineStyle(input.string("Dotted"                , title=""                    , group="Asian Range (Body)", inline='B', options=["Dotted", "Dashed", "Solid"]))
arBodyLineWidth =                       input.int(1                       , title=""                    , group="Asian Range (Body)", inline='B', minval=1)

arWickBoxColor  =                     input.color(color.new(#388e3c, 80), title="Box"                 , group="Asian Range (Wick)", inline='W')
arWickLineColor =                     input.color(#388e3c               , title="Line"                , group="Asian Range (Wick)", inline='W')
arWickLineStyle = tooUtils_lineStyle(input.string("Dotted"                , title=""                    , group="Asian Range (Wick)", inline='W', options=["Dotted", "Dashed", "Solid"]))
arWickLineWidth =                       input.int(1                       , title=""                    , group="Asian Range (Wick)", inline='W', minval=1)

arBodyAlert     =                      input.bool(false                   , title=""                    , group="Alerts"            , inline='b')
arBodyAlertLine =                    input.string("3B"                    , title="+/- Stdev"           , group="Alerts"            , inline='b', options=["1B", "2B", "3B", "4B", "5B"])

arWickAlert     =                      input.bool(false                   , title=""                    , group="Alerts"            , inline='w')
arWickAlertLine =                    input.string("3W"                    , title="+/- Stdev"           , group="Alerts"            , inline='w', options=["1W", "2W", "3W", "4W", "5W"])
//#endregion

//#region[DECLARATIONS & FUNCTION]
var asian_range = array.new_box(), var asian_stdev = array.new_line(), var asian_label = array.new_label()

var int ar_start = na            , var float ar_bodyHigh = na        , var float ar_wickHigh = na
var int ar_end   = na            , var float ar_bodyLow  = na        , var float ar_wickLow  = na

var alert_BodyUp = false         , var float alert_level_BodyUp = na
var alert_BodyDw = false         , var float alert_level_BodyDw = na
var alert_WickUp = false         , var float alert_level_WickUp = na
var alert_WickDw = false         , var float alert_level_WickDw = na

tooUtils_alertLine(string ID, string TYPE, float PRICE=na) =>
    if na(PRICE)
        if ID+TYPE == arBodyAlertLine
            ar_start+(7*86400000)
        else if ID+TYPE == arWickAlertLine
            ar_start+(7*86400000)
        else
            ar_end
    else
        if ID+TYPE == arBodyAlertLine
            PRICE
        else if ID+TYPE == arWickAlertLine
            PRICE
        else
            na
//#endregion

//#region[LOGIC]
range_time = time("1","1900-2359:5","America/New_York")
if range_time
    if not(range_time[1])
        ar_start    := time
        ar_bodyHigh := math.max(open,close)
        ar_bodyLow  := math.min(open,close)
        ar_wickHigh := high
        ar_wickLow  := low

    ar_bodyHigh := math.max(math.max(open,close), ar_bodyHigh)
    ar_bodyLow  := math.min(math.min(open,close), ar_bodyLow )
    ar_wickHigh := math.max(high, ar_wickHigh)
    ar_wickLow  := math.min(low , ar_wickLow )
//#endregion

//#region[PLOT]
else 
    if range_time[1]
        alert_BodyUp := true
        alert_BodyDw := true
        alert_WickUp := true
        alert_WickDw := true

        ar_end    := time
        body_Range = ar_bodyHigh-ar_bodyLow
        wick_Range = ar_wickHigh-ar_wickLow

        asian_range.unshift(box.new(ar_start, ar_bodyHigh, ar_end, ar_bodyLow, noColor, 0, xloc=xloc.bar_time, bgcolor=arBodyBoxColor))
        asian_range.unshift(box.new(ar_start, ar_wickHigh, ar_end, ar_wickLow, noColor, 0, xloc=xloc.bar_time, bgcolor=arWickBoxColor))     

        for i=1 to 5 by 1
            stdev_bodyUp = ar_bodyHigh+(i*body_Range)
            stdev_bodyDw =  ar_bodyLow-(i*body_Range)
            stdev_wickUp = ar_wickHigh+(i*wick_Range)
            stdev_wickDw =  ar_wickLow-(i*wick_Range)

            level_BodyUp = tooUtils_alertLine(str.tostring(i), "B", stdev_bodyUp)
            level_BodyDw = tooUtils_alertLine(str.tostring(i), "B", stdev_bodyDw)
            level_WickUp = tooUtils_alertLine(str.tostring(i), "W", stdev_wickUp)
            level_WickDw = tooUtils_alertLine(str.tostring(i), "W", stdev_wickDw)

            alert_level_BodyUp := na(level_BodyUp)?alert_level_BodyUp:level_BodyUp
            alert_level_BodyDw := na(level_BodyDw)?alert_level_BodyDw:level_BodyDw
            alert_level_WickUp := na(level_WickUp)?alert_level_WickUp:level_WickUp
            alert_level_WickDw := na(level_WickDw)?alert_level_WickDw:level_WickDw

            asian_stdev.unshift(line.new(ar_start, stdev_bodyUp, int(tooUtils_alertLine(str.tostring(i), "B")), stdev_bodyUp, color=arBodyLineColor, style=arBodyLineStyle, width=arBodyLineWidth, xloc=xloc.bar_time))
            asian_stdev.unshift(line.new(ar_start, stdev_bodyDw, int(tooUtils_alertLine(str.tostring(i), "B")), stdev_bodyDw, color=arBodyLineColor, style=arBodyLineStyle, width=arBodyLineWidth, xloc=xloc.bar_time))
            asian_stdev.unshift(line.new(ar_start, stdev_wickUp, int(tooUtils_alertLine(str.tostring(i), "W")), stdev_wickUp, color=arWickLineColor, style=arWickLineStyle, width=arWickLineWidth, xloc=xloc.bar_time))
            asian_stdev.unshift(line.new(ar_start, stdev_wickDw, int(tooUtils_alertLine(str.tostring(i), "W")), stdev_wickDw, color=arWickLineColor, style=arWickLineStyle, width=arWickLineWidth, xloc=xloc.bar_time))

            asian_label.unshift(label.new(ar_start, stdev_bodyUp, "+"+str.tostring(i)+"B", color=noColor, style=label.style_label_right, textcolor=arBodyLineColor, size=size.small, text_font_family=font.family_monospace, xloc=xloc.bar_time, tooltip=str.tostring(stdev_bodyUp)))
            asian_label.unshift(label.new(ar_start, stdev_bodyDw, "-"+str.tostring(i)+"B", color=noColor, style=label.style_label_right, textcolor=arBodyLineColor, size=size.small, text_font_family=font.family_monospace, xloc=xloc.bar_time, tooltip=str.tostring(stdev_bodyDw)))
            asian_label.unshift(label.new(ar_start, stdev_wickUp, "+"+str.tostring(i)+"W", color=noColor, style=label.style_label_right, textcolor=arWickLineColor, size=size.small, text_font_family=font.family_monospace, xloc=xloc.bar_time, tooltip=str.tostring(stdev_wickUp)))
            asian_label.unshift(label.new(ar_start, stdev_wickDw, "-"+str.tostring(i)+"W", color=noColor, style=label.style_label_right, textcolor=arWickLineColor, size=size.small, text_font_family=font.family_monospace, xloc=xloc.bar_time, tooltip=str.tostring(stdev_wickDw)))

        if asian_range.size() > (showLast+1)*2
            for i=1 to 2 by 1
                box.delete(asian_range.pop())
            for i=1 to 20 by 1
                line.delete(asian_stdev.pop())
                label.delete(asian_label.pop())
//#endregion

//#region[ALERTS]
if arBodyAlert
    if high>alert_level_BodyUp and alert_BodyUp
        alert_BodyUp := false
        alert(ticker.standard(syminfo.ticker)+" Crossing Friday's Asian Range +"+arBodyAlertLine+" Standard Deviation @ "+str.tostring(alert_level_BodyUp), alert.freq_once_per_bar)
    if low<alert_level_BodyDw and alert_BodyDw
        alert_BodyDw := false
        alert(ticker.standard(syminfo.ticker)+" Crossing Friday's Asian Range -"+arBodyAlertLine+" Standard Deviation @ "+str.tostring(alert_level_BodyDw), alert.freq_once_per_bar)
if arWickAlert
    if high>alert_level_WickUp and alert_WickUp
        alert_WickUp := false
        alert(ticker.standard(syminfo.ticker)+" Crossing Friday's Asian Range +"+arWickAlertLine+" Standard Deviation @ "+str.tostring(alert_level_WickUp), alert.freq_once_per_bar)
    if low<alert_level_WickDw and alert_WickDw
        alert_WickDw := false
        alert(ticker.standard(syminfo.ticker)+" Crossing Friday's Asian Range -"+arWickAlertLine+" Standard Deviation @ "+str.tostring(alert_level_WickDw), alert.freq_once_per_bar)
//#endregion