Zero Lag Liquidity [AlgoAlpha]

AlgoAlpha · study · 172 行 · 点赞 5,864 · TradingView 原页

本页源码来自 TradingView 公开发布的开源脚本,版权归原作者所有, 请遵循其原始许可(Pine 脚本常见 CC BY-NC-SA / MPL-2.0 / MIT)。 本项目仅用于研究检索与许可范围内的移植。

Pine Script

//@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")

← 返回列表