PROTECTED SOURCE SCRIPT

High Low + BOS/Sweep 2

30
//version=5
indicator("High Low + BOS/Sweep (fixed pivot check)", overlay=true, max_lines_count=500, max_labels_count=500)

// Inputs
offTop = input.int(2, "Offset đỉnh", minval=0)
offBot = input.int(2, "Offset đáy", minval=0)
w = input.int(2, "Độ dày line", minval=1)
c_bos_up = input.color(color.red, "Màu BOS phá đỉnh")
c_bos_down = input.color(color.lime, "Màu BOS phá đáy")
c_sweep_up = input.color(color.orange, "Màu Sweep đỉnh")
c_sweep_down = input.color(color.aqua, "Màu Sweep đáy")
styleBosStr = input.string("Solid", "Kiểu line BOS", options=["Solid", "Dashed", "Dotted"])
styleSweepStr = input.string("Dashed", "Kiểu line Sweep", options=["Solid", "Dashed", "Dotted"])
showBosLabel = input.bool(true, "Hiện label BOS")
showSweepLabel = input.bool(true, "Hiện label Sweep")
bosLabelText = input.string("BOS", "Text BOS")
sweepLabelText = input.string("SWEEP", "Text Sweep")
labelSizeStr = input.string("tiny", "Kích thước label", options=["tiny", "small", "normal", "large"])

// Convert styles / sizes
bosStyle = styleBosStr == "Dashed" ? line.style_dashed : styleBosStr == "Dotted" ? line.style_dotted : line.style_solid
sweepStyle = styleSweepStr == "Dashed" ? line.style_dashed : styleSweepStr == "Dotted" ? line.style_dotted : line.style_solid
lblSize = labelSizeStr == "small" ? size.small : labelSizeStr == "normal" ? size.normal : labelSizeStr == "large" ? size.large : size.tiny

// State vars
c = close
var int lastSignal = 0
var float sHigh = na
var int sHighBar = na
var float sLow = na
var int sLowBar = na
var float confHigh = na
var int confHighBar = na
var float confLow = na
var int confLowBar = na
var line highLine = na
var line lowLine = na
var label highLabel = na
var label lowLabel = na

// === Đánh dấu loại line: 0 = chưa có, 1 = Sweep, 2 = BOS ===
var int highLineType = 0
var int lowLineType = 0

// === Sweep tracking / pending ===
var bool pendingSweepUp = false
var bool pendingSweepDown = false
var int sweepDetectedBarUp = na
var float sweepTargetHighPrice = na
var int sweepTargetHighBar = na
var int sweepDetectedBarDown = na
var float sweepTargetLowPrice = na
var int sweepTargetLowBar = na

// === NEW: track BOS pivots ===
var int lastBOSHighBar = na
var int lastBOSLowBar = na

// Track swing
if (lastSignal == -1) or (lastSignal == 0)
if na(sHigh) or high > sHigh
sHigh := high
sHighBar := bar_index
if (lastSignal == 1) or (lastSignal == 0)
if na(sLow) or low < sLow
sLow := low
sLowBar := bar_index

// Confirm pivot
condTop = c < low[1]
condBot = c > high[1]
isTop = condTop and (lastSignal != 1)
isBot = condBot and (lastSignal != -1)

// On pivot confirm
if isTop
confHigh := sHigh
confHighBar := sHighBar
highLine := na
highLabel := na
highLineType := 0
label.new(confHighBar, confHigh + syminfo.mintick * offTop, "●", xloc=xloc.bar_index, yloc=yloc.price, style=label.style_none, textcolor=color.red, size=size.small)
lastSignal := 1
sHigh := na
sHighBar := na
sLow := low
sLowBar := bar_index

if isBot
confLow := sLow
confLowBar := sLowBar
lowLine := na
lowLabel := na
lowLineType := 0
label.new(confLowBar, confLow - syminfo.mintick * offBot, "●", xloc=xloc.bar_index, yloc=yloc.price, style=label.style_none, textcolor=color.lime, size=size.small)
lastSignal := -1
sLow := na
sLowBar := na
sHigh := high
sHighBar := bar_index

// Raw sweep detection
rawSweepUp = not na(confHigh) and (na(lastBOSHighBar) or confHighBar != lastBOSHighBar) and high > confHigh and close <= confHigh
rawSweepDown = not na(confLow) and (na(lastBOSLowBar) or confLowBar != lastBOSLowBar) and low < confLow and close >= confLow

if rawSweepUp
pendingSweepUp := true
sweepDetectedBarUp := bar_index
sweepTargetHighPrice := confHigh
sweepTargetHighBar := confHighBar

if rawSweepDown
pendingSweepDown := true
sweepDetectedBarDown := bar_index
sweepTargetLowPrice := confLow
sweepTargetLowBar := confLowBar

// Check sweep validity
checkSweepValidUp() =>
isValid = true
if pendingSweepUp and not na(sweepDetectedBarUp)
maxOffset = bar_index - sweepDetectedBarUp
if maxOffset >= 0
for i = 0 to maxOffset
if close > sweepTargetHighPrice
isValid := false
isValid

