Search code examples
pine-scriptpine-script-v5

Bar crossover wont work on my plotted box


I have coded to create a box when a specific confition is detected, the box is stored in an array and plot on the chart correctly. I have plotted the box to cut off when price crosses the average line and all this plots ok however when i try and plot a label (or any other kind of alert) for when 'high' crosses the box line i cant get the lable to appear. I've tried nesting the label inside the main conditoin 'if', and by itself. I've also tried creating a separat array for box_lows and coding the crossover in general and whilst the code compiles Ok the condition never triggers the label even though i can see on the chart the condition should. I've no idea why this is and would appreacite any help please I just need to be able to get label to print once current_index high is greater htan box low, it seems so simple and yet just wont plot! I'm sure the error must be something obvious but cannot work it out.

the full code is:-

//@version=5
indicator("My FVG Detector - Tester"
  , overlay = true
  , max_boxes_count = 500
  , max_labels_count = 500
  , max_lines_count = 500)
//------------------------------------------------------------------------------
//Settings
//-----------------------------------------------------------------------------{
//Fair Value Gaps
show_fvg = input(true, 'Fair Value Gaps (FVG)'
  , inline = 'fvg_css'
  , group = 'Fair Value Gaps')

bull_fvg_css = input.color(#2157f3, ''
  , inline = 'fvg_css'
  , group = 'Fair Value Gaps')

bear_fvg_css = input.color(#ff1100, ''
  , inline = 'fvg_css'
  , group = 'Fair Value Gaps')

fvg_usewidth = input(true, 'Min Width'
  , inline = 'fvg_width'
  , group = 'Fair Value Gaps')

fvg_gapwidth = input.float(1.95, ''
  , inline = 'fvg_width'
  , group = 'Fair Value Gaps')

fvg_method = input.string('ATR', ''
  , options = ['Points', '%', 'ATR']
  , inline = 'fvg_width'
  , group = 'Fair Value Gaps')

fvg_extend = input.int(3, 'Extend FVG'
  , minval = 0
  , group = 'Fair Value Gaps')

bull_entry = input.int(80, 'Bull Entry Threshold'
  , minval = 0
  , group = 'Fair Value Gaps')

bull_exit = input.int(80, 'Bull Exit Threshold'
  , minval = 0
  , group = 'Fair Value Gaps')

adboxcount = input.int (50, "Maximum Imb Displayed", 1, group = "Chart Customization")

//-----------------------------------------------------------------------------}
//Functions
//-----------------------------------------------------------------------------{


n = bar_index
atr = ta.atr(200)

//Detect imbalance and return count over time
imbalance_detection(show, usewidth, method, width, top, btm, condition, wide)=>
    var is_width = true
    var count = 0
    
    if usewidth
        dist = top - btm
        bull_wide = top - btm

        is_width := switch method
            'Points' => dist > width
            '%' => dist / btm * 100 > width
            'ATR' => dist > atr * width

    is_true = show and condition and is_width
    count += is_true ? 1 : 0
    
    [is_true, count]

    

//-----------------------------------------------------------------------------}
//Arrays
//-----------------------------------------------------------------------------{

var box[] imbboxarray = array.new_box()
var line[] bear_avg_line = array.new_line()
var float[] bear_boxlow = array.new_float()




//-----------------------------------------------------------------------------}
//Fair Value Gaps
//-----------------------------------------------------------------------------{
//Bullish
[bull_fvg, bull_fvg_count] = imbalance_detection(
  show_fvg
  , fvg_usewidth
  , fvg_method
  , fvg_gapwidth
  , low
  , high[2]
  , low > high[2] and close[1] > high[2]
  , high[2] - low)
bull_top = bull_fvg
bull_width = high[2] - low
bull_avg = math.avg(low, high[2])

//Bearish
[bear_fvg, bear_fvg_count] = imbalance_detection(
  show_fvg
  , fvg_usewidth
  , fvg_method
  , fvg_gapwidth
  , low[2]
  , high
  , high < low[2] and close[1] < low[2]
  , low[2] - high)
bear_top = bear_fvg
bear_width = low[2] - high
bear_avg = math.avg(low[2], high)
bearplot = high > low[1] ? 1 : 0


// Box & Line Calc {
f_choppedoffimb(imbboxarray, bear_avg_line) =>
    if array.size(imbboxarray) > 0 and array.size(bear_avg_line) > 0
        for i = array.size(imbboxarray) - 1 to 0 by 1
            cutbox = array.get(imbboxarray, i)
            cutline = array.get(bear_avg_line, i)
            boxhighzone = box.get_top(cutbox)
            boxlowzone = box.get_bottom(cutbox)
            boxrightzone = box.get_right(cutbox)
            bear_avg_right = line.get_x2(cutline)
            if na or bar_index - 1 == boxrightzone and not (high > boxhighzone)
                box.set_right(array.get(imbboxarray, i), bar_index)
                line.set_x2(array.get(bear_avg_line, i), bar_index)

