Breaking Bar [5ema]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// Reused some functions from "Market Sessions"(I believe made by @LeviathanCapital).
//@version=5

indicator("Breaking Bar [5ema]", overlay=true)
planA = input.bool(defval = false, title = "Highest Bar", group = "Choose the plan")
planB = input.bool(defval = true, title = "Open Bar", inline = "plan B", group = "Choose the plan")
choosemarket = input.string(defval = "Tokyo", title = "", options = ["Tokyo", "London", "New York", "Sydney"], inline = "plan B", group = "Choose the plan")
lookbackbar = input.int(defval = 100, minval = 1, title = "Look back bars", group = "Set up signal", tooltip ="The number of look back bar for finding the highest bar. It is not mean when choose plan Open market bar.")
rightbar = input.int(defval = 0, minval = 0, title = "Right bars", group = "Set up signal", tooltip = "What position of signal will appear from the open market bar (or high bar)? It is recommended set 0 for next bar if condition is satisfied.")
numberbreak = input.int(defval = 3, minval = 1, title = "Number bars break", group = "Set up signal", tooltip = "The maximum bars have price close breaked before giving signal. The first is 1, recommend set 1 to 5.")

// Session 1
TokyoTimeX     = input.session(defval="0000-0900", title="Tokyo session", group='Set up Sessions', tooltip = 'If you want to change the start/end time of the session, just make sure they are in UTC. There is no need to change the timezone of your Tradingview chart or to change the Timezone input below, because the sessions will be plotted correctly as long as the start/end time is set in UTC.')
// Session 2
LondonTimeX    = input.session(defval="0700-1600", title="London session", group='Set up Sessions', tooltip = 'If you want to change the start/end time of the session, just make sure they are in UTC. There is no need to change the timezone of your Tradingview chart or to change the Timezone input below, because the sessions will be plotted correctly as long as the start/end time is set in UTC.')
// Session 3
NewYorkTimeX   = input.session(defval="1200-2100", title="New York session", group='Set up Sessions', tooltip = 'If you want to change the start/end time of the session, just make sure they are in UTC. There is no need to change the timezone of your Tradingview chart or to change the Timezone input below, because the sessions will be plotted correctly as long as the start/end time is set in UTC.')
// Session 4
SydneyTimeX    = input.session(defval="2000-0500", title="Sydney session", group='Set up Sessions', tooltip = 'If you want to change the start/end time of the session, just make sure they are in UTC. There is no need to change the timezone of your Tradingview chart or to change the Timezone input below, because the sessions will be plotted correctly as long as the start/end time is set in UTC.')
// Sesssion Zone
SessionZone    = input.string("UTC", title="Input Timezone", group='Set up Sessions', tooltip = 'This input is defining the timezone for the session times selected above. It has nothing to do with the timezone of your chart, because the sessions will be plotted correctly even if your chart is not set to UTC.')
hideWeekends   = input.bool(true, 'Hide Weekends', group = 'Set up Sessions')

// Excluding or Including Weekends 
var TokyoTime   = hideWeekends ? TokyoTimeX+":123456" : TokyoTimeX+":1234567"
var LondonTime  = hideWeekends ? LondonTimeX+":123456" : LondonTimeX+":1234567"
var NewYorkTime = hideWeekends ? NewYorkTimeX+":123456" : NewYorkTimeX+":1234567"
var SydneyTime  = hideWeekends ? SydneyTimeX+":123456" : SydneyTimeX+":1234567"

// Session Time
InTokyo(TokyoTime, TokyoTimeZone=syminfo.timezone)       =>
    not na(time(timeframe.period, TokyoTime, SessionZone))
InLondon(LondonTime, LondonTimeZone=syminfo.timezone)    =>
    not na(time(timeframe.period, LondonTime, SessionZone))
InNewYork(NewYorkTime, NewYorkTimeZone=syminfo.timezone) =>
    not na(time(timeframe.period, NewYorkTime, SessionZone))
InSydney(SydneyTime, SydneyTimeZone=syminfo.timezone)    =>
    not na(time(timeframe.period, SydneyTime, SessionZone))

// Checking if session is active/has started
inTokyo        = InTokyo(TokyoTime, SessionZone)     and timeframe.isintraday
TokyoStart     = inTokyo   and not inTokyo[1]
inLondon       = InLondon(LondonTime, SessionZone)   and timeframe.isintraday
LondonStart    = inLondon  and not inLondon[1]
inNewYork      = InNewYork(NewYorkTime, SessionZone) and timeframe.isintraday
NewYorkStart   = inNewYork and not inNewYork[1]
inSydney       = InSydney(SydneyTime, SessionZone)   and timeframe.isintraday
SydneyStart    = inSydney  and not inSydney[1]


// Settings high, low at the beggining of the session
var HighPrice     = 0.0
var LowPrice      = 0.0

if TokyoStart and choosemarket == "Tokyo"
    HighPrice   := high
    LowPrice    := low

