Liquidity Sweep Filter [AlgoAlpha]

AlgoAlpha · study · 224 行 · 点赞 8,212 · TradingView 原页

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

Pine Script

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © AlgoAlpha
 
//@version=6
indicator("Liquidity Sweep Confluences [AlgoAlpha]", "AlgoAlpha - Liquidity Confluences", overlay=true, max_lines_count=500, max_boxes_count = 500, max_labels_count = 500)
 
// Trend Settings
len = input.int(12, "Length", minval=1, tooltip="The number of periods used for trend calculations. A longer length creates a smoother and longer term signal", group="Trend Settings")
mult = input.float(2.0, "Multiplier", minval=0.1, step=0.1, tooltip="Multiplier for the standard deviation calculation. Higher values create wider bands and makes the indicator more resistant to noise", group="Trend Settings")
src = input.source(close, "Source", tooltip="The price data used for calculations. Close is most common, but you can also use open, high, low, hl2 (high+low)/2, hlc3 (high+low+close)/3, or ohlc4 (open+high+low+close)/4", group="Trend Settings")
major_sweep_thresh = input.float(50, "Major Sweep Threshold", minval=0, tooltip="Threshold value that determines what constitutes a major liquidation sweep. Higher values mean only larger price movements will be considered major sweeps. Can only be 0-100, larger values will make it harder for sweeps to be considered 'major'", group="Trend Settings")
shw_mjr = input.bool(true, "Show Major Liquidations", tooltip="Toggle the display of major liquidation levels. These represent significant price levels where large position liquidations occurred", group="Trend Settings")
shw_mnr = input.bool(true, "Show Minor Liquidations", tooltip="Toggle the display of minor liquidation levels. These represent smaller price levels where position liquidations occurred", group="Trend Settings")
 
// Profile Settings
show_profile = input.bool(true, "Show Volume Profile", tooltip="Toggle the display of the volume profile visualization. When enabled, shows the distribution of trading volume across price levels", group="Profile Settings")
show_bounds = input.bool(true, "Show Bounding Box", tooltip="Toggle the display of the bounding box around the volume profile. Helps to clearly define the profile's boundaries", group="Profile Settings")
res = input.int(40, "Resolution", minval=1, tooltip="Number of bars in the volume profile. Higher values create more detailed profiles but may increase visual noise. Each bar represents a price range where volume occurred", group="Profile Settings")
scale = input.int(30, "Scale", minval=1, tooltip="Controls the horizontal width of the volume profile display. Higher values make the profile wider and more visible, while lower values make it more compact", group="Profile Settings")
 