// }

// Box Draw {
if bear_top and bear_width > 0
    boxhighzone = bear_top and bear_width > 0 ? low[2] : low[0]
    boxlowzone = bear_top and bear_width > 0 ? high[0] : high[2]
    bear_box_low = low[1]
    bear_avg_right = bar_index
    imbbox = box.new(bar_index, boxhighzone, bar_index, boxlowzone, bear_fvg_css, border_style = line.style_dashed, bgcolor = color.new(bear_fvg_css, 80))
    midline = line.new(bar_index, bear_avg, bear_avg_right, bear_avg, color = color.red, style = line.style_solid)
    if array.size(imbboxarray) > adboxcount
        box.delete(array.shift(imbboxarray))
        line.delete(array.shift(bear_avg_line))
    array.push(imbboxarray, imbbox)
    array.push(bear_avg_line, midline)
    array.push(bear_boxlow, low[1])

    if ta.crossover(high, boxlowzone)
        label.new(bar_index, bear_avg, "Bear", xloc = xloc.bar_index, color = color.red, style = label.style_arrowdown, textcolor = color.white, size = size.tiny)

f_choppedoffimb(imbboxarray, bear_avg_line)
// }

// Please help creating a label which is plotted each time a bar crosses the 'boxlowzone' or 'bear_box_low'. I've tried every way i can think of and none of them plot. No idea why!

As above, I've tried nesting hte conditoin within the main 'if', calling the box values from arrays, setting the condition bool up globally and then trying to change it within the'if' (which is not allowed) and have now run out of ideas


