OPEN-SOURCE SCRIPT

Liquidity & SMT Detector

66
//version=5
indicator("Liquidity & SMT Detector", overlay=true, max_lines_count=500, max_labels_count=500)

// ============================================
// INPUT SETTINGS
// ============================================

// Group 1: Liquidity Detection
swing_length = input.int(10, "Swing Length", minval=3, maxval=50, group="Liquidity Detection")
line_color_high = input.color(color.red, "High Line Color", group="Liquidity Detection")
line_color_low = input.color(color.green, "Low Line Color", group="Liquidity Detection")
line_width = input.int(2, "Line Width", minval=1, maxval=5, group="Liquidity Detection")
show_labels = input.bool(true, "Show H/L Labels", group="Liquidity Detection")

// Group 2: Displacement Detection
enable_displacement = input.bool(true, "Enable Displacement Detection", group="Displacement")
displacement_multiplier = input.float(2.0, "Size Multiplier", minval=1.5, maxval=5.0, step=0.1, group="Displacement")
displacement_period = input.int(20, "Average Period", minval=10, maxval=50, group="Displacement")
displacement_color_bull = input.color(color.new(color.aqua, 70), "Bullish Color", group="Displacement")
displacement_color_bear = input.color(color.new(color.orange, 70), "Bearish Color", group="Displacement")
show_displacement_label = input.bool(true, "Show Labels", group="Displacement")

// Group 3: SMT Detection
enable_smt = input.bool(true, "Enable SMT Detection", group="SMT Divergence")
nq_symbol = input.string("NQ1!", "Nasdaq Symbol", group="SMT Divergence")
es_symbol = input.string("ES1!", "S&P500 Symbol", group="SMT Divergence")
smt_lookback = input.int(20, "Lookback Period", minval=5, maxval=100, group="SMT Divergence")
smt_line_color = input.color(color.yellow, "SMT Line Color", group="SMT Divergence")
smt_text_color = input.color(color.yellow, "SMT Text Color", group="SMT Divergence")

// ============================================
// ARRAYS FOR LINE/LABEL MANAGEMENT
// ============================================

var line[] high_lines = array.new_line()
var line[] low_lines = array.new_line()
var label[] high_labels = array.new_label()
var label[] low_labels = array.new_label()
var float[] high_levels = array.new_float()
var float[] low_levels = array.new_float()

// ============================================
// FUNCTION: DETECT SWING HIGHS
// ============================================

isSwingHigh(len) =>
highestBar = ta.highestbars(high, len * 2 + 1)
highestBar == -len

// ============================================
// FUNCTION: DETECT SWING LOWS
// ============================================

isSwingLow(len) =>
lowestBar = ta.lowestbars(low, len * 2 + 1)
lowestBar == -len

// ============================================
// SWING HIGH DETECTION & LINE DRAWING
// ============================================

if isSwingHigh(swing_length)
swing_high = high[swing_length]
new_line = line.new(bar_index - swing_length, swing_high, bar_index, swing_high, color=line_color_high, width=line_width, style=line.style_dashed)
array.push(high_lines, new_line)
array.push(high_levels, swing_high)
if show_labels
new_label = label.new(bar_index - swing_length, swing_high, "H", color=color.new(line_color_high, 80), textcolor=line_color_high, style=label.style_label_down, size=size.small)
array.push(high_labels, new_label)

// ============================================
// SWING LOW DETECTION & LINE DRAWING
// ============================================

if isSwingLow(swing_length)
swing_low = low[swing_length]
new_line = line.new(bar_index - swing_length, swing_low, bar_index, swing_low, color=line_color_low, width=line_width, style=line.style_dashed)
array.push(low_lines, new_line)
array.push(low_levels, swing_low)
if show_labels
new_label = label.new(bar_index - swing_length, swing_low, "L", color=color.new(line_color_low, 80), textcolor=line_color_low, style=label.style_label_up, size=size.small)
array.push(low_labels, new_label)

// ============================================
// UPDATE EXISTING LINES & CHECK FOR SWEEPS
// ============================================