// Appearance Settings
bullColor = input.color(#00ffbb, "Bullish Color", tooltip="Color used for bullish trends and indicators. This color appears when price action or indicators suggest upward momentum", group="Appearance Settings")
bearColor = input.color(#ff1100, "Bearish Color", tooltip="Color used for bearish trends and indicators. This color appears when price action or indicators suggest downward momentum", group="Appearance Settings")
pc1 = input.color(color.gray, "Profile Color", tooltip="Color of the volume profile visualization. This shows the distribution of trading volume across different price levels", group="Appearance Settings")
 
profileCalculation(start_index, end_index, res, scale) =>
    top_boundaries = array.new_float(res)
    bottom_boundaries = array.new_float(res)
    binlen = array.new_float(res)
    highs = array.new_float()
    lows = array.new_float()
    volumes = array.new_float()
 
    for i = bar_index-start_index to bar_index-end_index
        highs.push(high[i])
        lows.push(low[i])
        volumes.push(volume[i])
 
    maxx = array.max(highs)
    minn = array.min(lows)
    size = array.size(highs)
 
    poc = 0.0
 
    if size > 0
        step = (maxx - minn) / res
        granularity = res
        for i = 0 to granularity - 1
            bin_size = 0.0
            bottom = minn + (i * step)
            top = minn + ((i + 1) * step)
            bottom_boundaries.insert(i, bottom)
            top_boundaries.insert(i, top)
            for j = 0 to array.size(highs) - 1
                candle_above_hbar = lows.get(j) > top
                candle_below_hbar = highs.get(j) < bottom
                is_candle_in_bucket = not (candle_above_hbar or candle_below_hbar)
                bin_size += is_candle_in_bucket ? volumes.get(j) : 0
            array.insert(binlen, i, bin_size)
        boc = binlen.max()
        boci = binlen.indexof(boc) > 0 ? binlen.indexof(boc) : 0
        poc := math.avg(top_boundaries.get(boci), bottom_boundaries.get(boci))
 
    [top_boundaries, bottom_boundaries, binlen, poc]
 
 
 
basis = ta.sma(ta.ema(src, len), len)
deviation = ta.ema(math.abs(close - basis), len * 3) * mult
upper = basis + deviation
lower = basis - deviation
 
length = int(len*mult)
nvol = (volume - ta.lowest(volume, length)) / (ta.highest(volume, length) - ta.lowest(volume, length)) * 100
 
 
var float trend = 0.0
if close > upper
    trend := 1
if close < lower
    trend := -1
 
plot(trend < 0 ? upper : na, color=color.new(bearColor, 30), style=plot.style_linebr, title="Downtrend Line", linewidth = 3)
 
plot(trend > 0 ? lower : na, color=color.new(bullColor, 30), style=plot.style_linebr, title="Uptrend Line", linewidth = 3)
 
peakform   = high[1] > high and high[2] < high[1]
valleyform = low[1]  < low and low[2]  > low[1]
 
var aPeakLines   = array.new_line()    // For swing highs (used in downtrend)
var aValleyLines = array.new_line()    // For swing lows (used in uptrend)
var aPeakVols    = array.new_float()   // Corresponding volume levels
var aValleyVols  = array.new_float()   // Corresponding volume levels
var aPeakNVols    = array.new_float()   // Corresponding normalized volume levels
var aValleyNVols  = array.new_float()   // Corresponding normalized volume levels
 
if trend < 0
    if peakform and high[1] < upper
        l = line.new(bar_index-1, high[1], bar_index, high[1], color=color.new(bearColor, 100-nvol[1]), width = 2)
        array.push(aPeakLines, l)
        array.push(aPeakVols, volume[1])
        array.push(aPeakNVols, nvol[1])
else if trend > 0 and low[1] > lower
    if valleyform
        l = line.new(bar_index-1, low[1], bar_index, low[1], color=color.new(bullColor, 100-nvol[1]), width = 2)
        array.push(aValleyLines, l)
        array.push(aValleyVols, volume[1])
        array.push(aValleyNVols, nvol[1])
 
bullliq = 0.0
bearliq = 0.0
Nbullliq = 0.0
Nbearliq = 0.0
 
if aPeakLines.size() > 0
    qt = aPeakLines.size()
    
    for ln = qt - 1 to 0
        if ln < aPeakLines.size()
            currentLine = aPeakLines.get(ln)
            lineLevel = currentLine.get_y1()
            
            if high > lineLevel or upper < lineLevel
                if high > lineLevel
                    bearliq += aPeakVols.get(ln)
                    Nbearliq += aPeakNVols.get(ln)
                aPeakLines.remove(ln)
                aPeakVols.remove(ln)
                aPeakNVols.remove(ln)
            else
                currentLine.set_x2(bar_index)
                
    if aPeakLines.size() > 500
        aPeakLines.shift().delete()
        aPeakVols.shift()
        aPeakNVols.shift()
 
if aValleyLines.size() > 0
    qt = aValleyLines.size()
    
    for ln = qt - 1 to 0
        if ln < aValleyLines.size()
            currentLine = aValleyLines.get(ln)
            lineLevel = currentLine.get_y1()
            
            if low < lineLevel or lower > lineLevel
                if low < lineLevel
                    bullliq += aValleyVols.get(ln)
                    Nbullliq += aValleyNVols.get(ln)
 
                aValleyLines.remove(ln)
                aValleyVols.remove(ln)
                aValleyNVols.remove(ln)
            else
                currentLine.set_x2(bar_index)
                
    if aValleyLines.size() > 500
        aValleyLines.shift().delete()
        aValleyVols.shift()
        aValleyNVols.shift()
 
 
if bullliq > 0
    if Nbullliq < major_sweep_thresh and shw_mnr
        label.new(bar_index, lower, str.tostring(bullliq, format.volume), xloc.bar_index, yloc.price, color.new(bullColor, 70), label.style_label_up, size = size.tiny)
    else if Nbullliq > major_sweep_thresh and shw_mjr
        label.new(bar_index, lower, str.tostring(bullliq, format.volume), xloc.bar_index, yloc.price, color.new(bullColor, 70), label.style_label_up, size = size.tiny)
 
if bearliq > 0
    if Nbearliq < major_sweep_thresh and shw_mnr
        label.new(bar_index, upper, str.tostring(bearliq, format.volume), xloc.bar_index, yloc.price, color.new(bearColor, 70), label.style_label_down, size = size.tiny)
    else if Nbearliq > major_sweep_thresh and shw_mjr
        label.new(bar_index, upper, str.tostring(bearliq, format.volume), xloc.bar_index, yloc.price, color.new(bearColor, 70), label.style_label_down, size = size.tiny)
 
volatility = ta.atr(14)/2
 
plotchar(bullliq != 0 and Nbullliq > major_sweep_thresh ? low - volatility : na, "Strong Bullish Sweep", "▲", location.absolute, bullColor, size = size.tiny)
plotchar(bearliq != 0 and Nbearliq > major_sweep_thresh ? high + volatility : na, "Strong Bearish Sweep", "▼", location.absolute, bearColor, size = size.tiny)
plotchar(bullliq != 0 and Nbullliq > 0 ? low - volatility : na, "Bullish Sweep", "△", location.absolute, bullColor)
plotchar(bearliq != 0 and Nbearliq > 0 ? high + volatility : na, "Bearish Sweep", "▽", location.absolute, bearColor)
 
plotshape(ta.crossover(trend, 0) ? lower : na, "Bullish Trend", shape.labelup, location.absolute, color.new(bullColor, 50), text = "▲", textcolor = chart.fg_color, size = size.small)
plotshape(ta.crossunder(trend, 0) ? upper : na, "Bearish Trend", shape.labeldown, location.absolute, color.new(bearColor, 50), text = "▼", textcolor = chart.fg_color, size = size.small)
 
timer = ta.barssince(ta.cross(trend, 0))
 
profile_upper = ta.highest(math.max(1, nz(timer)))
profile_lower = ta.lowest(math.max(1, nz(timer)))
 
end_index = bar_index
start_index = (bar_index - timer) + (end_index > (bar_index - timer) ? 1 : 0)
 
// Call the profile calculation function
[top_boundaries, bottom_boundaries, binlen, poc] = profileCalculation(start_index, end_index, res, scale)
 
// Draw the profile based on the returned parameters
var boxes = array.new_box()
var br = array.new_box()
 
while boxes.size() > 0
    boxes.shift().delete()
 
while br.size() > 0
    br.shift().delete()
 
for i = 0 to res - 1
    if show_profile
        box_right = bar_index + 7 + scale // binlen.max()
        box_left = box_right - math.round(binlen.get(i)) / math.round(binlen.max()) * scale
        box_top = array.get(top_boundaries, i)
        box_bottom = array.get(bottom_boundaries, i)
        gradient_color = color.from_gradient(math.sin(binlen.get(i) * math.pi / binlen.max()) * binlen.max(), 0, binlen.max(), trend > 0 ? bullColor : bearColor, pc1)
        array.push(boxes, box.new(box_left, box_top, box_right, box_bottom, border_style = line.style_solid, border_color = gradient_color, border_width = 1, bgcolor = color.new(gradient_color, 10)))
 
if show_bounds
    br.push(box.new(start_index, profile_upper, end_index+scale+7, profile_lower, border_style = line.style_solid, border_color = color.new(chart.fg_color, 90), border_width = 1, bgcolor = color.new(chart.fg_color, 95)))
 
///////////ALERTS
alertcondition(ta.crossover(trend, 0), title="Bullish Trend", message="Bullish Trend")
alertcondition(ta.crossunder(trend, 0), title="Bearish Trend", message="Bearish Trend")
alertcondition(bullliq != 0 and Nbullliq > major_sweep_thresh, title="Strong Bullish Sweep", message="Strong Bullish Sweep")
alertcondition(bearliq != 0 and Nbearliq > major_sweep_thresh, title="Strong Bearish Sweep", message="Strong Bearish Sweep")
alertcondition(bullliq != 0 and Nbullliq > 0, title="Bullish Sweep", message="Bullish Sweep")
alertcondition(bearliq != 0 and Nbearliq > 0, title="Bearish Sweep", message="Bearish Sweep")

← 返回列表