Session Breakout/Sweep with alerts
//This source code is subject the terms of the Mozilla Public License  at https://mozilla.org/MPL/2.0/
// © hiimannshu

//@version=5
indicator(title='Session Breakout', shorttitle='Sess Break', overlay=true, max_boxes_count=500, max_lines_count=500)

//---------------------------------  Inputs  --------------------------------------------------------------//

show_session_box = input.bool(true, title='Show session time range box ?', group='Session Time Range')
box_infil_color = input.color(color.new(color.red, 70), 'Box Infill', inline='box_prop', group='Session Time Range')
box_border_color = input.color(color.new(color.black, 70), 'Box Border', inline='box_prop', group='Session Time Range')
sess = input.session('1800-0101',"Session Timing", group='Session Time Range',tooltip = "Add one extra minute in session end time, otherwise it won't add last candle in time range. e.g. if your session timing is '12:00 - 13:00'\nset it as '12:00 - 13:01'")
show_hl_levels = input.bool(title='Show breakout Levels?', defval=true, group='Breakout Levels')
use_close      = input.bool(title='Use close as breakout confirmation ?', defval=false, group='Breakout Levels')
br_line_color = input.color(color.new(color.red, 70), 'Breakout Line Color', group='Breakout Levels')
extend_upto = input.int(defval=5,title='Extend breakout lines (in hours) ',minval=2,maxval=10, group='Breakout Levels')
ind_style   = input.string("Fixed","Breakout indicator style",options = ["Don't show","Fixed","Moving"], group='Breakout Levels')
use_method  = input.string("Breakout", title = "Use as",options = ["Breakout","Liquidity sweep"], group='Breakout Levels')

alerts      = input.string(defval = "No alerts",title="Alerts",options = ["No alerts","On first breakout","Every Time breakout happens"],group='Alerts')

show_day = input.bool(false,"Show previos day high low?",inline="day",group = "Previous Levels")
day_col  = input.color(color.new(color.blue, 70),"",inline="day",group = "Previous Levels")

show_week = input.bool(false,"Show previos week high low?",inline="week",group = "Previous Levels")
week_col  = input.color(color.new(color.green, 70),"",inline="week",group = "Previous Levels")

//---------------------------------  Functions  --------------------------------------------------------------//

in_session(sess) =>
    not na(time(timeframe.period, sess))

start_time(sess) =>
    int startTime = na
    startTime := in_session(sess) and not in_session(sess)[1] ? time : startTime[1]
    startTime

is_new_session(res, sess) =>
    t = time(res, sess)
    na(t[1]) and not na(t) or t[1] < t


candle_count(tf, hours) =>
    float candles = na
    in_min = hours * 60
    candles := in_min / tf
    candles


//---------------------------------  Variavles  --------------------------------------------------------------/
var int count = na
var float hv = na
var float lv = na

// ---- Verify Timeframe-----//

current_tf = str.tonumber(timeframe.period)
bool valid_tf = current_tf <= 45

// ---- Candle Count-----//

candles_far = int(candle_count(current_tf, extend_upto))


// ---- Time Range High Low -----//

float sess_low = na
float sess_high = na
float confirmed_low = na
float confirmed_high = na

session_started = is_new_session('1440', sess)
inside_sess     = in_session(sess)
session_ended   = inside_sess[1] and not(inside_sess)

sess_low  := session_started ? low  : in_session(sess) ? math.min(low, sess_low[1])   : na
sess_high := session_started ? high : in_session(sess) ? math.max(high, sess_high[1]) : na

confirmed_low :=  session_ended ? math.min(low, sess_low)[1] : na
confirmed_high := session_ended ? math.max(high, sess_high)[1] : na

dayHigh = request.security(syminfo.tickerid,"D",high[1])
dayLow  = request.security(syminfo.tickerid,"D",low[1])

weekHigh = request.security(syminfo.tickerid,"W",high[1])
weekLow  = request.security(syminfo.tickerid,"W",low[1])



// ---- Lines-----//

bullish_breakout_level = line(na)
bearish_breakout_level = line(na)
bull_br = line(na)
bear_br = line(na)

day_high    = line(na)
day_low     = line(na)
week_high   = line(na)
week_low    = line(na)
month_high  = line(na)
month_low   = line(na)
// ---- Breakout Level Coordinates-----//

time_diffrence = time - time[1]

x1_val = time[1]
x2_val = time + candles_far * time_diffrence

yl_val =  confirmed_low
yh_val =  confirmed_high

