ICT Session Opening FVG / Silver Bullet [MK]
// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
// © malk1903
//@version=5
indicator("Session Opening FVG / Silver Bullet [MK]", shorttitle="Opening FVG/Silver Bullet [MK]",overlay = true, max_lines_count = 500, max_boxes_count = 500)
//------------------------------------------------------------------------------
//Settings
timeZone = input.string("GMT-4", 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","GMT+1","GMT+2","GMT+3","GMT+4","GMT+5","GMT+6","GMT+7","GMT+8","GMT+9","GMT+10"], group="Timezone")
tf=input.timeframe(defval="Chart", title="Timeframe", options=["Chart", "1", "2", "3", "4", "5", "15"], tooltip="Timeframe used for FVG detection")
if tf == "Chart"
    tf := ""
i_maxtf_og             = input.int         (5, "Max Timeframe", 1, 240, tooltip="Indicator will not work on chart timeframes above this value")
disp_og                = timeframe.isintraday and timeframe.multiplier <= i_maxtf_og
t1H = input.int(16, title = 'Hour', inline="1", group="Extend Boxes")
t1m = input.int(00, title = 'Minute', inline="1", group="Extend Boxes")
ext_2last = input.bool(defval=false, title="Extend to Future Time", inline="1", group="Extend Boxes")
os_bx = input.int(3, title = 'Box Offset', minval=0, maxval=200, inline="1", group="Extend Boxes", tooltip="Extend box to right, this works if 'Extend to Future Time' is not selected")

//Session Periods. 
Ldn_Kz_2    = input.session     ('0200-0259:1234567', "LDN KZ 0200",   inline='1', group="Sessions")
Ldn_Kz_3    = input.session     ('0300-0359:1234567', "LDN KZ 0300",   inline='2', group="Sessions")
Ldn_Kz_4    = input.session     ('0400-0459:1234567', "LDN KZ 0400",   inline='3', group="Sessions")
Dead_Kz_5   = input.session     ('0500-0559:1234567', "Dead KZ 0500",   inline='4', group="Sessions")
Dead_Kz_6   = input.session     ('0600-0659:1234567', "Dead KZ 0600",   inline='5', group="Sessions")
NY_Kz_7     = input.session     ('0700-0829:1234567', "NY KZ 0700",   inline='6', group="Sessions")
NY_Kz_830   = input.session     ('0830-0929:1234567', "NY KZ 0830",   inline='7', group="Sessions")
NY_Kz_930   = input.session     ('0930-0959:1234567', "NY KZ 0930",   inline='8', group="Sessions")
NY_Kz_10    = input.session     ('1000-1059:1234567', "NY KZ 1000",   inline='9', group="Sessions")
NY_Kz_13    = input.session     ('1300-1359:1234567', "NY KZ 1300",   inline='9b', group="Sessions")
NY_Kz_14    = input.session     ('1400-1459:1234567', "NY KZ 1400",   inline='10', group="Sessions")
NY_Kz_15    = input.session     ('1500-1559:1234567', "NY KZ 1500",   inline='10b', group="Sessions")
Extra_1    = input.session     ('0100-0110:1234567', "Ex_1",   inline='11', group="Sessions")
Ex_txt1 = input.string(defval="Extra 1", title="Text", inline='11', group="Sessions")
i_Ex1 = input.bool(defval=false, title="On/Off",   inline='11', group="Sessions")
Extra_2    = input.session     ('0115-0125:1234567', "Ex_12",   inline='12', group="Sessions")
Ex_txt2 = input.string(defval="Extra 2", title="Text", inline='12', group="Sessions")
i_Ex2 = input.bool(defval=false, title="On/Off",   inline='12', group="Sessions")
Extra_3    = input.session     ('0130-0140:1234567', "Ex_3",   inline='13', group="Sessions")
Ex_txt3 = input.string(defval="Extra 3", title="Text", inline='13', group="Sessions")
i_Ex3 = input.bool(defval=false, title="On/Off",   inline='13', group="Sessions")

//Enable/Disable Session Periods
i_kx2 = input.bool(defval=false, title="On/Off",   inline='1', group="Sessions")
i_kx3 = input.bool(defval=true, title="On/Off",   inline='2', group="Sessions")
i_kx4 = input.bool(defval=false, title="On/Off",   inline='3', group="Sessions")
i_kx5 = input.bool(defval=false, title="On/Off",   inline='4', group="Sessions")
i_kx6 = input.bool(defval=false, title="On/Off",   inline='5', group="Sessions")
i_kx7 = input.bool(defval=false, title="On/Off",   inline='6', group="Sessions")
i_kx830 = input.bool(defval=true, title="On/Off",   inline='7', group="Sessions")
i_kx930 = input.bool(defval=true, title="On/Off",   inline='8', group="Sessions")
i_kx10 = input.bool(defval=true, title="On/Off",   inline='9', group="Sessions")
i_kx13 = input.bool(defval=true, title="On/Off",   inline='9b', group="Sessions")
i_kx14 = input.bool(defval=true, title="On/Off",   inline='10', group="Sessions")
i_kx15 = input.bool(defval=true, title="On/Off",   inline='10b', group="Sessions")

//Enable/Disable Session Periods
i_kx2_fo = input.bool(defval=false, title="First Only",   inline='1', group="Sessions", tooltip="Shows only first FVG in session, The first FVG in a Seesion can be used as an aid to BIAS. eg, does the 0930 opening FVG get inverted as part of a judas swing")
i_kx3_fo = input.bool(defval=false, title="First Only",   inline='2', group="Sessions")
i_kx4_fo = input.bool(defval=false, title="First Only",   inline='3', group="Sessions")
i_kx5_fo = input.bool(defval=false, title="First Only",   inline='4', group="Sessions")
i_kx6_fo = input.bool(defval=false, title="First Only",   inline='5', group="Sessions")
i_kx7_fo = input.bool(defval=false, title="First Only",   inline='6', group="Sessions")
i_kx830_fo = input.bool(defval=true, title="First Only",   inline='7', group="Sessions")
i_kx930_fo = input.bool(defval=true, title="First Only",   inline='8', group="Sessions")
i_kx10_fo = input.bool(defval=false, title="First only",   inline='9', group="Sessions")
i_kx13_fo = input.bool(defval=true, title="First Only",   inline='9b', group="Sessions")
i_kx14_fo = input.bool(defval=false, title="First Only",   inline='10', group="Sessions")
i_kx15_fo = input.bool(defval=true, title="First Only",   inline='10b', group="Sessions")

//Box Colors,Borders, Text Colors
fvgb_imb_c = input.color(defval=color.new(color.yellow,70),title="FVG Bull Box", inline="1", group="Colors + Labels")
fvgbr_imb_c = input.color(defval=color.new(color.blue,70),title="FVG Bear Box", inline="1", group="Colors + Labels")
mline = input.color(color.new(color.silver,50), 'Mid Line', inline="1", group="Colors + Labels")
txt_c = input.color(color.new(color.silver,0), 'Text', inline="1", group="Colors + Labels")
txt_on = input.bool(defval=true, title="Show Text", inline="2", group="Colors + Labels")
tf_on = input.bool(defval=true, title="Show Timeframe", tooltip="Shows timeframe chosen for FVG detection if it has been selected, If 'Chart' has been selected for FVG detection, then nothing will be displayed", inline="2", group="Colors + Labels")
fvgb_imb_cfo = input.color(defval=color.new(color.green,40),title="FVG Bull Box", inline="1", group="Colors First Only")
fvgbr_imb_cfo = input.color(defval=color.new(color.red,40),title="FVG Bear Box", inline="1", group="Colors First Only")

t1 = timestamp(timeZone, year, month, dayofmonth, t1H, t1m, 00)

txt_tf = tf == "5" ? "5m" : tf == "4" ? "4m" : tf == "3" ? "3m" : tf == "2" ? "2m" : tf == "1" ? "1m" : ""

//UDT's
type fvg
    float top
    float btm
    bool  mitigated
    bool  isnew
    bool  isbull
    line  lvl
    box   area
    string txt
 
//Method for setting fair value gaps
method set_fvg(fvg id, offset, bg_c, l_c, txt)=>
    avg = math.avg(id.top, id.btm)

    // area  = box.new(time[2], id.top, t1, id.btm, na, bgcolor = bg_c, text=txt_on and tf_on ? txt + " " + txt_tf : txt_on ? txt : tf_on ? txt_tf : na, text_color=txt_c, text_halign=text.align_right, text_size=size.normal, xloc = xloc.bar_time)
    // avg_l = line.new(time[2] - offset, avg, t1, avg, color = l_c, style = line.style_dashed, xloc = xloc.bar_time)

    area  = box.new(time[1], id.top, ext_2last ?  t1 : time + (os_bx * 1000000), id.btm, na, bgcolor = bg_c, text=txt_on and tf_on ? txt + " " + txt_tf : txt_on ? txt : tf_on ? txt_tf : na, text_color=txt_c, text_halign=text.align_right, text_size=size.normal, xloc = xloc.bar_time)
    avg_l = line.new(time[1] - offset, avg, ext_2last ?  t1 : time + (os_bx * 1000000), avg, color = l_c, style = line.style_dashed, xloc = xloc.bar_time)

    id.lvl := avg_l
    id.area := area

//Variables
var fvg sfvg = fvg.new(na, na, na, true, na)
var fvg sfvg2 = fvg.new(na, na, na, true, na)

var box area = na

// //mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
// // get higher timeframe price values
// _getHLvalues(_ticker,_tf,_high2,_high1,_high,_low2,_low1,_low,_close1,_open1) =>
//     request.security(_ticker,tf,[_high2,_high1,_high,_low2,_low1,_low,_close1,_open1],lookahead = barmerge.lookahead_on)

// //request values using chosen TF
// [_high2,_high1,_high,_low2,_low1,_low,_close1,_open1] = _getHLvalues(syminfo.tickerid,tf,high[2],high[1],high,low[2],low[1],low,close[1],open[1])
// //mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm

// Create non-repainting security function
rp_security(_symbol, tf, _src) =>
    request.security(_symbol, tf, _src[barstate.isrealtime ? 1 : 0],barmerge.gaps_on,barmerge.lookahead_on)//added the lookahead bit

// Get HTF price data
_high2 = rp_security(syminfo.tickerid, tf, high[2])
_high = rp_security(syminfo.tickerid, tf, high)
_low2 = rp_security(syminfo.tickerid, tf, low[2])
_low = rp_security(syminfo.tickerid, tf, low)
_close = rp_security(syminfo.tickerid, tf, close)
_close1 = rp_security(syminfo.tickerid, tf, close[1])
_open1 = rp_security(syminfo.tickerid, tf, open[1])

//detect bull and bear FVGs AND 
//ORIGINAL VERSION//bull_fvg = (_high2 < _low and _close > _open1 and barstate.isconfirmed) or (_low2 > _high and _close < _open1 and barstate.isconfirmed)//added the close > open so that logic waited for a close condition on newest candle
bull_fvg = (_high2 < _low) or (_low2 > _high)//added the close > open so that logic waited for a close condition on newest candle
is_bull = false
if  _close1 > _open1
    is_bull :=true

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

txt = in_session(Ldn_Kz_2) ? "0200" : in_session(Ldn_Kz_3) ? "0300" : in_session(Ldn_Kz_4) ? "0400" : in_session(Dead_Kz_5) ? "0500" : in_session(Dead_Kz_6) ? "0600" : in_session(NY_Kz_7) ? "0700" : in_session(NY_Kz_830) ? "0830" : in_session(NY_Kz_930) ? "0930" : in_session(NY_Kz_10) ? "1000" : in_session(NY_Kz_13) ? "1300" : in_session(NY_Kz_14) ? "1400" : in_session(NY_Kz_15) ? "1500" : in_session(Extra_1) ? Ex_txt1 : in_session(Extra_2) ? Ex_txt2 : in_session(Extra_3) ? Ex_txt3 : na

//New session bullish fvg
if bull_fvg and sfvg.isnew 
    sfvg := fvg.new(is_bull ? _low : _low2, is_bull ? _high2 : _high, false, false, true)
    sfvg.set_fvg(2, is_bull ? fvgb_imb_cfo : fvgbr_imb_cfo, mline, txt)

IsSessionStart(sessionTime, sessionTimeZone=syminfo.timezone) =>
    inSess = not na(time(timeframe.period, sessionTime, sessionTimeZone))
    inSess and not inSess[1]

IsLastBarSession(sessionTime, sessionTimeZone=syminfo.timezone) =>
    var int lastBarHour   = na
    var int lastBarMinute = na
    var int lastBarSecond = na
    inSess = not na(time(timeframe.period, sessionTime, sessionTimeZone))


    if not inSess and inSess[1]
        lastBarHour   := hour[1]
        lastBarMinute := minute[1]
        lastBarSecond := second[1]
    
    hour == lastBarHour and minute == lastBarMinute and second == lastBarSecond

//function for findng first FVG within sesion
firstbox(kz, i_kx)=>
    seshstart = IsSessionStart(kz,timeZone)
    seshend = IsLastBarSession(kz, timeZone)
    if seshstart and i_kx and disp_og
        sfvg.isnew := true 
    if seshend
        sfvg.isnew := false

//send to first FVG function
if i_kx2_fo and disp_og
    firstbox(Ldn_Kz_2, i_kx2)
if i_kx3_fo and disp_og
    firstbox(Ldn_Kz_3, i_kx3)
if i_kx4_fo and disp_og
    firstbox(Ldn_Kz_4, i_kx4)
if i_kx5_fo and disp_og
    firstbox(Dead_Kz_5, i_kx5)
if i_kx6_fo and disp_og
    firstbox(Dead_Kz_6, i_kx6)
if i_kx7_fo and disp_og
    firstbox(NY_Kz_7, i_kx7)
if i_kx830_fo and disp_og
    firstbox(NY_Kz_830, i_kx830)
if i_kx930_fo and disp_og
    firstbox(NY_Kz_930, i_kx930)
if i_kx10_fo and disp_og
    firstbox(NY_Kz_10, i_kx10)
if i_kx13_fo and disp_og
    firstbox(NY_Kz_13, i_kx13)
if i_kx14_fo and disp_og
    firstbox(NY_Kz_14, i_kx14)
if i_kx15_fo and disp_og
    firstbox(NY_Kz_15, i_kx15)

//function for findng all FVG within session
seshbox(kz, i_kx, txt,tf)=>
    sesh = in_session(kz)
    var box bull_fvg_bx = na
    var boxes = array.new_box()
    avg = (math.max(_low, _low2) + math.min(_high, _high2)) / 2
    
    if bull_fvg and sesh and i_kx 
        bull_fvg_bx := box.new(time[1], is_bull ? _low : _low2, ext_2last ? t1 :  time + (os_bx * 1000000), is_bull ? _high2 : _high,bgcolor = is_bull ? fvgb_imb_c : fvgbr_imb_c, border_color = color.new(color.black,100), xloc=xloc.bar_time, text_color=txt_c, text=txt_on and tf_on ? txt + " " + txt_tf : txt_on ? txt : tf_on ? txt_tf : na, text_size=size.normal, text_halign=text.align_right)
        avg_l = line.new(time[1], avg, ext_2last ?  t1 : time + (os_bx * 1000000), avg, color = mline, style = line.style_dashed, xloc = xloc.bar_time)
        array.push(boxes, bull_fvg_bx)

//send to all FVG function
if not i_kx2_fo and disp_og 
    seshbox(Ldn_Kz_2, i_kx2, "0200", tf)
if not i_kx3_fo and disp_og
    seshbox(Ldn_Kz_3, i_kx3, "0300", tf)
if not i_kx4_fo and disp_og
    seshbox(Ldn_Kz_4, i_kx4, "0400", tf)
if not i_kx5_fo and disp_og
    seshbox(Dead_Kz_5, i_kx5, "0500", tf)
if not i_kx6_fo and disp_og
    seshbox(Dead_Kz_6, i_kx6, "0600", tf)
if not i_kx7_fo and disp_og
    seshbox(NY_Kz_7, i_kx7, "0700", tf)
if not i_kx830_fo and disp_og
    seshbox(NY_Kz_830, i_kx830, "0830", tf)
if not i_kx930_fo and disp_og
    seshbox(NY_Kz_930, i_kx930, "0930", tf)
if not i_kx10_fo and disp_og
    seshbox(NY_Kz_10, i_kx10, "1000", tf)
if not i_kx13_fo and disp_og
    seshbox(NY_Kz_13, i_kx13, "1300", tf)
if not i_kx14_fo and disp_og
    seshbox(NY_Kz_14, i_kx14, "1400", tf)
if not i_kx15_fo and disp_og
    seshbox(NY_Kz_15, i_kx15, "1500", tf)
if i_Ex1 and disp_og
    seshbox(Extra_1, i_Ex1, Ex_txt1, tf)
if i_Ex2 and disp_og
    seshbox(Extra_2, i_Ex2, Ex_txt2, tf)
if i_Ex3 and disp_og
    seshbox(Extra_3, i_Ex3, Ex_txt3, tf)