//@version=5 indicator("Breaks and Retests with Volatility Stop [HG]", overlay = true, max_boxes_count = 500, max_labels_count = 500) g_sr = 'Support and Resistance' g_c = 'Conditions' g_st = 'Styling' t_r = 'Bar Confirmation: Generates alerts when candle closes. (1 Candle Later) \n\nHigh & Low: By default, the Break & Retest system uses the current close value to determine a condition, selecting High & Low will make the script utilize these two values instead of the close value. In return, the script won\'t repaint and will yield different results.' t_rv = 'Whenever a potential retest is detected, the indicator knows that a retest is about to happen. In that given situation, this input grants the ability to raise the limit on how many bars are allowed to be actively checked while a potential retest event is active.\n\nExample, if you see the potential retest label, how many bars do you want that potential retest label to be active for to eventually confirm a retest? This system was implemented to prevent retest alerts from going off 10+ bars later from the potential retest point leading to inaccurate results.' input_lookback = input.int(defval = 20, title = 'Lookback Range', minval = 1, tooltip = 'How many bars for a pivot event to occur.', group = g_sr) input_retSince = input.int(defval = 2, title = 'Bars Since Breakout', minval = 1, tooltip = 'How many bars since breakout in order to detect a retest.', group = g_sr) input_retValid = input.int(defval = 2, title = 'Retest Detection Limiter', minval = 1, tooltip = t_rv, group = g_sr) input_breakout = input.bool(defval = true, title = 'Breakouts', group = g_c) input_retest = input.bool(defval = true, title = 'Retests', group = g_c) input_repType = input.string(defval = 'On', title = 'Repainting', options = ['On', 'Off: Candle Confirmation', 'Off: High & Low'], tooltip = t_r, group = g_c) input_outL = input.string(defval = line.style_dotted, title = 'Outline', group = g_st, options = [line.style_dotted, line.style_dashed, line.style_solid]) input_extend = input.string(defval = extend.none, title = 'Extend', group = g_st, options = [extend.none, extend.right, extend.left, extend.both]) input_labelType = input.string(defval = 'Full', title = 'Label Type', options = ['Full', 'Simple'], group = g_st) input_labelSize = input.string(defval = size.small, title = 'Label Size', options = [size.tiny, size.small, size.normal, size.large, size.huge], group = g_st) input_plColor = input.color(defval = color.red, title = 'Support', inline = 'Color', group = g_st) input_phColor = input.color(defval = #089981, title = 'Resistance', inline = 'Color', group = g_st) input_override = input.bool(defval = false, title = 'Override Text Color ', inline = 'Override', group = g_st) input_textColor = input.color(defval = color.white, title = '', inline = 'Override', group = g_st) bb = input_lookback rTon = input_repType == 'On' rTcc = input_repType == 'Off: Candle Confirmation' rThv = input_repType == 'Off: High & Low' breakText = input_labelType == 'Simple' ? 'Br' : 'Break' // Pivot Instance pl = fixnan(ta.pivotlow(low, bb, bb)) ph = fixnan(ta.pivothigh(high, bb, bb)) // Box Height s_yLoc = low[bb + 1] > low[bb - 1] ? low[bb - 1] : low[bb + 1] r_yLoc = high[bb + 1] > high[bb - 1] ? high[bb + 1] : high[bb - 1] //----------------------------------------------------------------------------- // Functions //----------------------------------------------------------------------------- drawBox(condition, y1, y2, color) => var box drawBox = na if condition box.set_right(drawBox, bar_index - bb) drawBox.set_extend(extend.none) drawBox := box.new(bar_index - bb, y1, bar_index, y2, color, bgcolor = color.new(color, 90), border_style = input_outL, extend = input_extend) [drawBox] updateBox(box) => if barstate.isconfirmed box.set_right(box, bar_index + 5) breakLabel(y, color, style, textform) => label.new(bar_index, y, textform, textcolor = input_override ? input_textColor : color, style = style, color = color.new(color, 50), size = input_labelSize) retestCondition(breakout, condition) => ta.barssince(na(breakout)) > input_retSince and condition repaint(c1, c2, c3) => rTon ? c1 : rThv ? c2 : rTcc ? c3 : na //----------------------------------------------------------------------------- // Draw and Update Boxes //----------------------------------------------------------------------------- [sBox] = drawBox(ta.change(pl), s_yLoc, pl, input_plColor) [rBox] = drawBox(ta.change(ph), ph, r_yLoc, input_phColor) sTop = box.get_top(sBox), rTop = box.get_top(rBox) sBot = box.get_bottom(sBox), rBot = box.get_bottom(rBox) updateBox(sBox), updateBox(rBox) //----------------------------------------------------------------------------- // Breakout Event //----------------------------------------------------------------------------- var bool sBreak = na var bool rBreak = na cu = repaint(ta.crossunder(close, box.get_bottom(sBox)), ta.crossunder(low, box.get_bottom(sBox)), ta.crossunder(close, box.get_bottom(sBox)) and barstate.isconfirmed) co = repaint(ta.crossover(close, box.get_top(rBox)), ta.crossover(high, box.get_top(rBox)), ta.crossover(close, box.get_top(rBox)) and barstate.isconfirmed) switch cu and na(sBreak) => sBreak := true if input_breakout breakLabel(sBot, input_plColor, label.style_label_upper_right, breakText) co and na(rBreak) => rBreak := true if input_breakout breakLabel(rTop, input_phColor, label.style_label_lower_right, breakText) if ta.change(pl) if na(sBreak) box.delete(sBox[1]) sBreak := na if ta.change(ph) if na(rBreak) box.delete(rBox[1]) rBreak := na //----------------------------------------------------------------------------- // Retest Event //----------------------------------------------------------------------------- s1 = retestCondition(sBreak, high >= sTop and close <= sBot) // High is GOET top sBox value and the close price is LOET the bottom sBox value. s2 = retestCondition(sBreak, high >= sTop and close >= sBot and close <= sTop) // High is GOET top sBox value and close is GOET the bottom sBox value and closing price is LOET the top sBox value. s3 = retestCondition(sBreak, high >= sBot and high <= sTop) // High is in between the sBox. s4 = retestCondition(sBreak, high >= sBot and high <= sTop and close < sBot) // High is in between the sBox, and the closing price is below. r1 = retestCondition(rBreak, low <= rBot and close >= rTop) // Low is LOET bottom rBox value and close is GOET the top sBox value r2 = retestCondition(rBreak, low <= rBot and close <= rTop and close >= rBot) // Low is LOET bottom rBox value and close is LOET the top sBox value and closing price is GOET the bottom rBox value. r3 = retestCondition(rBreak, low <= rTop and low >= rBot) // Low is in between the rBox. r4 = retestCondition(rBreak, low <= rTop and low >= rBot and close > rTop) // Low is in between the rBox, and the closing price is above. retestEvent(c1, c2, c3, c4, y1, y2, col, style, pType) => if input_retest var bool retOccurred = na retActive = c1 or c2 or c3 or c4 retEvent = retActive and not retActive[1] retValue = ta.valuewhen(retEvent, y1, 0) if pType == 'ph' ? y2 < ta.valuewhen(retEvent, y2, 0) : y2 > ta.valuewhen(retEvent, y2, 0) retEvent := retActive // Must be reassigned here just in case the above if statement triggers. retValue := ta.valuewhen(retEvent, y1, 0) retSince = ta.barssince(retEvent) var retLabel = array.new