smc_confluence_engine.pine
Copy
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © shubhamtaywade82
// ============================================================
// SMC Confluence Engine v4 [nemesis] — 4-Layer MTF Engine
// Pine Script v6 | indicator() | overlay=true
// ============================================================
// CRITICAL UPGRADE from v3:
// v3 had ONE flat HTF filter — a single EMA crossover gate.
// v4 enforces the correct 4-layer timeframe hierarchy:
//
// LAYER A — 🟥 HTF BIAS (4H + 1D)
// • 4H EMA9/21 bias direction
// • 4H premium / discount zone (50-bar range midpoint)
// • Hard block if 4H bias is neutral — NO TRADE
//
// LAYER B — 🟧 SETUP TIMEFRAME (1H)
// • 1H BOS / CHoCH detection via confirmed pivots
// • 1H structure trend (HH/HL vs LH/LL)
// • Confirms trade is planned — aligns with 4H
// • Hard block if 1H structure disagrees with 4H bias
//
// LAYER C — 🟨 ENTRY TIMEFRAME (15m)
// • 15m Order Block presence (price near active OB)
// • 15m Liquidity sweep (recent stop hunt)
// • Defines the entry zone precision
// • Adds to score; trade blocked without ≥1 active
//
// LAYER D — 🟩 EXECUTION TIMEFRAME (5m — chart TF)
// • 5m CHoCH trigger (mandatory, same as v3)
// • 5m OB tap
// • 5m liq sweep, VP, session, trendline confluence
//
// SIGNAL FIRES ONLY WHEN:
// 4H bias aligned AND 1H structure confirms AND
// 15m zone present AND 5m CHoCH trigger
//
// SCORE 0–8:
// +1 4H bias aligned
// +1 4H in discount (long) / premium (short)
// +1 1H CHoCH/BOS confirmed
// +1 1H structure trend aligns
// +1 15m OB active
// +1 15m sweep recent
// +1 5m OB tap
// +1 5m extra confluence (VP / Session / TL)
// ============================================================
//@version=6
indicator(
title = "SMC Confluence Engine v4 [nemesis]",
shorttitle = "SMC-CE v4",
overlay = true,
max_bars_back = 500,
max_labels_count = 300,
max_lines_count = 500,
max_boxes_count = 150
)
// ════════════════════════════════════════════════════════════
// ░░ INPUTS
// ════════════════════════════════════════════════════════════
// ── 4-Layer MTF Config (NEW) ──────────────────────────────
grp_mtf = "🗂 MTF Stack (4-Layer)"
htf_tf = input.timeframe("240", "Layer A — HTF Bias TF", group=grp_mtf,
tooltip="Default 4H. Use 240 for 4H, D for daily.")
setup_tf = input.timeframe("60", "Layer B — Setup TF", group=grp_mtf,
tooltip="Default 1H.")
entry_tf = input.timeframe("15", "Layer C — Entry Zone TF", group=grp_mtf,
tooltip="Default 15m.")
// Layer D = chart timeframe (execution = 5m)
htf_ema_fast = input.int(9, "HTF EMA Fast", minval=3, group=grp_mtf)
htf_ema_slow = input.int(21, "HTF EMA Slow", minval=5, group=grp_mtf)
htf_swing = input.int(5, "HTF Pivot Swing Length", minval=2, maxval=20, group=grp_mtf)
htf_pd_len = input.int(50, "HTF Premium/Discount Lookback", minval=10, maxval=200, group=grp_mtf)
setup_swing = input.int(5, "Setup Pivot Swing Length", minval=2, maxval=20, group=grp_mtf)
entry_ob_pct = input.float(0.3,"Entry OB Zone Proximity %", minval=0.05, step=0.05, group=grp_mtf,
tooltip="Price within this % of 15m OB midpoint counts as 'in zone'.")
entry_liq_lb = input.int(10, "Entry Sweep Lookback (bars on entry TF)", minval=3, maxval=50, group=grp_mtf)
show_htf_lines = input.bool(true, "Show 4H EMA lines", group=grp_mtf)
show_4h_zones = input.bool(true, "Show Premium/Discount zone", group=grp_mtf)
// ── Layer D: SMC (5m chart) ───────────────────────────────
grp_smc = "🟩 Layer D — 5m SMC"
smc_swing = input.int(10, "Swing Length (BOS/CHoCH)", minval=3, maxval=50, group=grp_smc)
ob_body_pct = input.float(0.3,"OB Min Body %", minval=0.05,step=0.05,group=grp_smc)
ob_expire = input.int(50, "OB Expires (bars)", minval=5, maxval=300, group=grp_smc)
liq_lookback = input.int(20, "Liquidity Swing Lookback", minval=5, maxval=100, group=grp_smc)
liq_wick_pct = input.float(0.1,"Sweep Min Wick %", minval=0.02,step=0.02,group=grp_smc)
show_ob = input.bool(true,"Show Order Block Boxes", group=grp_smc)
show_bos = input.bool(true,"Show BOS/CHoCH Lines", group=grp_smc)
show_liq = input.bool(true,"Show Liquidity Sweeps", group=grp_smc)
// ── Market Structure ──────────────────────────────────────
grp_ms = "📐 5m Market Structure"
ms_swing = input.int(10, "Structure Swing Length", minval=3, maxval=30, group=grp_ms)
show_ms = input.bool(true,"Show HH/HL/LH/LL", group=grp_ms)
show_ms_line = input.bool(true,"Show Structure Lines", group=grp_ms)
// ── Trendlines ────────────────────────────────────────────
grp_tl = "📏 Trendlines"
tl_pivot_len = input.int(10, "Pivot Length", minval=3, maxval=30, group=grp_tl)
tl_retest_pct = input.float(0.15,"Retest Zone %", minval=0.02,step=0.02,group=grp_tl)
show_tl = input.bool(true, "Show Lines", group=grp_tl)
show_tl_break = input.bool(true, "Show Labels", group=grp_tl)
// ── Session Levels ────────────────────────────────────────
grp_sess = "🕐 Session Levels"
show_pdh_pdl = input.bool(true,"Show PDH/PDL", group=grp_sess)
sess_liq_pct = input.float(0.1,"Level Zone %", minval=0.02,step=0.02,group=grp_sess)
asia_sess = input.session("0000-0800","Asia", group=grp_sess)
london_sess = input.session("0800-1600","London", group=grp_sess)
ny_sess = input.session("1300-2100","NY", group=grp_sess)
// ── Volume Profile ────────────────────────────────────────
grp_vp = "📊 Volume Profile"
vp_bars = input.int(100, "Lookback", minval=20,maxval=500, group=grp_vp)
vp_rows = input.int(24, "Rows", minval=10,maxval=50, group=grp_vp)
poc_zone_pct = input.float(0.2,"POC Zone %", minval=0.05,step=0.05,group=grp_vp)
show_vp = input.bool(true,"Show Lines", group=grp_vp)
// ── Signal Engine ─────────────────────────────────────────
grp_sig = "🚀 Signal Engine"
min_score = input.int(5, "Min Score (0–8)", minval=0,maxval=8, group=grp_sig,
tooltip="Recommended ≥5. With 4 mandatory gates each worth 1pt, minimum meaningful score is 4. Score 6+ = high conviction.")
sig_cooldown = input.int(5, "Cooldown (bars)", minval=1,maxval=30,group=grp_sig)
show_signals = input.bool(true,"Show Entry Labels",group=grp_sig)
show_score = input.bool(true,"Show Score", group=grp_sig)
// ── Visuals ───────────────────────────────────────────────
grp_vis = "🎨 Visuals"
bull_col = input.color(#00c4ff,"Bullish Color", group=grp_vis)
bear_col = input.color(#ff3d3d,"Bearish Color", group=grp_vis)
show_dash = input.bool(true,"Show Dashboard", group=grp_vis)
// ════════════════════════════════════════════════════════════
// ░░ BASE
// ════════════════════════════════════════════════════════════
atr14 = ta.atr(14)
vol_sma = ta.sma(volume, 20)
is_new_day = ta.change(dayofweek) != 0
// ════════════════════════════════════════════════════════════
// ░░ LAYER A — 4H BIAS
// ════════════════════════════════════════════════════════════
// Non-repainting: lookahead_off on all security calls.
// 4H EMA9/21 gives direction; pivot BOS confirms the break.
// Premium/discount: price vs midpoint of 50-bar high/low range.
htf_ema_f = request.security(syminfo.tickerid, htf_tf,
ta.ema(close, htf_ema_fast), lookahead=barmerge.lookahead_off)
htf_ema_s = request.security(syminfo.tickerid, htf_tf,
ta.ema(close, htf_ema_slow), lookahead=barmerge.lookahead_off)
htf_close = request.security(syminfo.tickerid, htf_tf,
close, lookahead=barmerge.lookahead_off)
htf_high50 = request.security(syminfo.tickerid, htf_tf,
ta.highest(high, htf_pd_len), lookahead=barmerge.lookahead_off)
htf_low50 = request.security(syminfo.tickerid, htf_tf,
ta.lowest(low, htf_pd_len), lookahead=barmerge.lookahead_off)
htf_ph = request.security(syminfo.tickerid, htf_tf,
ta.pivothigh(high, htf_swing, htf_swing), lookahead=barmerge.lookahead_off)
htf_pl = request.security(syminfo.tickerid, htf_tf,
ta.pivotlow(low, htf_swing, htf_swing), lookahead=barmerge.lookahead_off)
// Track last confirmed 4H pivot levels
var float htf_last_ph = na
var float htf_last_pl = na
if not na(htf_ph)
htf_last_ph := htf_ph
if not na(htf_pl)
htf_last_pl := htf_pl
// 4H structural bias via EMA stack + pivot break
htf_ema_bull = htf_ema_f > htf_ema_s
htf_ema_bear = htf_ema_f < htf_ema_s
// Additional pivot BOS confirmation (price closed beyond last 4H swing)
htf_bos_bull = not na(htf_last_ph) and htf_close > htf_last_ph
htf_bos_bear = not na(htf_last_pl) and htf_close < htf_last_pl
// Persistent 4H bias — latches on confirmed direction, cleared to 0 when both disagree
var int htf_bias = 0
if htf_ema_bull and htf_bos_bull
htf_bias := 1
else if htf_ema_bear and htf_bos_bear
htf_bias := -1
// If EMA and BOS disagree → bias stays last known (momentum persists)
// Only explicitly reset to 0 if neither condition has ever been met
if na(htf_last_ph) and na(htf_last_pl)
htf_bias := 0
// 4H Premium / Discount zone
htf_range_mid = (htf_high50 + htf_low50) / 2.0
htf_in_discount = htf_close < htf_range_mid // buy zone for longs
htf_in_premium = htf_close > htf_range_mid // sell zone for shorts
// HARD BLOCK: 4H bias must be defined
// If EMA9 == EMA21 (flat) or insufficient history, bias = 0 → no trade
htf_defined = htf_bias != 0
htf_ok_long = htf_bias == 1
htf_ok_short = htf_bias == -1
// Plot 4H EMAs (extended to the right for reference)
var line htf_ema_f_line = na
var line htf_ema_s_line = na
if show_htf_lines and barstate.islast
line.delete(htf_ema_f_line)
line.delete(htf_ema_s_line)
htf_ema_f_line := line.new(bar_index - 5, htf_ema_f, bar_index + 20, htf_ema_f,
color=color.new(bull_col, 30), width=1, style=line.style_dashed, extend=extend.right)
htf_ema_s_line := line.new(bar_index - 5, htf_ema_s, bar_index + 20, htf_ema_s,
color=color.new(bear_col, 30), width=1, style=line.style_dashed, extend=extend.right)
// Premium / Discount zone boxes (live, refreshed each bar)
var box pd_prem_box = na
var box pd_disc_box = na
if show_4h_zones and not na(htf_high50) and not na(htf_low50) and barstate.islast
box.delete(pd_prem_box)
box.delete(pd_disc_box)
_left = bar_index - htf_pd_len
pd_prem_box := box.new(_left, htf_high50, bar_index + 10, htf_range_mid,
bgcolor=color.new(bear_col, 92), border_color=color.new(bear_col, 60), border_width=1)
pd_disc_box := box.new(_left, htf_range_mid, bar_index + 10, htf_low50,
bgcolor=color.new(bull_col, 92), border_color=color.new(bull_col, 60), border_width=1)
// ════════════════════════════════════════════════════════════
// ░░ LAYER B — 1H STRUCTURE (SETUP TF)
// ════════════════════════════════════════════════════════════
// 1H must show a CHoCH or BOS in the same direction as 4H bias.
// We track 1H pivot BOS direction and EMA trend independently.
h1_ema_f = request.security(syminfo.tickerid, setup_tf,
ta.ema(close, htf_ema_fast), lookahead=barmerge.lookahead_off)
h1_ema_s = request.security(syminfo.tickerid, setup_tf,
ta.ema(close, htf_ema_slow), lookahead=barmerge.lookahead_off)
h1_close = request.security(syminfo.tickerid, setup_tf,
close, lookahead=barmerge.lookahead_off)
h1_ph = request.security(syminfo.tickerid, setup_tf,
ta.pivothigh(high, setup_swing, setup_swing), lookahead=barmerge.lookahead_off)
h1_pl = request.security(syminfo.tickerid, setup_tf,
ta.pivotlow(low, setup_swing, setup_swing), lookahead=barmerge.lookahead_off)
var float h1_last_ph = na
var float h1_last_pl = na
var int h1_bias = 0
if not na(h1_ph)
h1_last_ph := h1_ph
if not na(h1_pl)
h1_last_pl := h1_pl
// 1H BOS: close through last swing level
h1_bos_bull = not na(h1_last_ph) and h1_close > h1_last_ph and h1_ema_f > h1_ema_s
h1_bos_bear = not na(h1_last_pl) and h1_close < h1_last_pl and h1_ema_f < h1_ema_s
// 1H CHoCH: BOS against prior bias (structure shift)
h1_choch_bull = not na(h1_last_ph) and h1_close > h1_last_ph and h1_bias == -1
h1_choch_bear = not na(h1_last_pl) and h1_close < h1_last_pl and h1_bias == 1
if h1_bos_bull or h1_choch_bull
h1_bias := 1
if h1_bos_bear or h1_choch_bear
h1_bias := -1
h1_ema_trend = h1_ema_f > h1_ema_s ? 1 : h1_ema_f < h1_ema_s ? -1 : 0
// HARD BLOCK: 1H structure must align with 4H bias
h1_ok_long = h1_bias == 1 and h1_ema_trend == 1
h1_ok_short = h1_bias == -1 and h1_ema_trend == -1
// ════════════════════════════════════════════════════════════
// ░░ LAYER C — 15m ENTRY ZONE
// ════════════════════════════════════════════════════════════
// Defines the precision entry. At minimum 1 of (OB or sweep) must be present.
// Fetches 15m data and checks for:
// Active OB: approximated by last opposing candle near current price on 15m
// Recent sweep: wick-beyond-swing on 15m
m15_close = request.security(syminfo.tickerid, entry_tf,
close, lookahead=barmerge.lookahead_off)
m15_high = request.security(syminfo.tickerid, entry_tf,
high, lookahead=barmerge.lookahead_off)
m15_low = request.security(syminfo.tickerid, entry_tf,
low, lookahead=barmerge.lookahead_off)
m15_open = request.security(syminfo.tickerid, entry_tf,
open, lookahead=barmerge.lookahead_off)
// 15m OB detection (approximation using confirmed 15m bars):
// Bullish OB on 15m: last 15m bar was bearish AND current 15m close > prior 15m high
// → price broke up through a bearish candle = the OB is the bearish candle
// We look at [1] to get the confirmed prior bar
m15_bull_ob_active = m15_open[1] > m15_close[1] and // prior 15m bar was bearish
m15_close > m15_high[1] and // current 15m broke above it
math.abs(m15_close - m15_open[1]) /
math.max(m15_high[1] - m15_low[1], 0.001) >= 0.3 and // body ≥ 30% range
math.abs(close - (m15_high[1] + m15_low[1]) / 2) /
close * 100 <= entry_ob_pct // 5m price near 15m OB midpoint
m15_bear_ob_active = m15_open[1] < m15_close[1] and // prior 15m bar was bullish
m15_close < m15_low[1] and // current 15m broke below it
math.abs(m15_close - m15_open[1]) /
math.max(m15_high[1] - m15_low[1], 0.001) >= 0.3 and
math.abs(close - (m15_high[1] + m15_low[1]) / 2) /
close * 100 <= entry_ob_pct
// 15m sweep detection: wick pierced beyond swing + close recovered
m15_swing_hi = request.security(syminfo.tickerid, entry_tf,
ta.highest(high, entry_liq_lb), lookahead=barmerge.lookahead_off)
m15_swing_lo = request.security(syminfo.tickerid, entry_tf,
ta.lowest(low, entry_liq_lb), lookahead=barmerge.lookahead_off)
m15_sweep_bull = m15_low < m15_swing_lo[1] and m15_close > m15_swing_lo[1]
m15_sweep_bear = m15_high > m15_swing_hi[1] and m15_close < m15_swing_hi[1]
// Track recency on LTF (5m) bars
var int last_m15_bull_ob = -999
var int last_m15_bear_ob = -999
var int last_m15_bull_sw = -999
var int last_m15_bear_sw = -999
if m15_bull_ob_active
last_m15_bull_ob := bar_index
if m15_bear_ob_active
last_m15_bear_ob := bar_index
if m15_sweep_bull
last_m15_bull_sw := bar_index
if m15_sweep_bear
last_m15_bear_sw := bar_index
// Active within last 3 × smc_swing bars
m15_ob_bull_ok = (bar_index - last_m15_bull_ob) <= smc_swing * 3
m15_ob_bear_ok = (bar_index - last_m15_bear_ob) <= smc_swing * 3
m15_sw_bull_ok = (bar_index - last_m15_bull_sw) <= smc_swing * 3
m15_sw_bear_ok = (bar_index - last_m15_bear_sw) <= smc_swing * 3
// HARD BLOCK: at least 1 entry zone signal required (OB or sweep)
m15_zone_long = m15_ob_bull_ok or m15_sw_bull_ok
m15_zone_short = m15_ob_bear_ok or m15_sw_bear_ok
// ════════════════════════════════════════════════════════════
// ░░ LAYER D — 5m EXECUTION (existing SMC engine, unchanged)
// ════════════════════════════════════════════════════════════
ph = ta.pivothigh(high, smc_swing, smc_swing)
pl = ta.pivotlow(low, smc_swing, smc_swing)
var float last_ph = na; var float last_pl = na
var int last_ph_bar = -999; var int last_pl_bar = -999
var int ph_age = 0; var int pl_age = 0
ph_age := ph_age + 1; pl_age := pl_age + 1
if not na(ph)
last_ph := ph; last_ph_bar := bar_index - smc_swing; ph_age := 0
if not na(pl)
last_pl := pl; last_pl_bar := bar_index - smc_swing; pl_age := 0
ph_valid = not na(last_ph) and ph_age <= ob_expire
pl_valid = not na(last_pl) and pl_age <= ob_expire
var int structure_bias = 0
bos_bull = ph_valid and close > last_ph and close[1] <= last_ph
bos_bear = pl_valid and close < last_pl and close[1] >= last_pl
choch_bull = ph_valid and close > last_ph and close[1] <= last_ph and structure_bias == -1
choch_bear = pl_valid and close < last_pl and close[1] >= last_pl and structure_bias == 1
if bos_bull or choch_bull
structure_bias := 1
if bos_bear or choch_bear
structure_bias := -1
// BOS / CHoCH lines (center text on line)
var int last_bos_bull_lbl = -999; var int last_bos_bear_lbl = -999
int bos_gap = math.max(3, smc_swing)
if show_bos
if choch_bull
_b = math.max(last_ph_bar, bar_index - 100)
line.new(_b, last_ph, bar_index, last_ph, color=color.new(bull_col, 0), width=1, style=line.style_solid)
label.new(math.round((_b + bar_index) / 2), last_ph, "CHoCH",
style=label.style_none, textcolor=color.new(bull_col, 0), size=size.small, yloc=yloc.price)
last_bos_bull_lbl := bar_index
if choch_bear
_b = math.max(last_pl_bar, bar_index - 100)
line.new(_b, last_pl, bar_index, last_pl, color=color.new(bear_col, 0), width=1, style=line.style_solid)
label.new(math.round((_b + bar_index) / 2), last_pl, "CHoCH",
style=label.style_none, textcolor=color.new(bear_col, 0), size=size.small, yloc=yloc.price)
last_bos_bear_lbl := bar_index
if bos_bull and not choch_bull and (bar_index - last_bos_bull_lbl) >= bos_gap
_b = math.max(last_ph_bar, bar_index - 100)
line.new(_b, last_ph, bar_index, last_ph, color=color.new(bull_col, 50), width=1, style=line.style_dashed)
label.new(math.round((_b + bar_index) / 2), last_ph, "BOS",
style=label.style_none, textcolor=color.new(bull_col, 20), size=size.small, yloc=yloc.price)
last_bos_bull_lbl := bar_index
if bos_bear and not choch_bear and (bar_index - last_bos_bear_lbl) >= bos_gap
_b = math.max(last_pl_bar, bar_index - 100)
line.new(_b, last_pl, bar_index, last_pl, color=color.new(bear_col, 50), width=1, style=line.style_dashed)
label.new(math.round((_b + bar_index) / 2), last_pl, "BOS",
style=label.style_none, textcolor=color.new(bear_col, 20), size=size.small, yloc=yloc.price)
last_bos_bear_lbl := bar_index
// 5m Order Blocks
impulse_body_pct = math.abs(close - open) / close * 100
var float bull_ob_hi = na; var float bull_ob_lo = na
var int bull_ob_bar = -999; var int bull_ob_age = 0
var float bear_ob_hi = na; var float bear_ob_lo = na
var int bear_ob_bar = -999; var int bear_ob_age = 0
bull_ob_age := bull_ob_age + 1; bear_ob_age := bear_ob_age + 1
if (bos_bull or choch_bull) and impulse_body_pct >= ob_body_pct and close[1] < open[1]
bull_ob_hi := high[1]; bull_ob_lo := low[1]; bull_ob_bar := bar_index - 1; bull_ob_age := 0
if (bos_bear or choch_bear) and impulse_body_pct >= ob_body_pct and close[1] > open[1]
bear_ob_hi := high[1]; bear_ob_lo := low[1]; bear_ob_bar := bar_index - 1; bear_ob_age := 0
bull_ob_valid = not na(bull_ob_hi) and bull_ob_age <= ob_expire and close >= bull_ob_lo * 0.998
bear_ob_valid = not na(bear_ob_hi) and bear_ob_age <= ob_expire and close <= bear_ob_hi * 1.002
in_bull_ob = bull_ob_valid and low <= bull_ob_hi and high >= bull_ob_lo
in_bear_ob = bear_ob_valid and high >= bear_ob_lo and low <= bear_ob_hi
var box bull_ob_box = na; var box bear_ob_box = na
if show_ob and bull_ob_valid and not na(bull_ob_hi)
box.delete(bull_ob_box)
bull_ob_box := box.new(bull_ob_bar, bull_ob_hi, bar_index, bull_ob_lo,
border_color=color.new(bull_col, 20), bgcolor=color.new(bull_col, 85), border_width=1)
if show_ob and bear_ob_valid and not na(bear_ob_hi)
box.delete(bear_ob_box)
bear_ob_box := box.new(bear_ob_bar, bear_ob_hi, bar_index, bear_ob_lo,
border_color=color.new(bear_col, 20), bgcolor=color.new(bear_col, 85), border_width=1)
// 5m Liquidity sweeps
liq_hi = ta.highest(high, liq_lookback); liq_lo = ta.lowest(low, liq_lookback)
liq_sweep_bull = low < liq_lo[1] - liq_lo[1] * (liq_wick_pct/100) and close > liq_lo[1]
liq_sweep_bear = high > liq_hi[1] + liq_hi[1] * (liq_wick_pct/100) and close < liq_hi[1]
var int last_bull_sw = -999; var int last_bear_sw = -999
var int last_liq_bull_lbl = -999; var int last_liq_bear_lbl = -999
int liq_gap = math.max(3, smc_swing)
if liq_sweep_bull then last_bull_sw := bar_index
if liq_sweep_bear then last_bear_sw := bar_index
recent_bull_sweep = (bar_index - last_bull_sw) <= smc_swing * 2
recent_bear_sweep = (bar_index - last_bear_sw) <= smc_swing * 2
if show_liq and liq_sweep_bull and (bar_index - last_liq_bull_lbl) >= liq_gap
label.new(bar_index, low, "•", style=label.style_none, textcolor=color.new(color.purple, 0), size=size.normal)
label.new(bar_index, low - atr14*0.3, "Sell-side", style=label.style_none, textcolor=color.new(color.purple,30), size=size.small)
last_liq_bull_lbl := bar_index
if show_liq and liq_sweep_bear and (bar_index - last_liq_bear_lbl) >= liq_gap
label.new(bar_index, high, "•", style=label.style_none, textcolor=color.new(color.orange, 0), size=size.normal)
label.new(bar_index, high + atr14*0.3, "Buy-side", style=label.style_none, textcolor=color.new(color.orange,30), size=size.small)
last_liq_bear_lbl := bar_index
// 5m Market Structure labels
ms_ph = ta.pivothigh(high, ms_swing, ms_swing); ms_pl = ta.pivotlow(low, ms_swing, ms_swing)
var float prev_ms_ph = na; var float prev_ms_pl = na
ms_hh = not na(ms_ph) and not na(prev_ms_ph) and ms_ph > prev_ms_ph
ms_lh = not na(ms_ph) and not na(prev_ms_ph) and ms_ph < prev_ms_ph
ms_hl = not na(ms_pl) and not na(prev_ms_pl) and ms_pl > prev_ms_pl
ms_ll = not na(ms_pl) and not na(prev_ms_pl) and ms_pl < prev_ms_pl
var float last_ms_ph_val = na; var float last_ms_pl_val = na
if not na(ms_ph) then prev_ms_ph := last_ms_ph_val; last_ms_ph_val := ms_ph
if not na(ms_pl) then prev_ms_pl := last_ms_pl_val; last_ms_pl_val := ms_pl
var int last_ms_lbl = -999; int ms_gap = math.max(3, ms_swing)
if show_ms and (bar_index - ms_swing - last_ms_lbl) >= ms_gap
if ms_hh then label.new(bar_index - ms_swing, ms_ph, "HH", style=label.style_none, textcolor=color.new(bull_col,20), size=size.small, yloc=yloc.abovebar); last_ms_lbl := bar_index - ms_swing
if ms_lh then label.new(bar_index - ms_swing, ms_ph, "LH", style=label.style_none, textcolor=color.new(bear_col,20), size=size.small, yloc=yloc.abovebar); last_ms_lbl := bar_index - ms_swing
if ms_hl then label.new(bar_index - ms_swing, ms_pl, "HL", style=label.style_none, textcolor=color.new(bull_col,20), size=size.small, yloc=yloc.belowbar); last_ms_lbl := bar_index - ms_swing
if ms_ll then label.new(bar_index - ms_swing, ms_pl, "LL", style=label.style_none, textcolor=color.new(bear_col,20), size=size.small, yloc=yloc.belowbar); last_ms_lbl := bar_index - ms_swing
var int ms_trend = 0
if ms_hh or ms_hl then ms_trend := 1
if ms_lh or ms_ll then ms_trend := -1
var line ms_ph_line = na; var line ms_pl_line = na
if show_ms_line
if not na(ms_ph)
line.delete(ms_ph_line)
ms_ph_line := line.new(bar_index-ms_swing-ms_swing, nz(prev_ms_ph,ms_ph), bar_index-ms_swing, ms_ph, color=color.new(bear_col,50), width=1, style=line.style_dashed)
if not na(ms_pl)
line.delete(ms_pl_line)
ms_pl_line := line.new(bar_index-ms_swing-ms_swing, nz(prev_ms_pl,ms_pl), bar_index-ms_swing, ms_pl, color=color.new(bull_col,50), width=1, style=line.style_dashed)
// ── Trendlines ────────────────────────────────────────────
tl_ph = ta.pivothigh(high, tl_pivot_len, tl_pivot_len); tl_pl = ta.pivotlow(low, tl_pivot_len, tl_pivot_len)
var float tl_ph1 = na; var int tl_ph1_bar = -999; var float tl_ph2 = na; var int tl_ph2_bar = -999
var float tl_pl1 = na; var int tl_pl1_bar = -999; var float tl_pl2 = na; var int tl_pl2_bar = -999
if not na(tl_ph) then tl_ph2 := tl_ph1; tl_ph2_bar := tl_ph1_bar; tl_ph1 := tl_ph; tl_ph1_bar := bar_index - tl_pivot_len
if not na(tl_pl) then tl_pl2 := tl_pl1; tl_pl2_bar := tl_pl1_bar; tl_pl1 := tl_pl; tl_pl1_bar := bar_index - tl_pivot_len
tl_bear_slope = not na(tl_ph1) and not na(tl_ph2) and tl_ph1_bar != tl_ph2_bar ? (tl_ph1 - tl_ph2) / (tl_ph1_bar - tl_ph2_bar) : na
tl_bull_slope = not na(tl_pl1) and not na(tl_pl2) and tl_pl1_bar != tl_pl2_bar ? (tl_pl1 - tl_pl2) / (tl_pl1_bar - tl_pl2_bar) : na
tl_bear_val = not na(tl_bear_slope) ? tl_ph1 + tl_bear_slope * (bar_index - tl_ph1_bar) : na
tl_bull_val = not na(tl_bull_slope) ? tl_pl1 + tl_bull_slope * (bar_index - tl_pl1_bar) : na
tl_bear_break = not na(tl_bear_val) and close > tl_bear_val and close[1] <= tl_bear_val[1]
tl_bull_break = not na(tl_bull_val) and close < tl_bull_val and close[1] >= tl_bull_val[1]
var bool tl_bear_broken = false; var bool tl_bull_broken = false
var bool tl_bear_retested = false; var bool tl_bull_retested = false
var int tl_bear_break_bar = -999; var int tl_bull_break_bar = -999
if not na(tl_ph) then tl_bear_broken := false; tl_bear_retested := false; tl_bear_break_bar := -999
if not na(tl_pl) then tl_bull_broken := false; tl_bull_retested := false; tl_bull_break_bar := -999
if tl_bear_break then tl_bear_broken := true; tl_bear_retested := false; tl_bear_break_bar := bar_index
if tl_bull_break then tl_bull_broken := true; tl_bull_retested := false; tl_bull_break_bar := bar_index
tl_bear_retest = tl_bear_broken and not tl_bear_retested and not na(tl_bear_val) and (bar_index - tl_bear_break_bar) > 1 and math.abs(close - tl_bear_val)/close*100 <= tl_retest_pct and close > tl_bear_val
tl_bull_retest = tl_bull_broken and not tl_bull_retested and not na(tl_bull_val) and (bar_index - tl_bull_break_bar) > 1 and math.abs(close - tl_bull_val)/close*100 <= tl_retest_pct and close < tl_bull_val
if tl_bear_retest then tl_bear_retested := true
if tl_bull_retest then tl_bull_retested := true
var line tl_bear_line = na; var line tl_bull_line = na
if show_tl
if not na(tl_ph1) and not na(tl_ph2)
line.delete(tl_bear_line)
tl_bear_line := line.new(tl_ph2_bar, tl_ph2, bar_index, tl_bear_val, color=color.new(bear_col,30), width=1, style=tl_bear_broken ? line.style_dashed : line.style_solid, extend=extend.right)
if not na(tl_pl1) and not na(tl_pl2)
line.delete(tl_bull_line)
tl_bull_line := line.new(tl_pl2_bar, tl_pl2, bar_index, tl_bull_val, color=color.new(bull_col,30), width=1, style=tl_bull_broken ? line.style_dashed : line.style_solid, extend=extend.right)
if show_tl_break
if tl_bear_break then label.new(bar_index, tl_bear_val, "◆ Break", style=label.style_none, textcolor=color.new(bull_col,0), size=size.small, yloc=yloc.belowbar)
if tl_bull_break then label.new(bar_index, tl_bull_val, "◆ Break", style=label.style_none, textcolor=color.new(bear_col,0), size=size.small, yloc=yloc.abovebar)
if tl_bear_retest then label.new(bar_index, tl_bear_val, "● Retest", style=label.style_none, textcolor=color.new(bull_col,0), size=size.small, yloc=yloc.belowbar)
if tl_bull_retest then label.new(bar_index, tl_bull_val, "● Retest", style=label.style_none, textcolor=color.new(bear_col,0), size=size.small, yloc=yloc.abovebar)
// ── Session Levels ────────────────────────────────────────
var float day_high = high; var float day_low = low; var float pdh = na; var float pdl = na
if is_new_day then pdh := day_high; pdl := day_low; day_high := high; day_low := low
else then day_high := math.max(day_high, high); day_low := math.min(day_low, low)
in_asia = not na(time(timeframe.period, asia_sess))
in_london = not na(time(timeframe.period, london_sess))
in_ny = not na(time(timeframe.period, ny_sess))
var float asia_hi = na; var float asia_lo = na
var float london_hi = na; var float london_lo = na
var float ny_hi = na; var float ny_lo = na
var bool was_asia = false; var bool was_london = false; var bool was_ny = false
if in_asia then asia_hi := na(asia_hi) or not was_asia ? high : math.max(asia_hi,high); asia_lo := na(asia_lo) or not was_asia ? low : math.min(asia_lo,low); was_asia := true
else if was_asia then was_asia := false
if in_london then london_hi := na(london_hi) or not was_london ? high : math.max(london_hi,high); london_lo := na(london_lo) or not was_london ? low : math.min(london_lo,low); was_london := true
else if was_london then was_london := false
if in_ny then ny_hi := na(ny_hi) or not was_ny ? high : math.max(ny_hi,high); ny_lo := na(ny_lo) or not was_ny ? low : math.min(ny_lo,low); was_ny := true
else if was_ny then was_ny := false
var line pdh_line = na; var line pdl_line = na
if show_pdh_pdl and not na(pdh) and barstate.islast
line.delete(pdh_line); line.delete(pdl_line)
pdh_line := line.new(bar_index-50, pdh, bar_index+20, pdh, color=color.new(bear_col,20), width=1, style=line.style_dotted, extend=extend.right)
pdl_line := line.new(bar_index-50, pdl, bar_index+20, pdl, color=color.new(bull_col,20), width=1, style=line.style_dotted, extend=extend.right)
pdh_sweep = not na(pdh) and high > pdh*(1+sess_liq_pct/100) and close < pdh
pdl_sweep = not na(pdl) and low < pdl*(1-sess_liq_pct/100) and close > pdl
near_pdh = not na(pdh) and math.abs(close-pdh)/close*100 <= sess_liq_pct
near_pdl = not na(pdl) and math.abs(close-pdl)/close*100 <= sess_liq_pct
near_sess_hi = (not na(asia_hi) and math.abs(close-asia_hi)/close*100 <= sess_liq_pct) or (not na(london_hi) and math.abs(close-london_hi)/close*100 <= sess_liq_pct)
near_sess_lo = (not na(asia_lo) and math.abs(close-asia_lo)/close*100 <= sess_liq_pct) or (not na(london_lo) and math.abs(close-london_lo)/close*100 <= sess_liq_pct)
sess_level_bull = near_pdl or near_sess_lo or pdl_sweep
sess_level_bear = near_pdh or near_sess_hi or pdh_sweep
// ── Volume Profile ────────────────────────────────────────
vp_high = ta.highest(high, vp_bars); vp_low = ta.lowest(low, vp_bars)
var float poc = na; var float vah = na; var float val_line = na
var float max_vol = 0.0; var float max_vol_price = na
if bar_index >= vp_bars
max_vol := 0.0; max_vol_price := close
for i = 0 to vp_bars - 1
if volume[i] > max_vol then max_vol := volume[i]; max_vol_price := (high[i]+low[i]+close[i])/3.0
poc := max_vol_price
float ws = 0.0; float wv = 0.0; float ws2 = 0.0
for i = 0 to vp_bars - 1
float tp = (high[i]+low[i]+close[i])/3.0; ws += tp*volume[i]; wv += volume[i]; ws2 += tp*tp*volume[i]
float wm = wv > 0 ? ws/wv : close; float vr = wv > 0 ? ws2/wv - wm*wm : 0.0; float sg = vr > 0 ? math.sqrt(vr) : atr14
vah := wm + sg; val_line := wm - sg
near_poc = not na(poc) and math.abs(close-poc)/close*100 <= poc_zone_pct
near_vah = not na(vah) and math.abs(close-vah)/close*100 <= poc_zone_pct
near_val = not na(val_line) and math.abs(close-val_line)/close*100 <= poc_zone_pct
vp_bull_conf = near_poc or near_val; vp_bear_conf = near_poc or near_vah
var line poc_line = na; var line vah_line = na; var line val_line2 = na
if show_vp and not na(poc) and barstate.islast
line.delete(poc_line); line.delete(vah_line); line.delete(val_line2)
poc_line := line.new(bar_index-vp_bars, poc, bar_index, poc, color=color.new(color.yellow,20), width=2, style=line.style_solid)
vah_line := line.new(bar_index-vp_bars, vah, bar_index, vah, color=color.new(bear_col,40), width=1, style=line.style_dashed)
val_line2 := line.new(bar_index-vp_bars, val_line, bar_index, val_line, color=color.new(bull_col,40), width=1, style=line.style_dashed)
// ════════════════════════════════════════════════════════════
// ░░ 4-LAYER SIGNAL ENGINE
// ════════════════════════════════════════════════════════════
// ALL 4 MANDATORY GATES MUST PASS — no signal otherwise
// Score adds 2 bonus points on top of the 4 mandatory pts
// ── Gate checks ───────────────────────────────────────────
gate_a_long = htf_ok_long // 4H bias = bull
gate_a_short = htf_ok_short // 4H bias = bear
gate_b_long = h1_ok_long // 1H structure = bull
gate_b_short = h1_ok_short // 1H structure = bear
gate_c_long = m15_zone_long // 15m OB or sweep active
gate_c_short = m15_zone_short
gate_d_long = choch_bull // 5m CHoCH trigger
gate_d_short = choch_bear
all_gates_long = gate_a_long and gate_b_long and gate_c_long and gate_d_long
all_gates_short = gate_a_short and gate_b_short and gate_c_short and gate_d_short
// ── Scoring (0–8): 4 gates = mandatory pts, 4 bonus pts ──
// Gate pts (1 each, only counted when gate passes)
long_ga = gate_a_long ? 1 : 0 // 4H bias
long_gb = gate_b_long ? 1 : 0 // 1H structure
long_gc = gate_c_long ? 1 : 0 // 15m zone
long_gd = gate_d_long ? 1 : 0 // 5m CHoCH
// Bonus pts (quality boosters)
long_b1 = htf_in_discount ? 1 : 0 // 4H price in discount zone (accumulation)
long_b2 = in_bull_ob ? 1 : 0 // 5m OB tap
long_b3 = (vp_bull_conf or sess_level_bull) ? 1 : 0 // VP or session confluence
long_b4 = (tl_bear_retest or recent_bull_sweep) ? 1 : 0 // TL retest or 5m sweep
short_ga = gate_a_short ? 1 : 0
short_gb = gate_b_short ? 1 : 0
short_gc = gate_c_short ? 1 : 0
short_gd = gate_d_short ? 1 : 0
short_b1 = htf_in_premium ? 1 : 0
short_b2 = in_bear_ob ? 1 : 0
short_b3 = (vp_bear_conf or sess_level_bear) ? 1 : 0
short_b4 = (tl_bull_retest or recent_bear_sweep) ? 1 : 0
long_score = long_ga + long_gb + long_gc + long_gd + long_b1 + long_b2 + long_b3 + long_b4
short_score = short_ga + short_gb + short_gc + short_gd + short_b1 + short_b2 + short_b3 + short_b4
var int last_sig_bar = -999
cooldown_ok = (bar_index - last_sig_bar) >= sig_cooldown
// Signal only fires when ALL 4 gates pass + score ≥ min
long_signal = all_gates_long and long_score >= min_score and cooldown_ok
short_signal = all_gates_short and short_score >= min_score and cooldown_ok
if long_signal or short_signal
last_sig_bar := bar_index
// ════════════════════════════════════════════════════════════
// ░░ SIGNAL LABELS
// ════════════════════════════════════════════════════════════
// Global series: UDFs that use values fed by request.security() fail bundled-ref analysis.
gate_breakdown_long_txt =
"4H" + (gate_a_long ? "✓" : "✗") + " 1H" + (gate_b_long ? "✓" : "✗") +
" 15m" + (gate_c_long ? "✓" : "✗") + " 5m" + (gate_d_long ? "✓" : "✗")
gate_breakdown_short_txt =
"4H" + (gate_a_short ? "✓" : "✗") + " 1H" + (gate_b_short ? "✓" : "✗") +
" 15m" + (gate_c_short ? "✓" : "✗") + " 5m" + (gate_d_short ? "✓" : "✗")
if show_signals and long_signal
_col = long_score >= 7 ? color.new(bull_col, 0) :
long_score >= 5 ? color.new(bull_col, 15) : color.new(bull_col, 30)
_txt = "▲ LONG" + (show_score ? " [" + str.tostring(long_score) + "/8]" : "") +
"\n" + gate_breakdown_long_txt +
(long_b1==1?" PD":"") + (long_b2==1?" OB":"") +
(long_b3==1?" VP/SESS":"") + (long_b4==1?" TL/LIQ":"")
label.new(bar_index, low - atr14 * 1.2, _txt,
style=label.style_label_up, color=_col, textcolor=color.white, size=size.normal)
if show_signals and short_signal
_col = short_score >= 7 ? color.new(bear_col, 0) :
short_score >= 5 ? color.new(bear_col, 15) : color.new(bear_col, 30)
_txt = "▼ SHORT" + (show_score ? " [" + str.tostring(short_score) + "/8]" : "") +
"\n" + gate_breakdown_short_txt +
(short_b1==1?" PD":"") + (short_b2==1?" OB":"") +
(short_b3==1?" VP/SESS":"") + (short_b4==1?" TL/LIQ":"")
label.new(bar_index, high + atr14 * 1.2, _txt,
style=label.style_label_down, color=_col, textcolor=color.white, size=size.normal)
// ════════════════════════════════════════════════════════════
// ░░ PLOTS
// ════════════════════════════════════════════════════════════
[st_val, st_dir] = ta.supertrend(3.0, 10)
plot(st_dir < 0 ? st_val : na, "ST Bull", color=color.new(bull_col,50), linewidth=1, style=plot.style_linebr)
plot(st_dir > 0 ? st_val : na, "ST Bear", color=color.new(bear_col,50), linewidth=1, style=plot.style_linebr)
// Background: show 4H bias (darkest = strongest signal)
bgcolor(htf_bias == 1 and h1_bias == 1 ? color.new(bull_col, 95) :
htf_bias == -1 and h1_bias == -1 ? color.new(bear_col, 95) :
htf_bias == 1 ? color.new(bull_col, 98) :
htf_bias == -1 ? color.new(bear_col, 98) : na,
title="4H+1H Bias BG")
barcolor(structure_bias == 1 ? color.new(bull_col, 65) :
structure_bias == -1 ? color.new(bear_col, 65) : na)
// ════════════════════════════════════════════════════════════
// ░░ DASHBOARD — 4-LAYER VIEW
// ════════════════════════════════════════════════════════════
var table dash = table.new(position.top_right, 3, 18,
bgcolor=color.new(#0d0d0d, 5),
border_color=color.new(#2a2a2a, 30), border_width=1,
frame_color=color.new(#3a3a3a, 20), frame_width=1)
dc(c, r, t, bg, tc) =>
table.cell(dash, c, r, t, bgcolor=bg, text_color=tc, text_size=size.small)
if show_dash and barstate.islast
pos = color.new(#00c87a, 20); neg = color.new(#ff3d3d, 20)
neu = color.new(#3a3a3a, 40); hd = color.new(#1a1a2e, 10)
blk = color.new(#ff0000, 5) // hard-block color
wht = color.white
dc(0, 0, "SMC-CE v4 [4-TF]", hd, wht)
dc(1, 0, "BULL", hd, wht)
dc(2, 0, "BEAR", hd, wht)
// ── LAYER A: 4H ──────────────────────────────────────
dc(0, 1, "🟥 4H BIAS", hd, wht)
dc(1, 1, "", hd, wht); dc(2, 1, "", hd, wht)
dc(0, 2, " EMA+BOS", neu, wht)
dc(1, 2, htf_bias == 1 ? "BULL ✓" : htf_bias == 0 ? "NEUTRAL ⚠" : "—",
htf_bias == 1 ? pos : htf_bias == 0 ? color.new(color.yellow,30) : neu, wht)
dc(2, 2, htf_bias == -1 ? "BEAR ✓" : htf_bias == 0 ? "NEUTRAL ⚠" : "—",
htf_bias == -1 ? neg : htf_bias == 0 ? color.new(color.yellow,30) : neu, wht)
dc(0, 3, " P/D Zone", neu, wht)
dc(1, 3, htf_in_discount ? "Discount ✓" : "Premium",
htf_in_discount ? pos : color.new(color.orange,30), wht)
dc(2, 3, htf_in_premium ? "Premium ✓" : "Discount",
htf_in_premium ? neg : color.new(color.orange,30), wht)
dc(0, 4, " Gate A", neu, wht)
dc(1, 4, gate_a_long ? "PASS ✓" : "BLOCK ✗", gate_a_long ? pos : blk, wht)
dc(2, 4, gate_a_short ? "PASS ✓" : "BLOCK ✗", gate_a_short ? neg : blk, wht)
// ── LAYER B: 1H ──────────────────────────────────────
dc(0, 5, "🟧 1H SETUP", hd, wht)
dc(1, 5, "", hd, wht); dc(2, 5, "", hd, wht)
dc(0, 6, " BOS/CHoCH", neu, wht)
dc(1, 6, h1_bias == 1 ? "BULL ✓" : "—", h1_bias == 1 ? pos : neu, wht)
dc(2, 6, h1_bias == -1 ? "BEAR ✓" : "—", h1_bias == -1 ? neg : neu, wht)
dc(0, 7, " EMA Trend", neu, wht)
dc(1, 7, h1_ema_trend == 1 ? "UP ✓" : "—", h1_ema_trend == 1 ? pos : neu, wht)
dc(2, 7, h1_ema_trend == -1 ? "DOWN ✓" : "—", h1_ema_trend == -1 ? neg : neu, wht)
dc(0, 8, " Gate B", neu, wht)
dc(1, 8, gate_b_long ? "PASS ✓" : "BLOCK ✗", gate_b_long ? pos : blk, wht)
dc(2, 8, gate_b_short ? "PASS ✓" : "BLOCK ✗", gate_b_short ? neg : blk, wht)
// ── LAYER C: 15m ─────────────────────────────────────
dc(0, 9, "🟨 15m ENTRY", hd, wht)
dc(1, 9, "", hd, wht); dc(2, 9, "", hd, wht)
dc(0,10, " OB Zone", neu, wht)
dc(1,10, m15_ob_bull_ok ? "ACTIVE ✓" : "—", m15_ob_bull_ok ? pos : neu, wht)
dc(2,10, m15_ob_bear_ok ? "ACTIVE ✓" : "—", m15_ob_bear_ok ? neg : neu, wht)
dc(0,11, " LIQ Sweep", neu, wht)
dc(1,11, m15_sw_bull_ok ? "RECENT ✓" : "—", m15_sw_bull_ok ? pos : neu, wht)
dc(2,11, m15_sw_bear_ok ? "RECENT ✓" : "—", m15_sw_bear_ok ? neg : neu, wht)
dc(0,12, " Gate C", neu, wht)
dc(1,12, gate_c_long ? "PASS ✓" : "BLOCK ✗", gate_c_long ? pos : blk, wht)
dc(2,12, gate_c_short ? "PASS ✓" : "BLOCK ✗", gate_c_short ? neg : blk, wht)
// ── LAYER D: 5m ──────────────────────────────────────
dc(0,13, "🟩 5m TRIGGER", hd, wht)
dc(1,13, "", hd, wht); dc(2,13, "", hd, wht)
dc(0,14, " CHoCH", neu, wht)
dc(1,14, choch_bull ? "FIRED ✓" : "—", choch_bull ? pos : neu, wht)
dc(2,14, choch_bear ? "FIRED ✓" : "—", choch_bear ? neg : neu, wht)
dc(0,15, " Gate D", neu, wht)
dc(1,15, gate_d_long ? "PASS ✓" : "WAIT", gate_d_long ? pos : neu, wht)
dc(2,15, gate_d_short ? "PASS ✓" : "WAIT", gate_d_short ? neg : neu, wht)
// ── Final output ──────────────────────────────────────
dc(0,16, "⭐ Score", hd, wht)
dc(1,16, str.tostring(long_score) + "/8",
long_score >= 6 ? pos : long_score >= 4 ? color.new(color.orange,30) : neu, wht)
dc(2,16, str.tostring(short_score) + "/8",
short_score >= 6 ? neg : short_score >= 4 ? color.new(color.orange,30) : neu, wht)
dc(0,17, "🚀 SIGNAL", hd, wht)
dc(1,17, long_signal ? "▲ LONG" : all_gates_long ? "READY" : "BLOCKED",
long_signal ? pos : all_gates_long ? color.new(bull_col,40) : neu, wht)
dc(2,17, short_signal ? "▼ SHORT" : all_gates_short ? "READY" : "BLOCKED",
short_signal ? neg : all_gates_short ? color.new(bear_col,40) : neu, wht)
// ════════════════════════════════════════════════════════════
// ░░ ALERTS
// ════════════════════════════════════════════════════════════
alertcondition(long_signal,
"▲ LONG [4-TF Aligned]",
"SMC-CE v4 ▲ LONG | 4H+1H+15m+5m aligned | Score: " + str.tostring(long_score) + "/8 | Close: {{close}}")
alertcondition(short_signal,
"▼ SHORT [4-TF Aligned]",
"SMC-CE v4 ▼ SHORT | 4H+1H+15m+5m aligned | Score: " + str.tostring(short_score) + "/8 | Close: {{close}}")
alertcondition(long_signal and long_score >= 7, "🔥 HIGH CONV LONG (7+)", "SMC-CE v4 🔥 LONG score≥7 | Close: {{close}}")
alertcondition(short_signal and short_score >= 7, "🔥 HIGH CONV SHORT (7+)", "SMC-CE v4 🔥 SHORT score≥7 | Close: {{close}}")
alertcondition(htf_bias != htf_bias[1] and htf_bias == 1, "4H → BULLISH", "4H bias shifted BULLISH | Close: {{close}}")
alertcondition(htf_bias != htf_bias[1] and htf_bias == -1, "4H → BEARISH", "4H bias shifted BEARISH | Close: {{close}}")
alertcondition(h1_choch_bull, "1H CHoCH ↑ — Setup forming", "1H CHoCH bullish — watch for 15m zone | Close: {{close}}")
alertcondition(h1_choch_bear, "1H CHoCH ↓ — Setup forming", "1H CHoCH bearish — watch for 15m zone | Close: {{close}}")
alertcondition(liq_sweep_bull, "💧 5m Sell-side swept", "5m sell-side liquidity taken | Close: {{close}}")
alertcondition(liq_sweep_bear, "💧 5m Buy-side swept", "5m buy-side liquidity taken | Close: {{close}}")
alertcondition(pdh_sweep, "⚠ PDH Swept", "PDH swept — reversal watch | Close: {{close}}")
alertcondition(pdl_sweep, "⚠ PDL Swept", "PDL swept — reversal watch | Close: {{close}}")
Show all 807 lines