checkSweepValidDown() =>
isValid = true
if pendingSweepDown and not na(sweepDetectedBarDown)
maxOffset = bar_index - sweepDetectedBarDown
if maxOffset >= 0
for i = 0 to maxOffset
if close < sweepTargetLowPrice
isValid := false
isValid

// BOS logic
bosUp = not na(confHigh) and c > confHigh
bosDown = not na(confLow) and c < confLow

if bosUp
pendingSweepUp := false
sweepDetectedBarUp := na
sweepTargetHighPrice := na
sweepTargetHighBar := na
lastBOSHighBar := confHighBar
if not na(highLine)
line.delete(highLine)
if not na(highLabel)
label.delete(highLabel)
highLine := line.new(confHighBar, confHigh, bar_index, confHigh, xloc=xloc.bar_index, extend=extend.none, color=c_bos_up, width=w, style=bosStyle)
highLineType := 2
if showBosLabel
midBar = math.floor((confHighBar + bar_index) / 2)
highLabel := label.new(midBar, confHigh, bosLabelText, xloc=xloc.bar_index, yloc=yloc.price, textcolor=c_bos_up, style=label.style_none, size=lblSize)

if bosDown
pendingSweepDown := false
sweepDetectedBarDown := na
sweepTargetLowPrice := na
sweepTargetLowBar := na
lastBOSLowBar := confLowBar
if not na(lowLine)
line.delete(lowLine)
if not na(lowLabel)
label.delete(lowLabel)
lowLine := line.new(confLowBar, confLow, bar_index, confLow, xloc=xloc.bar_index, extend=extend.none, color=c_bos_down, width=w, style=bosStyle)
lowLineType := 2
if showBosLabel
midBar = math.floor((confLowBar + bar_index) / 2)
lowLabel := label.new(midBar, confLow, bosLabelText, xloc=xloc.bar_index, yloc=yloc.price, textcolor=c_bos_down, style=label.style_none, size=lblSize)

// === Sweep draw (with pivot-in-between check) ===
if (isTop or isBot) and pendingSweepUp and not na(sweepTargetHighBar)
hasLowBetween = false
for i = sweepTargetHighBar to bar_index
if not na(confLowBar) and confLowBar == i
hasLowBetween := true
if checkSweepValidUp() and highLineType != 2 and hasLowBetween
if not na(highLine)
line.delete(highLine)
if not na(highLabel)
label.delete(highLabel)
highLine := line.new(sweepTargetHighBar, sweepTargetHighPrice, bar_index, sweepTargetHighPrice, xloc=xloc.bar_index, extend=extend.none, color=c_sweep_up, width=w, style=sweepStyle)
if showSweepLabel
midBar = math.floor((sweepTargetHighBar + bar_index) / 2)
highLabel := label.new(midBar, sweepTargetHighPrice, sweepLabelText, xloc=xloc.bar_index, yloc=yloc.price, textcolor=c_sweep_up, style=label.style_none, size=lblSize)
highLineType := 1
pendingSweepUp := false
sweepDetectedBarUp := na
sweepTargetHighPrice := na
sweepTargetHighBar := na

if (isTop or isBot) and pendingSweepDown and not na(sweepTargetLowBar)
hasHighBetween = false
for i = sweepTargetLowBar to bar_index
if not na(confHighBar) and confHighBar == i
hasHighBetween := true
if checkSweepValidDown() and lowLineType != 2 and hasHighBetween
if not na(lowLine)
line.delete(lowLine)
if not na(lowLabel)
label.delete(lowLabel)
lowLine := line.new(sweepTargetLowBar, sweepTargetLowPrice, bar_index, sweepTargetLowPrice, xloc=xloc.bar_index, extend=extend.none, color=c_sweep_down, width=w, style=sweepStyle)
if showSweepLabel
midBar = math.floor((sweepTargetLowBar + bar_index) / 2)
lowLabel := label.new(midBar, sweepTargetLowPrice, sweepLabelText, xloc=xloc.bar_index, yloc=yloc.price, textcolor=c_sweep_down, style=label.style_none, size=lblSize)
lowLineType := 1
pendingSweepDown := false
sweepDetectedBarDown := na
sweepTargetLowPrice := na
sweepTargetLowBar := na

// Alerts
alertcondition(isTop, "Top", "Top confirmed")
alertcondition(isBot, "Bot", "Bottom confirmed")
alertcondition(bosUp, "BOS Up", "Break of structure up")
alertcondition(bosDown, "BOS Down", "Break of structure down")

plot(na) // tránh lỗi

Declinazione di responsabilità

Le informazioni ed i contenuti pubblicati non costituiscono in alcun modo una sollecitazione ad investire o ad operare nei mercati finanziari. Non sono inoltre fornite o supportate da TradingView. Maggiori dettagli nelle Condizioni d'uso.