When Candle's Wick Break ChoCh and BOS then Immediately Update Trend, Don't Wait for Future Candle to Close, Always Update Trend Based on Current Candle, Once Trend is Shown on Table, then Start Consider Future Bars as Exist Method: //@version=5
indicator(title="BoS and ChoCh Indicator", shorttitle="BoS & ChoCh Indicator", overlay=true, max_lines_count=500, max_labels_count=500)

// Input parameters
swingLookback = input.int(title="Swing Lookback Period", defval=3, minval=1, maxval=20)
showBoS = input.bool(title="Show Break of Structure (BoS)", defval=true)
showChoCh = input.bool(title="Show Change of Character (ChoCh)", defval=true)
showLabels = input.bool(title="Show Labels", defval=true)
lineExtension = input.string(title="Line Extension", defval="Right", options=["None", "Right", "Both"])
higherTF = input.timeframe(title="Higher Timeframe", defval="", tooltip="Leave empty to use current timeframe")

// Map line extension to extend parameter
extend_mode = switch lineExtension
    "None" => extend.none
    "Right" => extend.right
    "Both" => extend.both
    => extend.right

// Function to detect swings and times
f_detectSwings(_swingLookback) =>
    // Identify swing highs and lows
    swh = ta.pivothigh(high, _swingLookback, _swingLookback)
    int swhTime = na
    if not na(swh)
        swhTime := time[_swingLookback]
    swl = ta.pivotlow(low, _swingLookback, _swingLookback)
    int swlTime = na
    if not na(swl)
        swlTime := time[_swingLookback]
    [swh, swhTime, swl, swlTime]

// Variables to store swing highs and lows
var float[] swingHighs = array.new_float()
var int[] swingHighTimes = array.new_int()
var float[] swingLows = array.new_float()
var int[] swingLowTimes = array.new_int()

// Get swings from higher timeframe if specified
[swh, swhTime, swl, swlTime] = request.security(syminfo.tickerid, higherTF == "" ? timeframe.period : higherTF, f_detectSwings(swingLookback), barmerge.gaps_off, barmerge.lookahead_off)

// Update swing highs and lows arrays
if not na(swh)
    array.unshift(swingHighs, swh)
    array.unshift(swingHighTimes, swhTime)
    if array.size(swingHighs) > 10
        array.pop(swingHighs)
        array.pop(swingHighTimes)

if not na(swl)
    array.unshift(swingLows, swl)
    array.unshift(swingLowTimes, swlTime)
    if array.size(swingLows) > 10
        array.pop(swingLows)
        array.pop(swingLowTimes)

// Determine the current trend
var string trend = na
if array.size(swingHighs) >= 2 and array.size(swingLows) >= 2
    lastSwingHigh = array.get(swingHighs, 0)
    prevSwingHigh = array.get(swingHighs, 1)
    lastSwingLow = array.get(swingLows, 0)
    prevSwingLow = array.get(swingLows, 1)

    // If last swing high is higher than previous swing high and last swing low is higher than previous swing low
    if lastSwingHigh > prevSwingHigh and lastSwingLow > prevSwingLow
        trend := "Uptrend"
    // If last swing high is lower than previous swing high and last swing low is lower than previous swing low
    else if lastSwingHigh < prevSwingHigh and lastSwingLow < prevSwingLow
        trend := "Downtrend"
    else
        trend := "Sideways"

// Variables to hold BoS and ChoCh lines and labels
var line bosLine = na
var label bosLabel = na
var line chochLine = na
var label chochLabel = na

// Variables to store event times
var int bosTime = na
var int chochTime = na