if array.size(high_lines) > 0
for i = array.size(high_lines) - 1 to 0
current_line = array.get(high_lines, i)
current_level = array.get(high_levels, i)
if close > current_level
line.delete(current_line)
array.remove(high_lines, i)
array.remove(high_levels, i)
if show_labels and i < array.size(high_labels)
label.delete(array.get(high_labels, i))
array.remove(high_labels, i)
else
line.set_x2(current_line, bar_index)

if array.size(low_lines) > 0
for i = array.size(low_lines) - 1 to 0
current_line = array.get(low_lines, i)
current_level = array.get(low_levels, i)
if close < current_level
line.delete(current_line)
array.remove(low_lines, i)
array.remove(low_levels, i)
if show_labels and i < array.size(low_labels)
label.delete(array.get(low_labels, i))
array.remove(low_labels, i)
else
line.set_x2(current_line, bar_index)

// ============================================
// DISPLACEMENT CANDLE DETECTION
// ============================================

body_size = math.abs(close - open)
avg_body = ta.sma(math.abs(close - open), displacement_period)
is_displacement = enable_displacement and body_size > (avg_body * displacement_multiplier)
is_bullish = close > open

bgcolor(is_displacement ? (is_bullish ? displacement_color_bull : displacement_color_bear) : na)

if is_displacement and show_displacement_label
label.new(bar_index, is_bullish ? high : low, "D", color=color.new(is_bullish ? color.aqua : color.orange, 50), textcolor=is_bullish ? color.aqua : color.orange, style=is_bullish ? label.style_label_up : label.style_label_down, size=size.tiny)

// ============================================
// SMT DIVERGENCE DETECTION
// ============================================

current_symbol = syminfo.ticker
comparison_symbol = str.contains(current_symbol, "NQ") ? es_symbol : nq_symbol
comparison_high = request.security(comparison_symbol, timeframe.period, high, lookahead=barmerge.lookahead_off)
comparison_low = request.security(comparison_symbol, timeframe.period, low, lookahead=barmerge.lookahead_off)

var float prev_current_low = na
var float prev_comparison_low = na
var int prev_swing_bar = na

current_is_swing_low = isSwingLow(swing_length)
comparison_is_swing_low = ta.lowestbars(comparison_low, swing_length * 2 + 1) == -swing_length

if enable_smt and current_is_swing_low
current_swing_low = low[swing_length]
comparison_swing_low = comparison_low[swing_length]
if not na(prev_current_low) and not na(prev_comparison_low)
current_lower = current_swing_low < prev_current_low
comparison_lower = comparison_swing_low < prev_comparison_low
is_smt = (current_lower and not comparison_lower) or (not current_lower and comparison_lower)
if is_smt
smt_line = line.new(prev_swing_bar, prev_current_low, bar_index - swing_length, current_swing_low, color=smt_line_color, width=2, style=line.style_solid)
mid_bar = math.round((prev_swing_bar + bar_index - swing_length) / 2)
mid_price = (prev_current_low + current_swing_low) / 2
label.new(mid_bar, mid_price, "SMT", color=color.new(smt_line_color, 80), textcolor=smt_text_color, style=label.style_label_center, size=size.normal)
prev_current_low := current_swing_low
prev_comparison_low := comparison_swing_low
prev_swing_bar := bar_index - swing_length

// ============================================
// ALERTS
// ============================================

alertcondition(array.size(high_lines) < array.size(high_lines)[1], title="Liquidity Sweep High", message="High liquidity swept at {{close}}")
alertcondition(array.size(low_lines) < array.size(low_lines)[1], title="Liquidity Sweep Low", message="Low liquidity swept at {{close}}")

alertcondition(is_displacement, title="Displacement Candle", message="Displacement candle detected at {{close}}")

כתב ויתור

המידע והפרסומים אינם אמורים להיות, ואינם מהווים, עצות פיננסיות, השקעות, מסחר או סוגים אחרים של עצות או המלצות שסופקו או מאושרים על ידי TradingView. קרא עוד בתנאים וההגבלות.