PROTECTED SOURCE SCRIPT
更新済

Sweep + BOS Alerts

50
//version=5
indicator("Sweep + BOS Alerts", overlay=true, shorttitle="SweepBOS")

// === User inputs ===
// Lookback length for pivot highs/lows. Higher values produce fewer swings/signals.
length = input.int(5, title="Pivot length", minval=1, maxval=50)
// Minimum relative wick size to qualify as a sweep (ratio of wick to body)
minWickMult = input.float(1.5, title="Min wick‑to‑body ratio", minval=0.0)
// Volume confirmation multiplier: volume must be at least this multiple of average volume
volMult = input.float(1.0, title="Volume multiple for BOS confirmation", minval=0.0)
// Maximum signals per month (to limit to ~5–7 as requested)
maxSignals = input.int(7, title="Max signals per month", minval=1, maxval=20)
// Only alert once per sweep/BOS pair
onlyFirst = input.bool(true, title="Only first BOS after sweep")

// === Helpers ===
// Identify pivot highs/lows using built‑in pivot functions
pivotHighPrice = ta.pivothigh(high, length, length)
pivotLowPrice = ta.pivotlow(low, length, length)

// Track the most recent swing high/low and their bar indices
var float lastSwingHigh = na
var float lastSwingLow = na
var int lastSwingHighBar = na
var int lastSwingLowBar = na

if not na(pivotHighPrice)
lastSwingHigh := pivotHighPrice
lastSwingHighBar := bar_index - length

if not na(pivotLowPrice)
lastSwingLow := pivotLowPrice
lastSwingLowBar := bar_index - length

// Calculate average volume for confirmation
avgVol = ta.sma(volume, 20)

// === Sweep detection ===
// Flags to signal a sweep occurred and BOS expected
var bool awaitingBearBOS = false
var bool awaitingBullBOS = false

// Check for sell sweep (buyside liquidity sweep)
// Condition: current high breaks previous swing high and closes back below the swing high with a long upper wick
bearSweep = false
if (not na(lastSwingHigh) and high > lastSwingHigh)
// compute candle components
bodySize = math.abs(close - open)
upperWick = high - math.max(open, close)
isLongUpperWick = bodySize > 0 ? upperWick / bodySize >= minWickMult : false
// price closes below the last swing high (reversion inside range)
closesInside = close < lastSwingHigh
bearSweep := isLongUpperWick and closesInside

// Check for buy sweep (sellside liquidity sweep)
bullSweep = false
if (not na(lastSwingLow) and low < lastSwingLow)
bodySize = math.abs(close - open)
lowerWick = math.min(open, close) - low
isLongLowerWick = bodySize > 0 ? lowerWick / bodySize >= minWickMult : false
closesInside = close > lastSwingLow
bullSweep := isLongLowerWick and closesInside

// When sweep occurs, set awaiting BOS flags
if bearSweep
awaitingBearBOS := true
awaitingBullBOS := false
if bullSweep
awaitingBullBOS := true
awaitingBearBOS := false

// === BOS detection ===
// Evaluate BOS only if a sweep has happened
autoSellSignal = false
autoBuySignal = false
if awaitingBearBOS
// Look for break of structure to downside: close lower than last swing low.
// Confirm with volume if needed: if average volume is zero (e.g. at start of data), accept any volume.
bool volOkDown = (avgVol == 0) or (volume >= volMult * avgVol)
if (not na(lastSwingLow) and close < lastSwingLow and volOkDown)
autoSellSignal := true
// If only first BOS should trigger, reset flag; otherwise keep awaiting further BOS
awaitingBearBOS := not onlyFirst

if awaitingBullBOS
// Look for break of structure to upside: close higher than last swing high.
bool volOkUp = (avgVol == 0) or (volume >= volMult * avgVol)
if (not na(lastSwingHigh) and close > lastSwingHigh and volOkUp)
autoBuySignal := true
awaitingBullBOS := not onlyFirst

// === Signal throttling per month ===
// Convert current date to month index (year*12 + month)
monthIndex = year * 12 + month
var int currentMonth = monthIndex
var int signalCount = 0
if monthIndex != currentMonth
currentMonth := monthIndex
signalCount := 0

