本页源码来自 TradingView 公开发布的开源脚本,版权归原作者所有, 请遵循其原始许可(Pine 脚本常见 CC BY-NC-SA / MPL-2.0 / MIT)。 本项目仅用于研究检索与许可范围内的移植。
//@version=6
//────────────────────────────────────────────────────────────────────── Indicator Header
indicator("Zero Lag Liquidity [AlgoAlpha]", "AlgoAlpha – Zero Lag Liq", overlay = true, max_lines_count = 500, max_labels_count = 500, behind_chart = false)
//────────────────────────────────────────────────────────────────────── Inputs
ltf = input.timeframe("3", title = "Lower Timeframe", tooltip = "The lower timeframe used to build the wick profile. This determines the resolution of the volume and price data used for liquidity calculations.", group = "Wick Profile")
binCount = input.int(7, title = "Profile Bin Count", minval = 1, tooltip = "Number of bins to divide the price range into for the wick profile. Higher values provide more granularity.", group = "Wick Profile")
wickMult = input.float(2.0, title = "Wick Multiplier", minval = 0.1, step = 0.1, tooltip = "Multiplier for the average wick size to determine significant wick events. Higher values require larger wicks to trigger highlights.", group = "Wick Profile")
trnd = input.bool(true, title = "Show Liquidity Trend", tooltip = "Enable to display the trend based on whether liquidity levels are being broken.", group = "Appearance")
brk = input.bool(true, title = "Show Liquidity Breaks", tooltip = "Enable to highlight when the price breaks through a liquidity level.", group = "Appearance")
rej = input.bool(true, title = "Show Liquidity Rejections", tooltip = "Enable to highlight when the price rejects off a liquidity level.", group = "Appearance")
lblPercent = input.bool(true, title = "Labels Show % Strength", tooltip = "If true, labels display the level's volume as a percentage of the cumulative volume of all active levels. If false, labels display the absolute volume recorded at creation.", group = "Appearance")
lblSizeOpt = input.string("Small", title = "Label Text Size", options=["Tiny","Small","Medium","Large"], group = "Appearance")
lblSizeConst = lblSizeOpt == "Tiny" ? size.tiny : lblSizeOpt == "Small" ? size.small : lblSizeOpt == "Medium" ? size.normal : size.large
bullCol = input.color(#00ffbb, title = "Bullish Colour", tooltip = "Color used for bullish (buy-side) liquidity levels.", group = "Appearance")
bearCol = input.color(#ff1100, title = "Bearish Colour", tooltip = "Color used for bearish (sell-side) liquidity levels.", group = "Appearance")
//────────────────────────────────────────────────────────────────────── Core Calculations
filter = ta.ema(ta.hma(close, 7), 21)
vol = ta.rsi(volume, 14)
lower_wick = math.min(close, open) - low
upper_wick = high - math.max(close, open)
avg_wick = (lower_wick + upper_wick) / 2
a_w = ta.sma(avg_wick, 21)
highlightRaw = vol > 60 and avg_wick > a_w * wickMult
highlight = highlightRaw and upper_wick != lower_wick
//────────────────────────────────────────────────────────────────────── Lower-TF Data Acquisition
ltVolsSeries = request.security_lower_tf(syminfo.tickerid, ltf, volume)
ltPricesSeries = request.security_lower_tf(syminfo.tickerid, ltf, close)
//────────────────────────────────────────────────────────────────────── Wick Profile & POC Function
f_wick_poc(float top, float bot, float[] pricesArr, float[] volsArr, int bins) =>
if array.size(pricesArr) == 0 or array.size(volsArr) == 0 or top == bot
na
else
range_ = top - bot
seg = range_ / bins
bounds = array.new_float()
volsBin = array.new_float()
for i = 0 to bins
array.push(bounds, bot + i * seg)
sizeP = array.size(pricesArr)
for i = 0 to bins - 1
totalVol = 0.0
for j = 0 to sizeP - 1
pr = array.get(pricesArr, j)
if pr >= array.get(bounds, i) and pr <= array.get(bounds, i + 1)
totalVol += array.get(volsArr, j)
array.push(volsBin, totalVol)
maxVol = array.max(volsBin)
pocIdx = array.indexof(volsBin, maxVol)
(array.get(bounds, pocIdx) + array.get(bounds, pocIdx + 1)) / 2
//────────────────────────────────────────────────────────────────────── Processing & Rendering
var line[] pocLines = array.new<line>()
var float[] pocPrices = array.new<float>()
var int[] pocTypes = array.new<int>()
var label[] pocLabels = array.new<label>()
var float[] pocVols = array.new<float>()
var line[] pocBodyLines = array.new<line>()
var linefill[] pocFills = array.new<linefill>()
isRedBar = highlight and lower_wick > upper_wick
isGreenBar = highlight and upper_wick > lower_wick
float wickTop = na
float wickBot = na
if isRedBar
wickTop := math.min(close, open)
wickBot := low
else if isGreenBar
wickTop := high
wickBot := math.max(close, open)
//────────────────────────────────────────────────────────────────────── New Line Creation
if highlight and not na(ltPricesSeries) and not na(ltVolsSeries)
poc = f_wick_poc(wickTop, wickBot, ltPricesSeries, ltVolsSeries, binCount)
if not na(poc)
newLine = line.new(bar_index, poc, bar_index, poc, xloc.bar_index, extend.none,
color = isGreenBar ? bullCol : bearCol, width = 1)
array.unshift(pocLines, newLine)
array.unshift(pocPrices, poc)
array.unshift(pocTypes, isGreenBar ? 1 : -1)
array.unshift(pocVols, volume)
newLabel = label.new(bar_index, poc, text = "", xloc = xloc.bar_index, yloc = yloc.price,
color = chart.fg_color, textcolor = chart.fg_color, style = label.style_none, size = lblSizeConst)
array.unshift(pocLabels, newLabel)
float bodyPrice = isGreenBar ? wickBot : wickTop
bodyLine = line.new(bar_index, bodyPrice, bar_index, bodyPrice, xloc.bar_index, extend.none,
color = color.new(isGreenBar ? bullCol : bearCol, 80), width = 1)
array.unshift(pocBodyLines, bodyLine)
fillColor = color.new(isGreenBar ? bullCol : bearCol, 80)
fillObj = linefill.new(newLine, bodyLine, fillColor)
array.unshift(pocFills, fillObj)
//────────────────────────────────────────────────────────────────────── Line Management
maxStored = 500
if array.size(pocLines) > maxStored
array.pop(pocLines)
array.pop(pocPrices)
array.pop(pocTypes)
array.pop(pocLabels)
array.pop(pocVols)
array.pop(pocBodyLines)
array.pop(pocFills)
bullrej = false
bearrej = false
var trend = 0
brkk = 0
sumVols = 0.0
if array.size(pocVols) > 0
for sv = 0 to array.size(pocVols) - 1
sumVols += array.get(pocVols, sv)
if array.size(pocLines) > 0
for i = array.size(pocLines) - 1 to 0
if i < array.size(pocLines)
l = array.get(pocLines, i)
lvlPrice = array.get(pocPrices, i)
typ = array.get(pocTypes, i)
lab = array.get(pocLabels, i)
if not na(lab)
lab.set_xy(bar_index, lvlPrice)
vol_i = array.get(pocVols, i)
txt = lblPercent ? str.tostring(vol_i / sumVols * 100, format.percent) : str.tostring(vol_i, format.volume)
lab.set_text(txt)
if sumVols > 0
dominance = vol_i / sumVols
int maxTrans = 60
int trans = math.round((1 - dominance) * maxTrans)
trans := trans < 0 ? 0 : trans > maxTrans ? maxTrans : trans
l.set_color(typ == 1 ? color.new(bullCol, trans) : color.new(bearCol, trans))
bool done = typ == 1 ? (close > lvlPrice and close[1] > lvlPrice) : (close < lvlPrice and close[1] < lvlPrice)
if done
brkk := typ
trend := typ
array.remove(pocLines, i)
array.remove(pocPrices, i)
array.remove(pocTypes, i)
array.remove(pocLabels, i)
array.remove(pocVols, i)
array.remove(pocBodyLines, i)
array.remove(pocFills, i)
else
if high[1] > l.get_y1() and low[1] < l.get_y1() and l.get_x2()-l.get_x1() > 0
if hl2 > l.get_y2() and typ == -1
bullrej := true
else if hl2 < l.get_y2() and typ == 1
bearrej := true
l.set_x2(bar_index)
bodyL = array.get(pocBodyLines, i)
bodyL.set_x2(bar_index)
plotchar(bullrej and rej, "Bullish Rejection", "▲", location.belowbar, color.new(bullCol, 50), size = size.tiny)
plotchar(bearrej and rej, "Bearish Rejection", "▼", location.abovebar, color.new(bearCol, 50), size = size.tiny)
x = 7
lw = ta.lowest(x)
hg = ta.highest(x)
plotshape(brkk > 0 and brk ? lw : na, "Bullish Break", shape.labelup, location.absolute, color.new(bullCol, 30), text = "▲", textcolor = chart.fg_color, size = size.tiny)
plotshape(brkk < 0 and brk ? hg : na, "Bearish Break", shape.labeldown, location.absolute, color.new(bearCol, 30), text = "▼", textcolor = chart.fg_color, size = size.tiny)
candlecol = highlight ? (isRedBar ? bearCol : bullCol) : trnd ? (trend > 0 ? color.from_gradient(0.65, 0, 1, bullCol, chart.bg_color) : trend < 0 ? color.from_gradient(0.65, 0, 1, bearCol, chart.bg_color) : na) : na
plotcandle(open, high, low, close, "Custom Candle", candlecol, candlecol, bordercolor = candlecol)
//────────────────────────────────────────────────────────────────────── Alerts
alertcondition(bullrej and rej, title = "Bullish Rejection")
alertcondition(bearrej and rej, title = "Bearish Rejection")
alertcondition(brkk > 0 and brk, title = "Bullish Break")
alertcondition(brkk < 0 and brk, title = "Bearish Break")
alertcondition(trend > 0 and trnd, title = "Bullish Trend")
alertcondition(trend < 0 and trnd, title = "Bearish Trend")