// ---- Box -----//
sess_box = box(na)

// ---- Label -----//
message = label(na)


//---------------------------------  Conditions  --------------------------------------------------------------//

condition_1 = inside_sess and valid_tf
condition_2 = session_ended and valid_tf

sess_start_time = start_time(sess)

//---------------------------------  Draw box and Levels  --------------------------------------------------------------//


if condition_1
    if in_session(sess)[1]
        box.delete(sess_box[1])

    if low < sess_low
        sess_low := low
        confirmed_low := sess_low
        confirmed_low

    if high > sess_high
        sess_high := high
        confirmed_high := sess_high
        confirmed_high
    if show_session_box
        sess_box := box.new(sess_start_time, sess_high, time, sess_low, xloc=xloc.bar_time, bgcolor= box_infil_color, border_color=box_border_color, border_style=line.style_solid)
        sess_box


if barstate.islast and not valid_tf
    message := label.new(x=bar_index + 2, y=close, style=label.style_label_left, size=size.large, color=#ffeecc, textcolor=color.black, text='Shift to lower Timeframe ( < 45 min )')
    message


if condition_2
   
    if show_hl_levels
        bearish_breakout_level := line.new(x1_val, yl_val, x2_val, yl_val, xloc.bar_time, color=br_line_color)
        bullish_breakout_level := line.new(x1_val, yh_val, x2_val, yh_val, xloc.bar_time, color=br_line_color)

    if show_day
        day_high := line.new(x1_val, dayHigh, x2_val, dayHigh, xloc.bar_time, color=day_col)
        day_low  := line.new(x1_val, dayLow, x2_val, dayLow, xloc.bar_time, color=day_col)
    
    if show_week
        week_high := line.new(x1_val, weekHigh, x2_val, weekHigh, xloc.bar_time, color=week_col)
        week_low  := line.new(x1_val, weekLow, x2_val, weekLow, xloc.bar_time, color=week_col)




if not(inside_sess) and inside_sess[1]
    count:=0
    hv:= yh_val
    lv:= yl_val

crossover = use_method =="Breakout"?(use_close?close[1]>hv : ((high[1]>hv and open[1]<hv) or close[1]>hv)):(low[1]<lv and close[1]>lv)
crossunder =use_method =="Breakout"?( use_close? close[1]<lv :((low[1]<lv and open[1]>lv) or close[1]<lv)):(high[1]>hv and close[1]<hv)

if count!=0 and inside_sess
    hv:=0
    lv:=0
    count:=0

if count==0 and not(inside_sess)
    if crossover
        count:= 1
    if crossunder
        count:= 2

bullish_breakout = (count[1]==0 and count==1) and show_hl_levels and valid_tf
bearish_breakout = (count[1]==0 and count==2) and show_hl_levels and valid_tf

br_st = ind_style == "Fixed"?1:(ind_style == "Moving"?2:0)

if  bullish_breakout and br_st == 2
    bull_br:=line.new(bar_index[1], low[1], bar_index[1], high[1],extend=extend.left, color=color.green, style = line.style_dotted,width=1)
if  bearish_breakout and br_st == 2
    bull_br:=line.new(bar_index[1], low[1], bar_index[1], high[1],extend=extend.right, color=color.red, style = line.style_dotted,width=1)


plotshape(bullish_breakout and br_st==2  ,"Bullish breakout",shape.labelup,location.bottom,text="⬆️",color = color.new(color.white,100),size=size.tiny,offset = -1)
plotshape(bearish_breakout and br_st==2   ,"Bearishbreakout",shape.labeldown,location.top,text="⬇️",color = color.new(color.white,100),size=size.tiny,offset = -1)

plotshape(bullish_breakout and br_st==1  ,"Bullish breakout",shape.triangleup,location.belowbar,color = color.new(color.green,0),size=size.tiny,offset = -1)
plotshape(bearish_breakout and br_st==1   ,"Bearish breakout",shape.triangledown,location.abovebar,color = color.new(color.red,0),size=size.tiny,offset = -1)


bull_alert = alerts=="On first breakout"?bullish_breakout:(alerts=="Every Time breakout happens"?crossover:false)
bear_alert = alerts=="On first breakout"?bearish_breakout:(alerts=="Every Time breakout happens"?crossunder:false)

if bull_alert
    alert("Bullish breakout on "+str.tostring(syminfo.tickerid), alert.freq_once_per_bar)

if bear_alert
    alert("Bearish breakout on "+str.tostring(syminfo.tickerid), alert.freq_once_per_bar)
