PROTECTED SOURCE SCRIPT
Institutions order spikes spotter

//version=5
indicator("Volume Spike — QuickFire (TF-Adaptive)", overlay=true, max_labels_count=500)
//––– Helpers –––
barsFromMinutes(mins, avgBarMs) =>
ms = mins * 60000.0
int(math.max(2, math.round(ms / math.max(1.0, nz(avgBarMs, 60000.0)))))
alphaFromLen(lenBarsFloat) =>
lb = math.max(2.0, lenBarsFloat)
2.0 / (lb + 1.0) // EMA alpha
//––– Inputs –––
useMinutesHorizon = input.bool(true, "Use Minutes Horizon (TF-adaptive)")
presetMinutes = input.string("120","Horizon Preset (min)", options=["30","60","120","240","480"])
horizonMinutes = input.int(240, "Custom Horizon (min) if preset OFF", minval=10, maxval=24*60)
usePresetMins = input.bool(true, "Use Preset")
// Sensitivity (LOOSE defaults)
multK = input.float(2.2, "K: vol > baseline × K", minval=1.1, step=0.1)
zThresh = input.float(2.5, "Z: vol > mean + Z·stdev", minval=1.5, step=0.1)
requireBoth = input.bool(false, "Require BOTH (K & Z). If OFF → EITHER")
// Optional filters (OFF by default)
useNewExtreme = input.bool(false, "Require New Extreme vs Prior Max (OFF)")
priorWinBarsInp = input.int(100, "Prior-Max Window (bars)", minval=20, maxval=5000)
priorFactor = input.float(1.20, "New Extreme ≥ priorMax ×", minval=1.0, step=0.05)
minDollarVol = input.float(0.0, "Min Dollar-Volume (price×vol×mult) — 0=off", step=1.0)
contractMult = input.float(1.0, "Contract/Dollar Multiplier (e.g., NQ 20, MNQ 2)", step=0.1)
sessionOnly = input.bool(false, "Restrict to Session (OFF)")
sess = input.session("0830-1600", "Session (exchange tz)")
earlyDetect = input.bool(true, "Early Intrabar Detection")
cooldownMins = input.int(10, "Cooldown Minutes", minval=0, maxval=24*60)
markerSize = input.string("normal", "Marker Size", options=["tiny","small","normal","large","huge"])
showLabel = input.bool(false, "Show ratio label")
shadeNear = input.bool(true, "Shade near-misses (only one condition)")
colUp = color.new(color.teal, 0)
colDn = color.new(color.red, 0)
colBgHit = color.new(color.yellow, 80)
colBgNear = color.new(color.silver, 88)
//––– Derived (minutes → bars → alphas) –––
avgBarMs = ta.sma(time - time[1], 50)
useMin = usePresetMins ? str.tonumber(presetMinutes) : horizonMinutes
lenEffBars = useMinutesHorizon ? barsFromMinutes(useMin, avgBarMs) : useMin
lenEffF = float(lenEffBars)
alphaVol = alphaFromLen(lenEffF)
alphaATR = alphaFromLen(math.max(10.0, lenEffF/2.0))
cooldownBars = useMinutesHorizon ? barsFromMinutes(cooldownMins, avgBarMs) : cooldownMins
//––– Guards –––
inSess = sessionOnly ? not na(time(timeframe.period, sess)) : true
//––– EW stats (no series-int) –––
vol = volume
var float vMean = na
var float vVar = na
vMeanPrev = nz(vMean[1], vol)
vMean := na(vMean[1]) ? vol : vMeanPrev + alphaVol * (vol - vMeanPrev)
delta = vol - vMeanPrev
vVar := na(vVar[1]) ? 0.0 : (1.0 - alphaVol) * (nz(vVar[1]) + alphaVol * delta * delta)
vStd = math.sqrt(math.max(vVar, 0.0))
// EW ATR (for optional anatomy later if you want)
trueRange = math.max(high - low, math.max(math.abs(high - close[1]), math.abs(low - close[1])))
var float atrEW = na
atrEW := na(atrEW[1]) ? trueRange : atrEW[1] + alphaATR * (trueRange - atrEW[1])
// Intrabar scaling
elapsedMs = barstate.isrealtime ? (timenow - time) : nz(avgBarMs, 0)
frac = earlyDetect ? math.max(0.0, math.min(1.0, elapsedMs / math.max(1.0, nz(avgBarMs, 1)))) : 1.0
// Thresholds
thMult = nz(vMean, 0) * multK
thZ = nz(vMean, 0) + zThresh * vStd
thMultEf = thMult * frac
thZEf = thZ * frac
condMult = vol > thMultEf
condZ = vol > thZEf
condCore = requireBoth ? (condMult and condZ) : (condMult or condZ)
// Optional filters (default OFF)
priorMax = ta.highest(vol[1], priorWinBarsInp)
condNewMax = not useNewExtreme or (vol >= priorMax * priorFactor)
dollarVol = close * vol * contractMult
condDVol = (minDollarVol <= 0) or (dollarVol >= minDollarVol)
// Cooldown
var int lastSpikeBar = -1000000000
coolOK = (bar_index - lastSpikeBar) > cooldownBars
// Final event (minimal gates)
isSpike = inSess and condCore and condNewMax and condDVol and coolOK
// Near-miss shading (only one condition true)
nearMiss = shadeNear and inSess and not isSpike and (condMult != condZ) and (condMult or condZ)
// Severity
ratio = nz(vol) / nz(vMean, 1.0)
dirUp = close >= open
// Update cooldown stamp
if isSpike
lastSpikeBar := bar_index
//––– Plotting –––
bgcolor(isSpike ? colBgHit : nearMiss ? colBgNear : na)
isUp = isSpike and dirUp
isDn = isSpike and not dirUp
// const-size markers
plotshape(markerSize == "tiny" and isUp, title="Spike Up tiny", style=shape.triangleup, color=colUp, location=location.belowbar, size=size.tiny)
plotshape(markerSize == "small" and isUp, title="Spike Up small", style=shape.triangleup, color=colUp, location=location.belowbar, size=size.small)
plotshape(markerSize == "normal" and isUp, title="Spike Up normal", style=shape.triangleup, color=colUp, location=location.belowbar, size=size.normal)
plotshape(markerSize == "large" and isUp, title="Spike Up large", style=shape.triangleup, color=colUp, location=location.belowbar, size=size.large)
plotshape(markerSize == "huge" and isUp, title="Spike Up huge", style=shape.triangleup, color=colUp, location=location.belowbar, size=size.huge)
plotshape(markerSize == "tiny" and isDn, title="Spike Dn tiny", style=shape.triangledown, color=colDn, location=location.abovebar, size=size.tiny)
plotshape(markerSize == "small" and isDn, title="Spike Dn small", style=shape.triangledown, color=colDn, location=location.abovebar, size=size.small)
plotshape(markerSize == "normal" and isDn, title="Spike Dn normal", style=shape.triangledown, color=colDn, location=location.abovebar, size=size.normal)
plotshape(markerSize == "large" and isDn, title="Spike Dn large", style=shape.triangledown, color=colDn, location=location.abovebar, size=size.large)
plotshape(markerSize == "huge" and isDn, title="Spike Dn huge", style=shape.triangledown, color=colDn, location=location.abovebar, size=size.huge)
// Optional label
if showLabel and isSpike
y = dirUp ? low : high
st = dirUp ? label.style_label_down : label.style_label_up
c = dirUp ? colUp : colDn
label.new(bar_index, y, str.tostring(ratio, "#.##x"), xloc=xloc.bar_index, style=st, textcolor=color.white, color=c)
// Alerts
alertcondition(isSpike, title="Volume Spike (Any)", message="Volume spike detected.")
alertcondition(isSpike and isUp, title="Volume Spike Up", message="UP volume spike.")
alertcondition(isSpike and isDn, title="Volume Spike Down", message="DOWN volume spike.")
// Hidden refs (optional)
plot(ratio, title="Severity Ratio", display=display.none)
plot(dollarVol, title="Dollar Volume", display=display.none)
plot(atrEW, title="EW ATR", display=display.none)
indicator("Volume Spike — QuickFire (TF-Adaptive)", overlay=true, max_labels_count=500)
//––– Helpers –––
barsFromMinutes(mins, avgBarMs) =>
ms = mins * 60000.0
int(math.max(2, math.round(ms / math.max(1.0, nz(avgBarMs, 60000.0)))))
alphaFromLen(lenBarsFloat) =>
lb = math.max(2.0, lenBarsFloat)
2.0 / (lb + 1.0) // EMA alpha
//––– Inputs –––
useMinutesHorizon = input.bool(true, "Use Minutes Horizon (TF-adaptive)")
presetMinutes = input.string("120","Horizon Preset (min)", options=["30","60","120","240","480"])
horizonMinutes = input.int(240, "Custom Horizon (min) if preset OFF", minval=10, maxval=24*60)
usePresetMins = input.bool(true, "Use Preset")
// Sensitivity (LOOSE defaults)
multK = input.float(2.2, "K: vol > baseline × K", minval=1.1, step=0.1)
zThresh = input.float(2.5, "Z: vol > mean + Z·stdev", minval=1.5, step=0.1)
requireBoth = input.bool(false, "Require BOTH (K & Z). If OFF → EITHER")
// Optional filters (OFF by default)
useNewExtreme = input.bool(false, "Require New Extreme vs Prior Max (OFF)")
priorWinBarsInp = input.int(100, "Prior-Max Window (bars)", minval=20, maxval=5000)
priorFactor = input.float(1.20, "New Extreme ≥ priorMax ×", minval=1.0, step=0.05)
minDollarVol = input.float(0.0, "Min Dollar-Volume (price×vol×mult) — 0=off", step=1.0)
contractMult = input.float(1.0, "Contract/Dollar Multiplier (e.g., NQ 20, MNQ 2)", step=0.1)
sessionOnly = input.bool(false, "Restrict to Session (OFF)")
sess = input.session("0830-1600", "Session (exchange tz)")
earlyDetect = input.bool(true, "Early Intrabar Detection")
cooldownMins = input.int(10, "Cooldown Minutes", minval=0, maxval=24*60)
markerSize = input.string("normal", "Marker Size", options=["tiny","small","normal","large","huge"])
showLabel = input.bool(false, "Show ratio label")
shadeNear = input.bool(true, "Shade near-misses (only one condition)")
colUp = color.new(color.teal, 0)
colDn = color.new(color.red, 0)
colBgHit = color.new(color.yellow, 80)
colBgNear = color.new(color.silver, 88)
//––– Derived (minutes → bars → alphas) –––
avgBarMs = ta.sma(time - time[1], 50)
useMin = usePresetMins ? str.tonumber(presetMinutes) : horizonMinutes
lenEffBars = useMinutesHorizon ? barsFromMinutes(useMin, avgBarMs) : useMin
lenEffF = float(lenEffBars)
alphaVol = alphaFromLen(lenEffF)
alphaATR = alphaFromLen(math.max(10.0, lenEffF/2.0))
cooldownBars = useMinutesHorizon ? barsFromMinutes(cooldownMins, avgBarMs) : cooldownMins
//––– Guards –––
inSess = sessionOnly ? not na(time(timeframe.period, sess)) : true
//––– EW stats (no series-int) –––
vol = volume
var float vMean = na
var float vVar = na
vMeanPrev = nz(vMean[1], vol)
vMean := na(vMean[1]) ? vol : vMeanPrev + alphaVol * (vol - vMeanPrev)
delta = vol - vMeanPrev
vVar := na(vVar[1]) ? 0.0 : (1.0 - alphaVol) * (nz(vVar[1]) + alphaVol * delta * delta)
vStd = math.sqrt(math.max(vVar, 0.0))
// EW ATR (for optional anatomy later if you want)
trueRange = math.max(high - low, math.max(math.abs(high - close[1]), math.abs(low - close[1])))
var float atrEW = na
atrEW := na(atrEW[1]) ? trueRange : atrEW[1] + alphaATR * (trueRange - atrEW[1])
// Intrabar scaling
elapsedMs = barstate.isrealtime ? (timenow - time) : nz(avgBarMs, 0)
frac = earlyDetect ? math.max(0.0, math.min(1.0, elapsedMs / math.max(1.0, nz(avgBarMs, 1)))) : 1.0
// Thresholds
thMult = nz(vMean, 0) * multK
thZ = nz(vMean, 0) + zThresh * vStd
thMultEf = thMult * frac
thZEf = thZ * frac
condMult = vol > thMultEf
condZ = vol > thZEf
condCore = requireBoth ? (condMult and condZ) : (condMult or condZ)
// Optional filters (default OFF)
priorMax = ta.highest(vol[1], priorWinBarsInp)
condNewMax = not useNewExtreme or (vol >= priorMax * priorFactor)
dollarVol = close * vol * contractMult
condDVol = (minDollarVol <= 0) or (dollarVol >= minDollarVol)
// Cooldown
var int lastSpikeBar = -1000000000
coolOK = (bar_index - lastSpikeBar) > cooldownBars
// Final event (minimal gates)
isSpike = inSess and condCore and condNewMax and condDVol and coolOK
// Near-miss shading (only one condition true)
nearMiss = shadeNear and inSess and not isSpike and (condMult != condZ) and (condMult or condZ)
// Severity
ratio = nz(vol) / nz(vMean, 1.0)
dirUp = close >= open
// Update cooldown stamp
if isSpike
lastSpikeBar := bar_index
//––– Plotting –––
bgcolor(isSpike ? colBgHit : nearMiss ? colBgNear : na)
isUp = isSpike and dirUp
isDn = isSpike and not dirUp
// const-size markers
plotshape(markerSize == "tiny" and isUp, title="Spike Up tiny", style=shape.triangleup, color=colUp, location=location.belowbar, size=size.tiny)
plotshape(markerSize == "small" and isUp, title="Spike Up small", style=shape.triangleup, color=colUp, location=location.belowbar, size=size.small)
plotshape(markerSize == "normal" and isUp, title="Spike Up normal", style=shape.triangleup, color=colUp, location=location.belowbar, size=size.normal)
plotshape(markerSize == "large" and isUp, title="Spike Up large", style=shape.triangleup, color=colUp, location=location.belowbar, size=size.large)
plotshape(markerSize == "huge" and isUp, title="Spike Up huge", style=shape.triangleup, color=colUp, location=location.belowbar, size=size.huge)
plotshape(markerSize == "tiny" and isDn, title="Spike Dn tiny", style=shape.triangledown, color=colDn, location=location.abovebar, size=size.tiny)
plotshape(markerSize == "small" and isDn, title="Spike Dn small", style=shape.triangledown, color=colDn, location=location.abovebar, size=size.small)
plotshape(markerSize == "normal" and isDn, title="Spike Dn normal", style=shape.triangledown, color=colDn, location=location.abovebar, size=size.normal)
plotshape(markerSize == "large" and isDn, title="Spike Dn large", style=shape.triangledown, color=colDn, location=location.abovebar, size=size.large)
plotshape(markerSize == "huge" and isDn, title="Spike Dn huge", style=shape.triangledown, color=colDn, location=location.abovebar, size=size.huge)
// Optional label
if showLabel and isSpike
y = dirUp ? low : high
st = dirUp ? label.style_label_down : label.style_label_up
c = dirUp ? colUp : colDn
label.new(bar_index, y, str.tostring(ratio, "#.##x"), xloc=xloc.bar_index, style=st, textcolor=color.white, color=c)
// Alerts
alertcondition(isSpike, title="Volume Spike (Any)", message="Volume spike detected.")
alertcondition(isSpike and isUp, title="Volume Spike Up", message="UP volume spike.")
alertcondition(isSpike and isDn, title="Volume Spike Down", message="DOWN volume spike.")
// Hidden refs (optional)
plot(ratio, title="Severity Ratio", display=display.none)
plot(dollarVol, title="Dollar Volume", display=display.none)
plot(atrEW, title="EW ATR", display=display.none)
보호된 스크립트입니다
이 스크립트는 비공개 소스로 게시됩니다. 하지만 제한 없이 자유롭게 사용할 수 있습니다 — 여기에서 자세히 알아보기.
면책사항
이 정보와 게시물은 TradingView에서 제공하거나 보증하는 금융, 투자, 거래 또는 기타 유형의 조언이나 권고 사항을 의미하거나 구성하지 않습니다. 자세한 내용은 이용 약관을 참고하세요.
보호된 스크립트입니다
이 스크립트는 비공개 소스로 게시됩니다. 하지만 제한 없이 자유롭게 사용할 수 있습니다 — 여기에서 자세히 알아보기.
면책사항
이 정보와 게시물은 TradingView에서 제공하거나 보증하는 금융, 투자, 거래 또는 기타 유형의 조언이나 권고 사항을 의미하거나 구성하지 않습니다. 자세한 내용은 이용 약관을 참고하세요.