// Detect BoS and ChoCh based on trend
if trend == "Uptrend"
    // Break of Structure (BoS) to the upside using High of candle
    if showBoS and high > array.get(swingHighs, 0)
        bosTime := time
        // Delete previous BoS line and label
        if not na(bosLine)
            line.delete(bosLine)
        if not na(bosLabel)
            label.delete(bosLabel)
        // Draw BoS line
        bosLine := line.new(x1=array.get(swingHighTimes, 0), y1=array.get(swingHighs, 0), x2=bosTime, y2=array.get(swingHighs, 0), xloc=xloc.bar_time, extend=extend_mode, color=color.green, width=2)
        // Add label
        if showLabels
            bosLabel := label.new(x=bosTime, y=array.get(swingHighs, 0), text="BoS High", xloc=xloc.bar_time, style=label.style_label_down, color=color.new(color.green, 0), textcolor=color.white, size=size.tiny)
    // Change of Character (ChoCh) to the downside
    if showChoCh and low < array.get(swingLows, 0)
        chochTime := time
        // Delete previous ChoCh line and label
        if not na(chochLine)
            line.delete(chochLine)
        if not na(chochLabel)
            label.delete(chochLabel)
        // Draw ChoCh line
        chochLine := line.new(x1=array.get(swingLowTimes, 0), y1=array.get(swingLows, 0), x2=chochTime, y2=array.get(swingLows, 0), xloc=xloc.bar_time, extend=extend_mode, color=color.orange, width=2)
        // Add label
        if showLabels
            chochLabel := label.new(x=chochTime, y=array.get(swingLows, 0), text="ChoCh Low", xloc=xloc.bar_time, style=label.style_label_up, color=color.new(color.orange, 0), textcolor=color.white, size=size.tiny)
        // Reset trend
        trend := "Downtrend"

else if trend == "Downtrend"
    // Break of Structure (BoS) to the downside using Low of candle
    if showBoS and low < array.get(swingLows, 0)
        bosTime := time
        // Delete previous BoS line and label
        if not na(bosLine)
            line.delete(bosLine)
        if not na(bosLabel)
            label.delete(bosLabel)
        // Draw BoS line
        bosLine := line.new(x1=array.get(swingLowTimes, 0), y1=array.get(swingLows, 0), x2=bosTime, y2=array.get(swingLows, 0), xloc=xloc.bar_time, extend=extend_mode, color=color.red, width=2)
        // Add label
        if showLabels
            bosLabel := label.new(x=bosTime, y=array.get(swingLows, 0), text="BoS Low", xloc=xloc.bar_time, style=label.style_label_up, color=color.new(color.red, 0), textcolor=color.white, size=size.tiny)
    // Change of Character (ChoCh) to the upside
    if showChoCh and high > array.get(swingHighs, 0)
        chochTime := time
        // Delete previous ChoCh line and label
        if not na(chochLine)
            line.delete(chochLine)
        if not na(chochLabel)
            label.delete(chochLabel)
        // Draw ChoCh line
        chochLine := line.new(x1=array.get(swingHighTimes, 0), y1=array.get(swingHighs, 0), x2=chochTime, y2=array.get(swingHighs, 0), xloc=xloc.bar_time, extend=extend_mode, color=color.purple, width=2)
        // Add label
        if showLabels
            chochLabel := label.new(x=chochTime, y=array.get(swingHighs, 0), text="ChoCh High", xloc=xloc.bar_time, style=label.style_label_down, color=color.new(color.purple, 0), textcolor=color.white, size=size.tiny)
        // Reset trend
        trend := "Uptrend"

// --- Display Current Trend Label on Top Right Corner of Chart ---

// Create a table to display the trend
var table trendTable = table.new(position.top_right, 1, 1, border_width = 1)

// Update the table with the current trend
if barstate.islast and not na(trend)
    // Define background color based on trend
    bgcolor = trend == "Uptrend" ? color.new(color.green, 80) : trend == "Downtrend" ? color.new(color.red, 80) : color.new(color.gray, 80)
    // Update the table cell
    table.cell(trendTable, 0, 0, text = "Current Trend:\n" + trend, text_color = color.white, bgcolor = bgcolor, text_halign = text.align_center, text_valign = text.align_center)