Nexus Blast Trading Strategy [Kaspricci]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Kaspricci

//@version=5
indicator("Nexus Blast Trading Strategy [Kaspricci]", shorttitle = "Nexus Blast Trading", overlay = true, max_lines_count = 500, max_boxes_count = 500)

// ========================================================================================================================================================================
groupGeneral        = "General Settings"

timeZone            = input.string(group = groupGeneral, title = "Timezone", defval = "UTC-4", options = ["UTC-10", "UTC-9", "UTC-8", "UTC-7", "UTC-6", "UTC-5", "UTC-4", "UTC-3", "UTC-2", "UTC-1", "UTC", "UTC+1", "UTC+2", "UTC+3", "UTC+4", "UTC+5", "UTC+6", "UTC+7", "UTC+8", "UTC+9", "UTC+10", "UTC+11", "UTC+12"])

// ========================================================================================================================================================================
groupSessions       = "Sessions"

londonSession       = input.session(group = groupSessions, title = "London", defval = "0000-0800", tooltip = "London session 00:00 - 08:00")
amSession           = input.session(group = groupSessions, title = "NY am",  defval = "0800-1300", tooltip = "NY am session 08:00 - 13:00")
pmSession           = input.session(group = groupSessions, title = "NY pm",  defval = "1300-1900", tooltip = "NY pm session 13:00 - 19:00")
asianSession        = input.session(group = groupSessions, title = "Asian",  defval = "1900-0000", tooltip = "Asian session 19:00 - 00:00")

sessionColor        = input.color(defval = color.rgb(178, 181, 190, 50), title = "Session Line Color")
newDayColor         = input.color(defval = color.rgb(33, 149, 243, 50),  title = "New Day Line Color")

//numberOfDaysBack    = input.int(group = groupSessions, title = "Number of Days back", defval = 10, minval = 1, step = 5, maxval = 50, tooltip = "Defines the number of days for which a high and low line will be drawn")
numberOfDaysBack    = 50

inLondonSession     = not na(time("", londonSession, timeZone))
inAmSession         = not na(time("", amSession,     timeZone))
inPmSession         = not na(time("", pmSession,     timeZone))
inAsianSession      = not na(time("", asianSession,  timeZone))

isSunday            = dayofweek(time, timeZone) == dayofweek.sunday


// ========================================================================================================================================================================
bgcolor(isSunday ? color.rgb(178, 181, 190, 90) : na )

var currentHigh = high
var line currentHighLine = na
var line[] highLines = array.new_line(0, na)

var currentLow  = low
var line currentLowLine  = na
var line[] lowLines = array.new_line(0, na)

hasBuySideLiquidityTaken(line[] highLines) =>
    flag = false

    if highLines.size() > 1
        for i = 0 to highLines.size() - 2
            highLine = highLines.get(i)

            price = line.get_y1(highLine)
            lastBar = line.get_x2(highLine)

            if (bar_index > lastBar and high > price )
                highLines.remove(i)

                flag := true

                break
    
    flag

hasSellSideLiquidityTaken(line[] lowLines) =>
    flag = false

    if lowLines.size() > 1
        for i = 0 to lowLines.size() - 2
            lowLine = lowLines.get(i)

            price = line.get_y1(lowLine)
            lastBar = line.get_x2(lowLine)

            if (bar_index > lastBar and low < price )
                lowLines.remove(i)

                flag := true

                break
    
    flag