Solution

  • ta.crossover() may not work reliably within if, better call it on each calculation.

    In your script the crossover condition was not true at the times were you expected it to be true, since boxlowzone did not reflect the low border of the box, but was changing every bar.

    (Left some debugging code inside, you may find that useful too)

    Please check the script below:

    //@version=5
    indicator("My FVG Detector - Tester"
      , overlay = true
      , max_boxes_count = 500
      , max_labels_count = 500
      , max_lines_count = 500)
    //------------------------------------------------------------------------------
    //Settings
    //-----------------------------------------------------------------------------{
    //Fair Value Gaps
    show_fvg = input(true, 'Fair Value Gaps (FVG)'
      , inline = 'fvg_css'
      , group = 'Fair Value Gaps')
    
    bull_fvg_css = input.color(#2157f3, ''
      , inline = 'fvg_css'
      , group = 'Fair Value Gaps')
    
    bear_fvg_css = input.color(#ff1100, ''
      , inline = 'fvg_css'
      , group = 'Fair Value Gaps')
    
    fvg_usewidth = input(true, 'Min Width'
      , inline = 'fvg_width'
      , group = 'Fair Value Gaps')
    
    fvg_gapwidth = input.float(1.95, ''
      , inline = 'fvg_width'
      , group = 'Fair Value Gaps')
    
    fvg_method = input.string('ATR', ''
      , options = ['Points', '%', 'ATR']
      , inline = 'fvg_width'
      , group = 'Fair Value Gaps')
    
    fvg_extend = input.int(3, 'Extend FVG'
      , minval = 0
      , group = 'Fair Value Gaps')
    
    bull_entry = input.int(80, 'Bull Entry Threshold'
      , minval = 0
      , group = 'Fair Value Gaps')
    
    bull_exit = input.int(80, 'Bull Exit Threshold'
      , minval = 0
      , group = 'Fair Value Gaps')
    
    adboxcount = input.int (50, "Maximum Imb Displayed", 1, group = "Chart Customization")
    
    //-----------------------------------------------------------------------------}
    //Functions
    //-----------------------------------------------------------------------------{
    
    
    n = bar_index
    atr = ta.atr(200)
    
    //Detect imbalance and return count over time
    imbalance_detection(show, usewidth, method, width, top, btm, condition, wide)=>
        var is_width = true
        var count = 0
        
        if usewidth
            dist = top - btm
            bull_wide = top - btm
    
            is_width := switch method
                'Points' => dist > width
                '%' => dist / btm * 100 > width
                'ATR' => dist > atr * width
    
        is_true = show and condition and is_width
        count += is_true ? 1 : 0
        
        [is_true, count]
    
        
    
    //-----------------------------------------------------------------------------}
    //Arrays
    //-----------------------------------------------------------------------------{
    
    var box[] imbboxarray = array.new_box()
    var line[] bear_avg_line = array.new_line()
    var float[] bear_boxlow = array.new_float()
    
    
    
    
    //-----------------------------------------------------------------------------}
    //Fair Value Gaps
    //-----------------------------------------------------------------------------{
    //Bullish
    [bull_fvg, bull_fvg_count] = imbalance_detection(
      show_fvg
      , fvg_usewidth
      , fvg_method
      , fvg_gapwidth
      , low
      , high[2]
      , low > high[2] and close[1] > high[2]
      , high[2] - low)
    bull_top = bull_fvg
    bull_width = high[2] - low
    bull_avg = math.avg(low, high[2])
    
    //Bearish
    [bear_fvg, bear_fvg_count] = imbalance_detection(
      show_fvg
      , fvg_usewidth
      , fvg_method
      , fvg_gapwidth
      , low[2]
      , high
      , high < low[2] and close[1] < low[2]
      , low[2] - high)
    bear_top = bear_fvg
    bear_width = low[2] - high
    bear_avg = math.avg(low[2], high)
    bearplot = high > low[1] ? 1 : 0
    
    
    // Box & Line Calc {
    f_choppedoffimb(imbboxarray, bear_avg_line) =>
        if array.size(imbboxarray) > 0 and array.size(bear_avg_line) > 0
            for i = array.size(imbboxarray) - 1 to 0 by 1
                cutbox = array.get(imbboxarray, i)
                cutline = array.get(bear_avg_line, i)
                boxhighzone = box.get_top(cutbox)
                boxlowzone = box.get_bottom(cutbox)
                boxrightzone = box.get_right(cutbox)
                bear_avg_right = line.get_x2(cutline)
                if na or bar_index - 1 == boxrightzone and not (high > boxhighzone)
                    box.set_right(array.get(imbboxarray, i), bar_index)
                    line.set_x2(array.get(bear_avg_line, i), bar_index)
    
    // }
    
    var boxhighzone = 0.
    var boxlowzone = 0.
    
    boxhighzone := bear_top and bear_width > 0 ? low[2] : boxhighzone
    boxlowzone := bear_top and bear_width > 0 ? high[0] : boxlowzone
    bear_box_low = low[1]
    bear_avg_right = bar_index
    var belowBoxhighzone = false
    if imbboxarray.size() > 0
        belowBoxhighzone := (high > box.get_top(imbboxarray.last())) ? false : belowBoxhighzone
    
    crossoverHighBoxLowZone =  ta.crossover(high, boxlowzone) and belowBoxhighzone
    
    
    if crossoverHighBoxLowZone
        label.new(bar_index, bear_avg, "Bear", xloc = xloc.bar_index, color = color.red, style = label.style_arrowdown, textcolor = color.white, size = size.tiny)
    
    // Box Draw {
    if bear_top and bear_width > 0
        imbbox = box.new(bar_index, boxhighzone, bar_index, boxlowzone, bear_fvg_css, border_style = line.style_dashed, bgcolor = color.new(bear_fvg_css, 80))
        midline = line.new(bar_index, bear_avg, bear_avg_right, bear_avg, color = color.red, style = line.style_solid)
        if array.size(imbboxarray) > adboxcount
            box.delete(array.shift(imbboxarray))
            line.delete(array.shift(bear_avg_line))
        array.push(imbboxarray, imbbox)
        array.push(bear_avg_line, midline)
        array.push(bear_boxlow, low[1])
        belowBoxhighzone := true
    
    
    bgcolor(bear_top and bear_width > 0 ? color.rgb(255, 235, 59, 57) : na)
    bgcolor(crossoverHighBoxLowZone ? color.rgb(213, 59, 255, 56) : na)
    
    plotchar(bear_top, "bear_top", "", location = location.top)
    plotchar(bear_width, "bear_width", "", location = location.top)
    plotchar(boxlowzone, "boxlowzone", "", location = location.top)
    plotchar(crossoverHighBoxLowZone, "crossoverHighBoxLowZone", "", location = location.top)
    plotchar(array.size(label.all), "label.all.size()", "", location = location.top)
    plotchar(array.size(box.all), "box.all.size()", "", location = location.top)
    
    
    // if bar_index % 20 == 0  
    //     label.new(bar_index, bear_avg, "Bear", xloc = xloc.bar_index, color = color.red, style = label.style_arrowdown, textcolor = color.white, size = size.tiny)
    
    f_choppedoffimb(imbboxarray, bear_avg_line)
    // }