// Limit number of signals per month
buyAllowed = autoBuySignal and (signalCount < maxSignals)
sellAllowed = autoSellSignal and (signalCount < maxSignals)

if buyAllowed or sellAllowed
signalCount += 1

// === Plotting signals ===
plotshape(buyAllowed, title="Buy Signal", style=shape.triangleup, location=location.belowbar, color=color.new(color.green, 0), size=size.tiny, text="BUY")
plotshape(sellAllowed, title="Sell Signal", style=shape.triangledown, location=location.abovebar, color=color.new(color.red, 0), size=size.tiny, text="SELL")

// Plot swing levels (optional for visual reference)
plot(lastSwingHigh, title="Swing High", color=color.gray, style=plot.style_linebr)
plot(lastSwingLow, title="Swing Low", color=color.gray, style=plot.style_linebr)

// === Alerts ===
// These alertconditions allow TradingView to trigger notifications
alertcondition(buyAllowed, title="Buy Alert", message="Sweep+BOS Buy signal on {{exchange}} {{ticker}} @ {{close}} on {{interval}}")
alertcondition(sellAllowed, title="Sell Alert", message="Sweep+BOS Sell signal on {{exchange}} {{ticker}} @ {{close}} on {{interval}}")

リリースノート
//version=5
indicator("Sweep + BOS Alerts", overlay=true, shorttitle="SweepBOS")

// === User inputs ===
length = input.int(5, title="Pivot length", minval=1, maxval=50)
minWickMult = input.float(1.5, title="Min wick‑to‑body ratio", minval=0.0)
volMult = input.float(1.0, title="Volume multiple", minval=0.0)
onlyFirst = input.bool(true, title="Only first BOS after sweep")
buyColor = input.color(color.green, title="Buy arrow color")
sellColor = input.color(color.red, title="Sell arrow color")
// Liquidity detection
liqLen = input.int(7, title='Liquidity Detection Length', minval=3, maxval=13, group='Liquidity')
liqMargin = input.float(6.9, title='Liquidity Margin', minval=4, maxval=9, step=0.1, group='Liquidity')
showLiqBuy = input.bool(true, title='Show Buyside Liquidity', group='Liquidity')
showLiqSell = input.bool(true, title='Show Sellside Liquidity', group='Liquidity')

// === Helpers ===
pivotHighPrice = ta.pivothigh(high, length, length)
pivotLowPrice = ta.pivotlow(low, length, length)

var float lastSwingHigh = na
var float lastSwingLow = na
if not na(pivotHighPrice)
lastSwingHigh := pivotHighPrice
if not na(pivotLowPrice)
lastSwingLow := pivotLowPrice

avgVol = ta.sma(volume, 20)

// === Sweep detection ===
var bool awaitingBearBOS = false
var bool awaitingBullBOS = false

bearSweep = false
if not na(lastSwingHigh) and high > lastSwingHigh
bodySize = math.abs(close - open)
upperWick = high - math.max(open, close)
isLongUpper = bodySize > 0 ? upperWick / bodySize >= minWickMult : false
closesInside = close < lastSwingHigh
bearSweep := isLongUpper and closesInside

bullSweep = false
if not na(lastSwingLow) and low < lastSwingLow
bodySize = math.abs(close - open)
lowerWick = math.min(open, close) - low
isLongLower = bodySize > 0 ? lowerWick / bodySize >= minWickMult : false
closesInside = close > lastSwingLow
bullSweep := isLongLower and closesInside

if bearSweep
awaitingBearBOS := true
awaitingBullBOS := false
if bullSweep
awaitingBullBOS := true
awaitingBearBOS := false

// === BOS detection ===
autoSellSignal = false
autoBuySignal = false
if awaitingBearBOS
bool volOkDown = (avgVol == 0) or (volume >= volMult * avgVol)
if not na(lastSwingLow) and close < lastSwingLow and volOkDown
autoSellSignal := true
awaitingBearBOS := not onlyFirst
if awaitingBullBOS
bool volOkUp = (avgVol == 0) or (volume >= volMult * avgVol)
if not na(lastSwingHigh) and close > lastSwingHigh and volOkUp
autoBuySignal := true
awaitingBullBOS := not onlyFirst

// === Signals without monthly limits ===
buyAllowed = autoBuySignal
sellAllowed = autoSellSignal