handleSession(bool inSession, line[] highLines, line[] lowLines, float maxHigh, float minLow) =>
    if ( not inSession[1] and inSession ) // start of session
        highLine = line.new(bar_index, high, bar_index + 1, high)
        lowLine  = line.new(bar_index, low,  bar_index + 1, low)

        highLines.push(highLine)
        lowLines.push(lowLine)

    if ( inSession and not isSunday ) // during session
        line.set_y1(highLines.last(), maxHigh)
        line.set_xy2(highLines.last(), bar_index, maxHigh)

        line.set_y1(lowLines.last(), minLow)
        line.set_xy2(lowLines.last(), bar_index, minLow)

    if ( highLines.size() > numberOfDaysBack * 4)
        firstLine = highLines.first()

        line.delete(firstLine)
        
        highLines.remove(0)

    if ( lowLines.size() > numberOfDaysBack * 4 )
        firstLine = lowLines.first()

        line.delete(firstLine)
        
        lowLines.remove(0)

    if highLines.size() > 1
        for i = 0 to highLines.size() - 2
            highLine = highLines.get(i)

            price = line.get_y1(highLine)
            lastBar = line.get_x2(highLine)

            if (bar_index > lastBar and high > price )
                line.set_color(highLine, color.red)
    
    if lowLines.size() > 1
        for i = 0 to lowLines.size() - 2
            lowLine = lowLines.get(i)

            price = line.get_y1(lowLine)
            lastBar = line.get_x2(lowLine)

            if (bar_index > lastBar and low < price )
                line.set_color(lowLine, color.red)


if ( inLondonSession and not isSunday )
    currentHigh := math.max(high, currentHigh)
    currentLow  := math.min(low, currentLow)

handleSession(inLondonSession, highLines, lowLines, currentHigh, currentLow)

if ( inLondonSession[1] and not inLondonSession )
    currentHigh := high
    currentLow  := low

    line.new(bar_index, high, bar_index, low, extend = extend.both, color = sessionColor)


if ( inAmSession and not isSunday)
    currentHigh := math.max(high, currentHigh)
    currentLow  := math.min(low, currentLow)

handleSession(inAmSession, highLines, lowLines, currentHigh, currentLow)

if ( inAmSession[1] and not inAmSession )
    currentHigh := high
    currentLow  := low

    line.new(bar_index, high, bar_index, low, extend = extend.both, color = sessionColor)


if ( inPmSession and not isSunday )
    currentHigh := math.max(high, currentHigh)
    currentLow  := math.min(low, currentLow)

handleSession(inPmSession, highLines, lowLines, currentHigh, currentLow)

if ( inPmSession[1] and not inPmSession and not isSunday )
    currentHigh := high
    currentLow  := low

    line.new(bar_index, high, bar_index, low, extend = extend.both, color = sessionColor)


if ( inAsianSession and not isSunday )
    currentHigh := math.max(high, currentHigh)
    currentLow  := math.min(low, currentLow)

handleSession(inAsianSession, highLines, lowLines, currentHigh, currentLow)

if ( inAsianSession[1] and not inAsianSession and not isSunday )
    currentHigh := high
    currentLow  := low


if ( ta.change(time("1D", "0000-0000:1234567", timeZone)) )
    line.new(bar_index, high, bar_index, low, extend = extend.both, color = newDayColor)


alertcondition(hasBuySideLiquidityTaken(highLines), "Buy Side Liquidity Alert", "{{timenow}} - Buy Side Liquidity Alert for {{exchange}}:{{ticker}} at price: {{close}}")

alertcondition(hasSellSideLiquidityTaken(lowLines), "Sell Side Liquidity Alert", "{{timenow}} - Sell Side Liquidity Alert for {{exchange}}:{{ticker}} at price: {{close}}")


// ========================================================================================================================================================================
groupFVG = "FVG Settings"

threshold = input.int(group = groupFVG, defval = 0, minval = 0, step = 5, title = "Threshold in Ticks", tooltip = "Hide fair value gaps (FVG) with a gap smaller then this number of ticks")

isBearishFVG = low[2]  > high + threshold * syminfo.mintick
isBullishFVG = high[2] < low  - threshold * syminfo.mintick

bullishColor = input.color(defval = color.rgb(33, 149, 243, 70), title = "Bullish FVG Color")
bearishColor = input.color(defval = color.rgb(255, 153, 0, 70),  title = "Bearish FVG Color")

if barstate.isconfirmed and isBearishFVG
    box.new(bar_index - 2, low[2], bar_index, high, border_color = color.new(bearishColor, 0), bgcolor = bearishColor)

if barstate.isconfirmed and isBullishFVG
    box.new(bar_index - 2, high[2], bar_index, low, border_color = color.new(bullishColor, 0), bgcolor = bullishColor)