if LondonStart and choosemarket == "London"
    HighPrice  := high
    LowPrice   := low

if NewYorkStart and choosemarket == "New York"
    HighPrice := high
    LowPrice  := low

if SydneyStart and choosemarket == "Sydney"
    HighPrice  := high
    LowPrice   := low

var openbar = 0

if choosemarket == "Tokyo"
    openbar := ta.barssince(TokyoStart)

if choosemarket == "London"
    openbar := ta.barssince(LondonStart)

if choosemarket == "New York"
    openbar := ta.barssince(NewYorkStart)

if choosemarket == "Sydney"
    openbar := ta.barssince(SydneyStart)

// Find the highest bar
maVolume = ta.sma(volume, lookbackbar)
highVolume = volume > maVolume * 2 and volume > volume[1]
motherBar = ta.highestbars(math.abs(open-close), lookbackbar) ==0
motherBarIndex = planA ? ta.barssince(motherBar and highVolume) : planB ? openbar : na
motherBarHigh = planA ? high[motherBarIndex] : planB ? HighPrice : na
motherBarLow = planA ? low[motherBarIndex] : planB ? LowPrice : na

// Find the breaking bar
barbreakBuy = close > open and (high-close) < 0.236* (high-low) and (close - motherBarHigh) > 0.5*(close - open)
barbreakBuyIndex = ta.barssince(barbreakBuy)

barbreakSell = close < open and (close-low) < 0.236* (high-low) and (motherBarLow - close) > 0.5 * (open - close)
barbreakSellIndex = ta.barssince(barbreakSell)

// Signal condition
signalIndex = barbreakBuy ? barbreakBuyIndex : barbreakSell ? barbreakSellIndex : na
maxRange = motherBarIndex - signalIndex < lookbackbar  and motherBarIndex - signalIndex > rightbar

// Count the number of breaking bar
countBreakUp = 0
for i = signalIndex  to motherBarIndex
    if close[i] > high[motherBarIndex] or close[i] < low[motherBarIndex]
        countBreakUp := countBreakUp + 1

countBreakDown = 0
for i = signalIndex  to motherBarIndex
    if close[i] < low[motherBarIndex] or close[i] > high[motherBarIndex]
        countBreakDown := countBreakDown + 1


// Plot open market
shapeopenbar = open > close ? color.red : color.green
plotshape(planB and choosemarket == "Tokyo" and TokyoStart ? HighPrice : na , color=shapeopenbar, style=shape.circle, location=location.belowbar, title = "Tokyo", text="Tokyo")
plotshape(planB and choosemarket == "London" and LondonStart ? HighPrice : na , color=shapeopenbar, style=shape.circle, location=location.belowbar, title = "London", text="London")
plotshape(planB and choosemarket == "New York" and NewYorkStart ? HighPrice : na , color=shapeopenbar, style=shape.circle, location=location.belowbar, title = "NewYork", text="NewYork")
plotshape(planB and choosemarket == "Sydney" and  SydneyStart ? HighPrice : na , color=shapeopenbar, style=shape.circle, location=location.belowbar, title = "Sydney", text="Sydney")

// Plot signals
signalBUY = barbreakBuy and maxRange and countBreakUp <= numberbreak
signalSELL = barbreakSell and maxRange and countBreakDown <= numberbreak
plotshape(signalBUY, color=color.green, style=shape.triangleup, location=location.belowbar, title = "Shape Buy", text="BUY", textcolor = color.green)
plotshape(signalSELL, color=color.red, style=shape.triangledown, location=location.abovebar, title = "Shape Sell", text="SELL", textcolor = color.red)
plotshape(planA ? motherBar : na, color=shapeopenbar, style=shape.triangleup, location=location.belowbar, title = "High Bar", text="High")

// Draw box
if (barbreakBuy or barbreakSell) and maxRange and (countBreakUp <= numberbreak or countBreakDown <= numberbreak)
    rangesignal = box.new(left=bar_index[motherBarIndex],top=motherBarHigh,right=bar_index[signalIndex],bottom=motherBarLow, border_color= barbreakBuy ? color.new(color.green, 50) : color.new(color.red, 50),bgcolor=barbreakBuy ? color.new(color.green, 90) : color.new(color.red, 90))

// Alert
alertBUY = ""
alertSELL = ""
alertBUY := signalBUY ? syminfo.ticker + " - Time frame: " + timeframe.period + " - BUY" +  "\n" : alertBUY
alertSELL := signalSELL ? syminfo.ticker + " - Time frame: " + timeframe.period + " - SELL" + "\n" : alertSELL
if (alertBUY != "")
    alert(alertBUY + "\n" + "(Breaking Bar [5ema])", freq=alert.freq_once_per_bar_close)
if (alertSELL != "")
    alert(alertSELL + "\n" + "(Breaking Bar [5ema])", freq=alert.freq_once_per_bar_close)