// === Liquidity detection ===
liqHigh = ta.pivothigh(high, liqLen, liqLen)
liqLow = ta.pivotlow (low, liqLen, liqLen)
var float[] liq_highs = array.new<float>()
var float[] liq_lows = array.new<float>()
if not na(liqHigh)
array.unshift(liq_highs, liqHigh)
if array.size(liq_highs) > 50
array.pop(liq_highs)
if not na(liqLow)
array.unshift(liq_lows, liqLow)
if array.size(liq_lows) > 50
array.pop(liq_lows)

liqATR = ta.atr(10)
liqDetect(level, prices) =>
int count = 0
float minVal = na
float maxVal = na
for i = 0 to array.size(prices) - 1
float p = prices.get(i)
if p < level + (liqATR/liqMargin) and p > level - (liqATR/liqMargin)
count += 1
minVal := na(minVal) ? p : math.min(minVal, p)
maxVal := na(maxVal) ? p : math.max(maxVal, p)
if count > 2
[minVal, maxVal]
else
[na, na]

var box[] liqBuyZones = array.new<box>()
var box[] liqSellZones = array.new<box>()

if bar_index > 0
if array.size(liq_highs) > 2 and showLiqBuy
[liMin, liMax] = liqDetect(liq_highs.get(0), liq_highs)
if not na(liMin)
bool updated = false
if array.size(liqBuyZones) > 0
for i = 0 to array.size(liqBuyZones) - 1
box b = liqBuyZones.get(i)
if close < b.get_top() and close > b.get_bottom()
b.set_top(liMax + (liqATR/liqMargin))
b.set_bottom(liMin - (liqATR/liqMargin))
b.set_right(bar_index)
updated := true
break
if not updated
box newBox = box.new(bar_index - liqLen, liMax + (liqATR/liqMargin),
bar_index + liqLen, liMin - (liqATR/liqMargin),
bgcolor=color.new(color.green,80), border_color=color.new(color.green,0))
array.unshift(liqBuyZones, newBox)
if array.size(liqBuyZones) > 5
box oldBox = array.pop(liqBuyZones)
oldBox.delete()
if array.size(liq_lows) > 2 and showLiqSell
[liMinS, liMaxS] = liqDetect(liq_lows.get(0), liq_lows)
if not na(liMinS)
bool updatedS = false
if array.size(liqSellZones) > 0
for i = 0 to array.size(liqSellZones) - 1
box b = liqSellZones.get(i)
if close < b.get_top() and close > b.get_bottom()
b.set_top(liMaxS + (liqATR/liqMargin))
b.set_bottom(liMinS - (liqATR/liqMargin))
b.set_right(bar_index)
updatedS := true
break
if not updatedS
box newBoxS = box.new(bar_index - liqLen, liMaxS + (liqATR/liqMargin),
bar_index + liqLen, liMinS - (liqATR/liqMargin),
bgcolor=color.new(color.red,80), border_color=color.new(color.red,0))
array.unshift(liqSellZones, newBoxS)
if array.size(liqSellZones) > 5
box oldBoxS = array.pop(liqSellZones)
oldBoxS.delete()

// === Plotting ===
// Usa size.normal para flechas más grandes; puedes cambiarlo a size.small, size.large, etc.
plotshape(buyAllowed, title="Buy Signal", style=shape.arrowup, location=location.belowbar, color=buyColor, size=size.normal)
plotshape(sellAllowed, title="Sell Signal", style=shape.arrowdown, location=location.abovebar, color=sellColor, size=size.normal)

// Swing levels
plot(lastSwingHigh, title="Swing High", color=color.gray, style=plot.style_linebr)
plot(lastSwingLow, title="Swing Low", color=color.gray, style=plot.style_linebr)

// Alertas
alertcondition(buyAllowed, title="Buy Alert", message="Sweep+BOS Buy signal on {{ticker}} @ {{close}}")
alertcondition(sellAllowed, title="Sell Alert", message="Sweep+BOS Sell signal on {{ticker}} @ {{close}}")

免責事項

これらの情報および投稿は、TradingViewが提供または保証する金融、投資、取引、またはその他の種類のアドバイスや推奨を意図したものではなく、またそのようなものでもありません。詳しくは利用規約をご覧ください。