OPEN-SOURCE SCRIPT
BOS + Liquidity Sweep Entries

//version=5
indicator("BOS + Liquidity Sweep Entries (Both Directions) — Fixed", overlay=true, shorttitle="BOS+LS")
// ===== INPUTS =====
swingLen = input.int(5, "Swing lookback", minval=1)
sweepATRmult = input.float(0.5, "Sweep wick threshold (ATR multiplier)", minval=0.0, step=0.1)
maxBarsSinceBOS = input.int(50, "Max bars to wait for sweep after BOS", minval=1)
showLabels = input.bool(true, "Show labels", inline="lbl")
showShapes = input.bool(true, "Show shapes", inline="lbl")
atr = ta.atr(14)
// ===== PIVOTS =====
ph_val = ta.pivothigh(high, swingLen, swingLen)
pl_val = ta.pivotlow(low, swingLen, swingLen)
// persist last pivots and their bar indices
var float lastPH = na
var int lastPH_bar = na
var float lastPL = na
var int lastPL_bar = na
if not na(ph_val)
lastPH := ph_val
lastPH_bar := bar_index - swingLen
if not na(pl_val)
lastPL := pl_val
lastPL_bar := bar_index - swingLen
// ===== BOS DETECTION (record the bar where BOS first confirmed) =====
var int bull_bos_bar = na
bull_bos = not na(lastPH) and close > lastPH and bar_index > lastPH_bar
if bull_bos
// store first confirmation bar (overwrite only if new)
if na(bull_bos_bar) or bar_index > bull_bos_bar
bull_bos_bar := bar_index
var int bear_bos_bar = na
bear_bos = not na(lastPL) and close < lastPL and bar_index > lastPL_bar
if bear_bos
if na(bear_bos_bar) or bar_index > bear_bos_bar
bear_bos_bar := bar_index
// If pivots update to a more recent pivot, clear older BOS/sweep markers that predate the new pivot
if not na(lastPH_bar) and not na(bull_bos_bar)
if bull_bos_bar <= lastPH_bar
bull_bos_bar := na
// clear bull sweep when pivot updates
var int last_bull_sweep_bar = na
if not na(lastPL_bar) and not na(bear_bos_bar)
if bear_bos_bar <= lastPL_bar
bear_bos_bar := na
var int last_bear_sweep_bar = na
// ensure sweep tracking vars exist (declared outside so we can reference later)
var int last_bull_sweep_bar = na
var int last_bear_sweep_bar = na
// ===== SWEEP DETECTION =====
// Bullish sweep: wick above BOS (lastPH) by threshold, then close back below the BOS level
bull_sweep = false
if not na(bull_bos_bar) and not na(lastPH)
bars_since = bar_index - bull_bos_bar
if bars_since <= maxBarsSinceBOS
wick_above = high - lastPH
if (wick_above > sweepATRmult * atr) and (close < lastPH)
bull_sweep := true
last_bull_sweep_bar := bar_index
// Bearish sweep: wick below BOS (lastPL) by threshold, then close back above the BOS level
bear_sweep = false
if not na(bear_bos_bar) and not na(lastPL)
bars_since = bar_index - bear_bos_bar
if bars_since <= maxBarsSinceBOS
wick_below = lastPL - low
if (wick_below > sweepATRmult * atr) and (close > lastPL)
bear_sweep := true
last_bear_sweep_bar := bar_index
// ===== ENTRY RULES (only after sweep happened AFTER BOS) =====
long_entry = false
if not na(last_bull_sweep_bar) and not na(bull_bos_bar)
if (last_bull_sweep_bar > bull_bos_bar) and (bar_index > last_bull_sweep_bar) and (close > lastPH)
long_entry := true
// avoid duplicate triggers from the same sweep
last_bull_sweep_bar := na
short_entry = false
if not na(last_bear_sweep_bar) and not na(bear_bos_bar)
if (last_bear_sweep_bar > bear_bos_bar) and (bar_index > last_bear_sweep_bar) and (close < lastPL)
short_entry := true
// avoid duplicate triggers from the same sweep
last_bear_sweep_bar := na
// ===== PLOTTING LINES =====
plot(lastPH, title="Last Swing High", color=color.orange, linewidth=2, style=plot.style_linebr)
plot(lastPL, title="Last Swing Low", color=color.teal, linewidth=2, style=plot.style_linebr)
// ===== LABELS & SHAPES (managed to avoid label flooding) =====
var label lb_bull_bos = na
var label lb_bear_bos = na
var label lb_bull_sweep = na
var label lb_bear_sweep = na
var label lb_long_entry = na
var label lb_short_entry = na
if showLabels
if bull_bos
if not na(lb_bull_bos)
label.delete(lb_bull_bos)
lb_bull_bos := label.new(bar_index, high, "Bull BOS ✓", yloc=yloc.abovebar, style=label.style_label_up, color=color.green, textcolor=color.white)
if bear_bos
if not na(lb_bear_bos)
label.delete(lb_bear_bos)
lb_bear_bos := label.new(bar_index, low, "Bear BOS ✓", yloc=yloc.belowbar, style=label.style_label_down, color=color.red, textcolor=color.white)
if bull_sweep
if not na(lb_bull_sweep)
label.delete(lb_bull_sweep)
lb_bull_sweep := label.new(bar_index, high, "Bull Sweep", yloc=yloc.abovebar, style=label.style_label_down, color=color.purple, textcolor=color.white)
if bear_sweep
if not na(lb_bear_sweep)
label.delete(lb_bear_sweep)
lb_bear_sweep := label.new(bar_index, low, "Bear Sweep", yloc=yloc.belowbar, style=label.style_label_up, color=color.purple, textcolor=color.white)
if long_entry
if not na(lb_long_entry)
label.delete(lb_long_entry)
lb_long_entry := label.new(bar_index, low, "LONG ENTRY", yloc=yloc.belowbar, style=label.style_label_up, color=color.lime, textcolor=color.black)
if short_entry
if not na(lb_short_entry)
label.delete(lb_short_entry)
lb_short_entry := label.new(bar_index, high, "SHORT ENTRY", yloc=yloc.abovebar, style=label.style_label_down, color=color.red, textcolor=color.white)
// optional shapes (good for quick visual scanning)
if showShapes
plotshape(bull_sweep, title="Bull Sweep Shape", location=location.abovebar, color=color.purple, style=shape.triangledown, size=size.tiny)
plotshape(bear_sweep, title="Bear Sweep Shape", location=location.belowbar, color=color.purple, style=shape.triangleup, size=size.tiny)
plotshape(long_entry, title="Long Shape", location=location.belowbar, color=color.lime, style=shape.triangleup, size=size.small)
plotshape(short_entry, title="Short Shape", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small)
// ===== ALERTS =====
alertcondition(bull_bos, title="Bullish BOS", message="Bullish BOS confirmed above swing high")
alertcondition(bear_bos, title="Bearish BOS", message="Bearish BOS confirmed below swing low")
alertcondition(bull_sweep, title="Bullish Sweep", message="Liquidity sweep above swing high detected")
alertcondition(bear_sweep, title="Bearish Sweep", message="Liquidity sweep below swing low detected")
alertcondition(long_entry, title="LONG Entry", message="LONG Entry: BOS -> sweep -> reclaim")
alertcondition(short_entry, title="SHORT Entry", message="SHORT Entry: BOS -> sweep -> reclaim")
indicator("BOS + Liquidity Sweep Entries (Both Directions) — Fixed", overlay=true, shorttitle="BOS+LS")
// ===== INPUTS =====
swingLen = input.int(5, "Swing lookback", minval=1)
sweepATRmult = input.float(0.5, "Sweep wick threshold (ATR multiplier)", minval=0.0, step=0.1)
maxBarsSinceBOS = input.int(50, "Max bars to wait for sweep after BOS", minval=1)
showLabels = input.bool(true, "Show labels", inline="lbl")
showShapes = input.bool(true, "Show shapes", inline="lbl")
atr = ta.atr(14)
// ===== PIVOTS =====
ph_val = ta.pivothigh(high, swingLen, swingLen)
pl_val = ta.pivotlow(low, swingLen, swingLen)
// persist last pivots and their bar indices
var float lastPH = na
var int lastPH_bar = na
var float lastPL = na
var int lastPL_bar = na
if not na(ph_val)
lastPH := ph_val
lastPH_bar := bar_index - swingLen
if not na(pl_val)
lastPL := pl_val
lastPL_bar := bar_index - swingLen
// ===== BOS DETECTION (record the bar where BOS first confirmed) =====
var int bull_bos_bar = na
bull_bos = not na(lastPH) and close > lastPH and bar_index > lastPH_bar
if bull_bos
// store first confirmation bar (overwrite only if new)
if na(bull_bos_bar) or bar_index > bull_bos_bar
bull_bos_bar := bar_index
var int bear_bos_bar = na
bear_bos = not na(lastPL) and close < lastPL and bar_index > lastPL_bar
if bear_bos
if na(bear_bos_bar) or bar_index > bear_bos_bar
bear_bos_bar := bar_index
// If pivots update to a more recent pivot, clear older BOS/sweep markers that predate the new pivot
if not na(lastPH_bar) and not na(bull_bos_bar)
if bull_bos_bar <= lastPH_bar
bull_bos_bar := na
// clear bull sweep when pivot updates
var int last_bull_sweep_bar = na
if not na(lastPL_bar) and not na(bear_bos_bar)
if bear_bos_bar <= lastPL_bar
bear_bos_bar := na
var int last_bear_sweep_bar = na
// ensure sweep tracking vars exist (declared outside so we can reference later)
var int last_bull_sweep_bar = na
var int last_bear_sweep_bar = na
// ===== SWEEP DETECTION =====
// Bullish sweep: wick above BOS (lastPH) by threshold, then close back below the BOS level
bull_sweep = false
if not na(bull_bos_bar) and not na(lastPH)
bars_since = bar_index - bull_bos_bar
if bars_since <= maxBarsSinceBOS
wick_above = high - lastPH
if (wick_above > sweepATRmult * atr) and (close < lastPH)
bull_sweep := true
last_bull_sweep_bar := bar_index
// Bearish sweep: wick below BOS (lastPL) by threshold, then close back above the BOS level
bear_sweep = false
if not na(bear_bos_bar) and not na(lastPL)
bars_since = bar_index - bear_bos_bar
if bars_since <= maxBarsSinceBOS
wick_below = lastPL - low
if (wick_below > sweepATRmult * atr) and (close > lastPL)
bear_sweep := true
last_bear_sweep_bar := bar_index
// ===== ENTRY RULES (only after sweep happened AFTER BOS) =====
long_entry = false
if not na(last_bull_sweep_bar) and not na(bull_bos_bar)
if (last_bull_sweep_bar > bull_bos_bar) and (bar_index > last_bull_sweep_bar) and (close > lastPH)
long_entry := true
// avoid duplicate triggers from the same sweep
last_bull_sweep_bar := na
short_entry = false
if not na(last_bear_sweep_bar) and not na(bear_bos_bar)
if (last_bear_sweep_bar > bear_bos_bar) and (bar_index > last_bear_sweep_bar) and (close < lastPL)
short_entry := true
// avoid duplicate triggers from the same sweep
last_bear_sweep_bar := na
// ===== PLOTTING LINES =====
plot(lastPH, title="Last Swing High", color=color.orange, linewidth=2, style=plot.style_linebr)
plot(lastPL, title="Last Swing Low", color=color.teal, linewidth=2, style=plot.style_linebr)
// ===== LABELS & SHAPES (managed to avoid label flooding) =====
var label lb_bull_bos = na
var label lb_bear_bos = na
var label lb_bull_sweep = na
var label lb_bear_sweep = na
var label lb_long_entry = na
var label lb_short_entry = na
if showLabels
if bull_bos
if not na(lb_bull_bos)
label.delete(lb_bull_bos)
lb_bull_bos := label.new(bar_index, high, "Bull BOS ✓", yloc=yloc.abovebar, style=label.style_label_up, color=color.green, textcolor=color.white)
if bear_bos
if not na(lb_bear_bos)
label.delete(lb_bear_bos)
lb_bear_bos := label.new(bar_index, low, "Bear BOS ✓", yloc=yloc.belowbar, style=label.style_label_down, color=color.red, textcolor=color.white)
if bull_sweep
if not na(lb_bull_sweep)
label.delete(lb_bull_sweep)
lb_bull_sweep := label.new(bar_index, high, "Bull Sweep", yloc=yloc.abovebar, style=label.style_label_down, color=color.purple, textcolor=color.white)
if bear_sweep
if not na(lb_bear_sweep)
label.delete(lb_bear_sweep)
lb_bear_sweep := label.new(bar_index, low, "Bear Sweep", yloc=yloc.belowbar, style=label.style_label_up, color=color.purple, textcolor=color.white)
if long_entry
if not na(lb_long_entry)
label.delete(lb_long_entry)
lb_long_entry := label.new(bar_index, low, "LONG ENTRY", yloc=yloc.belowbar, style=label.style_label_up, color=color.lime, textcolor=color.black)
if short_entry
if not na(lb_short_entry)
label.delete(lb_short_entry)
lb_short_entry := label.new(bar_index, high, "SHORT ENTRY", yloc=yloc.abovebar, style=label.style_label_down, color=color.red, textcolor=color.white)
// optional shapes (good for quick visual scanning)
if showShapes
plotshape(bull_sweep, title="Bull Sweep Shape", location=location.abovebar, color=color.purple, style=shape.triangledown, size=size.tiny)
plotshape(bear_sweep, title="Bear Sweep Shape", location=location.belowbar, color=color.purple, style=shape.triangleup, size=size.tiny)
plotshape(long_entry, title="Long Shape", location=location.belowbar, color=color.lime, style=shape.triangleup, size=size.small)
plotshape(short_entry, title="Short Shape", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small)
// ===== ALERTS =====
alertcondition(bull_bos, title="Bullish BOS", message="Bullish BOS confirmed above swing high")
alertcondition(bear_bos, title="Bearish BOS", message="Bearish BOS confirmed below swing low")
alertcondition(bull_sweep, title="Bullish Sweep", message="Liquidity sweep above swing high detected")
alertcondition(bear_sweep, title="Bearish Sweep", message="Liquidity sweep below swing low detected")
alertcondition(long_entry, title="LONG Entry", message="LONG Entry: BOS -> sweep -> reclaim")
alertcondition(short_entry, title="SHORT Entry", message="SHORT Entry: BOS -> sweep -> reclaim")
开源脚本
本着TradingView的真正精神,此脚本的创建者将其开源,以便交易者可以查看和验证其功能。向作者致敬!虽然您可以免费使用它,但请记住,重新发布代码必须遵守我们的网站规则。
免责声明
这些信息和出版物并不意味着也不构成TradingView提供或认可的金融、投资、交易或其它类型的建议或背书。请在使用条款阅读更多信息。
开源脚本
本着TradingView的真正精神,此脚本的创建者将其开源,以便交易者可以查看和验证其功能。向作者致敬!虽然您可以免费使用它,但请记住,重新发布代码必须遵守我们的网站规则。
免责声明
这些信息和出版物并不意味着也不构成TradingView提供或认可的金融、投资、交易或其它类型的建议或背书。请在使用条款阅读更多信息。