If you trade the Nifty 50, you know how quickly the market can shift. Relying on gut feeling or a single indicator is a surefire way to get shaken out by intraday noise. To consistently find high-probability setups, you have to treat the market like a complex system one that requires systematic testing, validation, and strict rule-based execution.
Here is a look under the hood at how the logic works.
A common vulnerability in many trading strategies is treating all market environments the same. A momentum oscillator that works beautifully in a range will destroy your capital in a strong trend.
To solve this, the engine first establishes a "Market Regime" using the Average Directional Index (ADX). By normalizing the ADX, the script determines if the market is actually trending:
If the regime trend is above 0.5, the engine activates. If it's choppy and directionless, the system stays out.
Instead of waiting for a perfect alignment of a dozen indicators, the engine assigns normalized base scores across four critical categories:
Here is where the engine gets dynamic. The weights assigned to Trend, Momentum, Volume, and Volatility aren't static; they adapt based on the market regime calculated earlier.
For example, as the trend strengthens, the algorithm dynamically increases the weight of the trend component and decreases the reliance on momentum:
Once the system calculates the final probability (from 0 to 99%), it filters the signals through a short-term directional bias (EMA 9 vs. EMA 21 crossover).
If the probability exceeds the strict 75% trigger threshold, it prints a clear, actionable label on the chart AI CALL or AI PUT along with a real-time dashboard tracking the current regime and bias.
//@version=6
indicator("⚡ NIFTY AI SCALPER PRO [v7]", overlay=true, max_labels_count=500, max_lines_count=500, max_boxes_count=100)
// ╔══════════════════════════════════════════════════════════════════╗
// ║ GLOBAL FUNCTIONS ║
// ╚══════════════════════════════════════════════════════════════════╝
f_price(p) => str.tostring(math.round(p, 1))
f_pts(p) => str.tostring(math.round(p, 0)) + "p"
score_col(v, mx) =>
r = v / mx
r >= 0.75 ? color.new(#00E676, 0) : r >= 0.45 ? color.new(#FFB300, 0) : color.new(#FF5252, 0)
make_pill(x, y, txt, bg, tc) =>
label.new(x, y, txt,
xloc=xloc.bar_index, style=label.style_label_left,
color=bg, textcolor=tc, size=size.small, textalign=text.align_left)
// ╔══════════════════════════════════════════════════════════════════╗
// ║ INPUTS ║
// ╚══════════════════════════════════════════════════════════════════╝
g_ai = "🧠 AI Engine"
g_smc = "🏦 Smart Money"
g_sig = "🎯 Signal Filters"
g_ex = "💰 Exit & Targets"
g_ses = "🕐 Session"
g_vis = "📊 Display"
// AI
min_prob = input.int (68, "Min Signal Probability (%)", group=g_ai, minval=50, maxval=99)
warmup_thr = input.int (55, "Warmup Alert Threshold (%)", group=g_ai, minval=40, maxval=95)
ml_lookback = input.int (50, "ML Pattern Lookback (bars)", group=g_ai, minval=20, maxval=200)
// SMC
ob_lookback = input.int (10, "Order Block Lookback", group=g_smc, minval=3, maxval=30)
show_ob = input.bool (true, "Show Order Blocks", group=g_smc)
show_bos = input.bool (true, "Show BOS / CHoCH Labels", group=g_smc)
swing_len = input.int (10, "Swing Point Length", group=g_smc, minval=5, maxval=30)
// Filters
req_candle = input.bool (true, "Require Candle Pattern", group=g_sig)
req_consec = input.bool (true, "Require 2-Bar Momentum", group=g_sig)
req_mtf = input.bool (true, "Require 5min MTF Align", group=g_sig)
req_ob = input.bool (false, "Require Order Block Entry", group=g_sig)
// Session
use_sess = input.bool (true, "Enable Session Filter", group=g_ses)
use_decay = input.bool (true, "Block Decay Zone (last N min)", group=g_ses)
decay_mins = input.int (10, "Decay Block Minutes", group=g_ses, minval=5, maxval=20)
s1_st = input.int (915, "Session 1 Start", group=g_ses)
s1_en = input.int (1000, "Session 1 End", group=g_ses)
s2_st = input.int (1145, "Session 2 Start", group=g_ses)
s2_en = input.int (1300, "Session 2 End", group=g_ses)
s3_st = input.int (1430, "Session 3 Start", group=g_ses)
s3_en = input.int (1515, "Session 3 End", group=g_ses)
// Exit
rr1 = input.float(1.2, "T1 R:R", group=g_ex, step=0.1)
rr2 = input.float(2.0, "T2 R:R", group=g_ex, step=0.1)
rr3 = input.float(3.2, "T3 R:R", group=g_ex, step=0.1)
sl_mult = input.float(1.0, "SL ATR Multiplier", group=g_ex, step=0.1)
atr_len = input.int (10, "ATR Length", group=g_ex)
use_trail = input.bool (true, "Trailing SL after T1", group=g_ex)
trail_mult = input.float(0.8, "Trail ATR Mult", group=g_ex, step=0.1)
use_be = input.bool (true, "Auto Breakeven after T1", group=g_ex)
// Display
show_lines = input.bool (true, "Show Target Lines", group=g_vis)
show_warmup = input.bool (true, "Show Warmup Alerts", group=g_vis)
show_regime = input.bool (true, "Show Regime Background", group=g_vis)
// ╔══════════════════════════════════════════════════════════════════╗
// ║ CORE INDICATORS ║
// ╚══════════════════════════════════════════════════════════════════╝
ema200 = ta.ema(close, 200)
ema50 = ta.ema(close, 50)
ema21 = ta.ema(close, 21)
ema9 = ta.ema(close, 9)
rsi14 = ta.rsi(close, 14)
rsi7 = ta.rsi(close, 7)
[ml, sl_m, hl] = ta.macd(close, 12, 26, 9)
[ms, ss, hs] = ta.macd(close, 5, 13, 5)
[_, st_d] = ta.supertrend(3.0, 10)
[stv2, st_d2] = ta.supertrend(2.0, 7)
vwap_v = ta.vwap(close)
atr_v = ta.atr(atr_len)
atr20 = ta.atr(20)
[pDI, mDI, adx_v] = ta.dmi(14, 14)
[pDIf, mDIf, adxf] = ta.dmi(7, 7)
[bbm, bbu, bbl] = ta.bb(close, 20, 2.0)
[kcm, kcu, kcl] = ta.kc(close, 20, 1.5, true)
stoch_k = ta.sma(ta.stoch(close, high, low, 14), 3)
stoch_d = ta.sma(stoch_k, 3)
obv_v = ta.obv
obv_ema = ta.ema(obv_v, 21)
vol_avg = ta.sma(volume, 20)
vol_avg5= ta.sma(volume, 5)
// ╔══════════════════════════════════════════════════════════════════╗
// ║ MODULE 1 — ADAPTIVE REGIME CLASSIFIER ║
// ║ 4 states: STRONG_TREND / WEAK_TREND / RANGING / CHOP ║
// ╚══════════════════════════════════════════════════════════════════╝
adx_norm = math.min((adx_v + adxf * 0.5) / 45.0, 1.0)
atr_ratio = atr_v / atr20 // current vs avg volatility
bb_squeeze = bbu < kcu and bbl > kcl
REGIME_STRONG = 0
REGIME_WEAK = 1
REGIME_RANGE = 2
REGIME_CHOP = 3
regime = adx_norm > 0.65 and atr_ratio > 0.85 ? REGIME_STRONG : adx_norm > 0.40 and atr_ratio > 0.70 ? REGIME_WEAK : adx_norm < 0.30 and not bb_squeeze ? REGIME_RANGE : REGIME_CHOP
trending = regime == REGIME_STRONG or regime == REGIME_WEAK
strong_trend = regime == REGIME_STRONG
ranging = regime == REGIME_RANGE
choppy = regime == REGIME_CHOP
// Adaptive weights per regime
w_trend = regime == REGIME_STRONG ? 0.28 : regime == REGIME_WEAK ? 0.20 : 0.10
w_mom = regime == REGIME_STRONG ? 0.18 : regime == REGIME_WEAK ? 0.22 : 0.20
w_vol = 0.16
w_vwap = regime == REGIME_RANGE ? 0.28 : 0.16
w_pa = 0.10
w_smc = regime == REGIME_STRONG ? 0.08 : 0.12
w_ml = 0.12
// ╔══════════════════════════════════════════════════════════════════╗
// ║ MODULE 2 — SMART MONEY: BOS / CHoCH / ORDER BLOCKS ║
// ╚══════════════════════════════════════════════════════════════════╝
ph = ta.pivothigh(high, swing_len, swing_len)
pl = ta.pivotlow (low, swing_len, swing_len)
var float last_ph = na
var float last_ph2 = na
var float last_pl = na
var float last_pl2 = na
var int ph_bar = na
var int pl_bar = na
if not na(ph)
last_ph2 := last_ph
last_ph := ph
ph_bar := bar_index - swing_len
if not na(pl)
last_pl2 := last_pl
last_pl := pl
pl_bar := bar_index - swing_len
// BOS: price breaks above last swing high (bullish) or below last swing low (bearish)
bos_bull = not na(last_ph) and close > last_ph and close[1] <= last_ph
bos_bear = not na(last_pl) and close < last_pl and close[1] >= last_pl
// CHoCH: higher timeframe structure flip
// Bullish CHoCH: was making lower highs, now breaks above last lower high
choch_bull = not na(last_ph) and not na(last_ph2) and last_ph < last_ph2 and close > last_ph
choch_bear = not na(last_pl) and not na(last_pl2) and last_pl > last_pl2 and close < last_pl
var bool smc_bull_bias = false
var bool smc_bear_bias = false
if bos_bull or choch_bull
smc_bull_bias := true
smc_bear_bias := false
if bos_bear or choch_bear
smc_bear_bias := true
smc_bull_bias := false
// Order Block detection
// Bullish OB: last bearish candle before a bullish BOS
var float ob_bull_top = na
var float ob_bull_bot = na
var int ob_bull_bar = na
var float ob_bear_top = na
var float ob_bear_bot = na
var int ob_bear_bar = na
if bos_bull
for i = 1 to ob_lookback
if close[i] < open[i] // bearish candle
ob_bull_top := high[i]
ob_bull_bot := low[i]
ob_bull_bar := bar_index - i
break
if bos_bear
for i = 1 to ob_lookback
if close[i] > open[i] // bullish candle
ob_bear_top := high[i]
ob_bear_bot := low[i]
ob_bear_bar := bar_index - i
break
// Is price inside an order block?
in_bull_ob = not na(ob_bull_top) and close >= ob_bull_bot and close <= ob_bull_top
in_bear_ob = not na(ob_bear_top) and close >= ob_bear_bot and close <= ob_bear_top
ob_ok_bull = not req_ob or in_bull_ob
ob_ok_bear = not req_ob or in_bear_ob
// Draw order block boxes
var box bull_ob_box = na
var box bear_ob_box = na
if show_ob and bos_bull and not na(ob_bull_bar)
box.delete(bull_ob_box)
bull_ob_box := box.new(
ob_bull_bar, ob_bull_top, bar_index, ob_bull_bot,
xloc=xloc.bar_index, extend=extend.right,
border_color=color.new(#00E676, 40), border_width=1,
bgcolor=color.new(#00E676, 88))
if show_ob and bos_bear and not na(ob_bear_bar)
box.delete(bear_ob_box)
bear_ob_box := box.new(
ob_bear_bar, ob_bear_top, bar_index, ob_bear_bot,
xloc=xloc.bar_index, extend=extend.right,
border_color=color.new(#FF5252, 40), border_width=1,
bgcolor=color.new(#FF5252, 88))
// BOS / CHoCH labels
if show_bos and bos_bull
label.new(bar_index, low, "BOS ▲",
style=label.style_label_up, color=color.new(#00E676, 20),
textcolor=color.white, yloc=yloc.belowbar, size=size.tiny)
if show_bos and bos_bear
label.new(bar_index, high, "BOS ▼",
style=label.style_label_down, color=color.new(#FF5252, 20),
textcolor=color.white, yloc=yloc.abovebar, size=size.tiny)
if show_bos and choch_bull
label.new(bar_index, low, "CHoCH ▲",
style=label.style_label_up, color=color.new(#FFD600, 20),
textcolor=color.black, yloc=yloc.belowbar, size=size.tiny)
if show_bos and choch_bear
label.new(bar_index, high, "CHoCH ▼",
style=label.style_label_down, color=color.new(#FFD600, 20),
textcolor=color.black, yloc=yloc.abovebar, size=size.tiny)
// ╔══════════════════════════════════════════════════════════════════╗
// ║ MODULE 3 — VOLUME DELTA ENGINE ║
// ║ Reconstructed buy/sell pressure from candle anatomy ║
// ╚══════════════════════════════════════════════════════════════════╝
rng = high - low
buy_vol = rng > 0 ? volume * (close - low) / rng : volume * 0.5
sell_vol = rng > 0 ? volume * (high - close) / rng : volume * 0.5
delta = buy_vol - sell_vol
cum_delta = ta.ema(delta, 14)
delta_bull = cum_delta > 0 and cum_delta > cum_delta[1]
delta_bear = cum_delta < 0 and cum_delta < cum_delta[1]
// Delta divergence: price up but delta falling = exhaustion
delta_div_bear = close > close[3] and cum_delta < cum_delta[3]
delta_div_bull = close < close[3] and cum_delta > cum_delta[3]
// Volume absorption: high volume, tiny body = big player absorbing
body_pct = rng > 0 ? math.abs(close - open) / rng : 0.0
absorb_bull = volume > vol_avg * 1.8 and body_pct < 0.25 and close > open
absorb_bear = volume > vol_avg * 1.8 and body_pct < 0.25 and close < open
vol_spike = volume > vol_avg * 1.3
// ╔══════════════════════════════════════════════════════════════════╗
// ║ MODULE 4 — MULTI-TIMEFRAME CONFLUENCE ║
// ╚══════════════════════════════════════════════════════════════════╝
htf5_ema9 = request.security(syminfo.tickerid, "5", ta.ema(close, 9), lookahead=barmerge.lookahead_off)
htf5_ema21 = request.security(syminfo.tickerid, "5", ta.ema(close, 21), lookahead=barmerge.lookahead_off)
htf5_close = request.security(syminfo.tickerid, "5", close, lookahead=barmerge.lookahead_off)
htf5_rsi = request.security(syminfo.tickerid, "5", ta.rsi(close, 14), lookahead=barmerge.lookahead_off)
[_5, htf5_std] = ta.supertrend(3.0, 10)
htf5_st = request.security(syminfo.tickerid, "5", htf5_std, lookahead=barmerge.lookahead_off)
htf15_ema9 = request.security(syminfo.tickerid, "15", ta.ema(close, 9), lookahead=barmerge.lookahead_off)
htf15_ema21 = request.security(syminfo.tickerid, "15", ta.ema(close, 21), lookahead=barmerge.lookahead_off)
htf15_close = request.security(syminfo.tickerid, "15", close, lookahead=barmerge.lookahead_off)
[_15, htf15_std] = ta.supertrend(3.0, 10)
htf15_st = request.security(syminfo.tickerid, "15", htf15_std, lookahead=barmerge.lookahead_off)
mtf5_bull = htf5_ema9 > htf5_ema21 and htf5_close > htf5_ema21 and htf5_st < 0 and htf5_rsi > 50
mtf5_bear = htf5_ema9 < htf5_ema21 and htf5_close < htf5_ema21 and htf5_st > 0 and htf5_rsi < 50
mtf15_bull = htf15_ema9 > htf15_ema21 and htf15_close > htf15_ema21 and htf15_st < 0
mtf15_bear = htf15_ema9 < htf15_ema21 and htf15_close < htf15_ema21 and htf15_st > 0
mtf_stack_bull = (mtf5_bull ? 1 : 0) + (mtf15_bull ? 1 : 0)
mtf_stack_bear = (mtf5_bear ? 1 : 0) + (mtf15_bear ? 1 : 0)
mtf_ok_bull = not req_mtf or mtf_stack_bull >= 1
mtf_ok_bear = not req_mtf or mtf_stack_bear >= 1
// ╔══════════════════════════════════════════════════════════════════╗
// ║ MODULE 5 — ML-STYLE PREDICTIVE BIAS ║
// ║ Counts historical occurrences of current pattern → win rate ║
// ╚══════════════════════════════════════════════════════════════════╝
// Pattern fingerprint: RSI zone + MACD state + volume state + candle direction
rsi_zone = rsi14 > 60 ? 2 : rsi14 > 50 ? 1 : rsi14 > 40 ? 0 : rsi14 > 30 ? -1 : -2
macd_state = ml > sl_m ? 1 : -1
vol_state = volume > vol_avg ? 1 : 0
candle_dir = close > open ? 1 : -1
pat_bull_match = 0
pat_bear_match = 0
pat_total = 0
for i = 1 to ml_lookback
h_rsi_zone = rsi14[i] > 60 ? 2 : rsi14[i] > 50 ? 1 : rsi14[i] > 40 ? 0 : rsi14[i] > 30 ? -1 : -2
h_macd_state = ml[i] > sl_m[i] ? 1 : -1
h_vol_state = volume[i] > vol_avg[i] ? 1 : 0
h_candle_dir = close[i] > open[i] ? 1 : -1
match = h_rsi_zone == rsi_zone and h_macd_state == macd_state and h_vol_state == vol_state and h_candle_dir == candle_dir
if match
pat_total += 1
if close[i - 1] > close[i]
pat_bull_match += 1
else
pat_bear_match += 1
ml_bull_rate = pat_total > 5 ? pat_bull_match / pat_total * 100 : 50.0
ml_bear_rate = pat_total > 5 ? pat_bear_match / pat_total * 100 : 50.0
// ╔══════════════════════════════════════════════════════════════════╗
// ║ MODULE 6 — SESSION & PREMIUM DECAY ║
// ╚══════════════════════════════════════════════════════════════════╝
t_hhmm = hour * 100 + minute
t_mins = hour * 60 + minute
to_min(hhmm) => (hhmm / 100) * 60 + hhmm % 100
raw1 = t_hhmm >= s1_st and t_hhmm < s1_en
raw2 = t_hhmm >= s2_st and t_hhmm < s2_en
raw3 = t_hhmm >= s3_st and t_hhmm < s3_en
ok1 = not use_decay or (to_min(s1_en) - t_mins > decay_mins)
ok2 = not use_decay or (to_min(s2_en) - t_mins > decay_mins)
ok3 = not use_decay or (to_min(s3_en) - t_mins > decay_mins)
in_s1 = raw1 and ok1
in_s2 = raw2 and ok2
in_s3 = raw3 and ok3
in_sess = not use_sess or (in_s1 or in_s2 or in_s3)
in_decay = use_sess and ((raw1 and not ok1) or (raw2 and not ok2) or (raw3 and not ok3))
sess_quality = in_s1 ? 1.0 : in_s2 ? 0.7 : in_s3 ? 0.85 : 0.0
// ╔══════════════════════════════════════════════════════════════════╗
// ║ MODULE 7 — CANDLE PATTERNS ║
// ╚══════════════════════════════════════════════════════════════════╝
c_body = math.abs(close - open)
c_range = high - low
c_br = c_range > 0 ? c_body / c_range : 0.0
c_uwk = high - math.max(close, open)
c_lwk = math.min(close, open) - low
bull_eng = close > open and open < close[1] and close > open[1] and close[1] < open[1]
bear_eng = close < open and open > close[1] and close < open[1] and close[1] > open[1]
pin_b = c_lwk > c_body * 2.0 and c_uwk < c_body * 0.5 and c_br < 0.35
pin_s = c_uwk > c_body * 2.0 and c_lwk < c_body * 0.5 and c_br < 0.35
mom_b = c_br > 0.65 and close > open
mom_s = c_br > 0.65 and close < open
ob_bull_c = high > high[1] and low < low[1] and close > open
ob_bear_c = high > high[1] and low < low[1] and close < open
bull_pat = bull_eng or pin_b or mom_b or ob_bull_c
bear_pat = bear_eng or pin_s or mom_s or ob_bear_c
cpat_ok_b = not req_candle or bull_pat
cpat_ok_s = not req_candle or bear_pat
// ╔══════════════════════════════════════════════════════════════════╗
// ║ MODULE 8 — OPTIONS INTELLIGENCE ║
// ╚══════════════════════════════════════════════════════════════════╝
// IV proxy: normalised BB width vs 50-bar average
bb_w = (bbu - bbl) / bbm
bb_w_avg = ta.sma(bb_w, 50)
iv_regime = bb_w > bb_w_avg * 1.3 ? "HIGH" : bb_w < bb_w_avg * 0.7 ? "LOW" : "NORMAL"
// Premium decay curve — worst in final 15min of session
decay_penalty = in_decay ? 0.7 : 1.0
// Distance from VWAP = moneyness proxy
vwap_dist_pct = math.abs(close - vwap_v) / vwap_v * 100
otm_penalty = vwap_dist_pct > 0.8 ? 0.85 : 1.0 // far from VWAP = more OTM
// ╔══════════════════════════════════════════════════════════════════╗
// ║ AI SCORING ENGINE — 7 MODULES ║
// ╚══════════════════════════════════════════════════════════════════╝
// ── BULL SCORES ───────────────────────────────────────────────────
// Trend module (max 25)
tr_b = 0.0
tr_b += close > ema200 ? 6.0 : 0.0
tr_b += close > ema50 ? 4.0 : 0.0
tr_b += ema21 > ema50 ? 4.0 : 0.0
tr_b += st_d < 0 ? 6.0 : 0.0
tr_b += st_d2 < 0 ? 5.0 : 0.0
// Momentum module (max 25)
rsi_w = rsi14 * 0.5 + rsi14[1] * 0.3 + rsi14[2] * 0.2
h_rise3 = hl > hl[1] and hl[1] > hl[2]
consec_b = rsi14 > rsi14[1] and ms > ss and ms[1] > ss[1]
mo_b = 0.0
mo_b += (rsi_w > 52 and rsi_w < 72) ? 5.0 : 0.0
mo_b += (rsi7 > 54 and rsi7 < 80) ? 4.0 : 0.0
mo_b += ml > sl_m ? 5.0 : 0.0
mo_b += ms > ss ? 4.0 : 0.0
mo_b += h_rise3 ? 5.0 : 0.0
mo_b += stoch_k > 50 and stoch_k > stoch_d ? 2.0 : 0.0
// Volume module (max 20)
vl_b = 0.0
vl_b += vol_spike and close > open ? 8.0 : 0.0
vl_b += delta_bull ? 6.0 : 0.0
vl_b += obv_v > obv_ema ? 4.0 : 0.0
vl_b += absorb_bull ? 2.0 : 0.0
// VWAP module (max 20)
vw_b = 0.0
vw_b += close > vwap_v ? 7.0 : 0.0
vw_b += open > vwap_v ? 3.0 : 0.0
vw_b += low > vwap_v ? 4.0 : 0.0
vw_b += close > bbm ? 4.0 : 0.0
vw_b += not delta_div_bear ? 2.0 : 0.0
// Price Action module (max 10)
pa_b = 0.0
pa_b += c_br > 0.60 ? 4.0 : 0.0
pa_b += bull_eng ? 4.0 : 0.0
pa_b += (high - close) < (close - low) * 0.35 ? 2.0 : 0.0
// SMC module (max 20)
smc_b = 0.0
smc_b += smc_bull_bias ? 6.0 : 0.0
smc_b += bos_bull ? 5.0 : 0.0
smc_b += choch_bull ? 4.0 : 0.0
smc_b += in_bull_ob ? 5.0 : 0.0
// ML module (max 20)
ml_b = 0.0
ml_b += ml_bull_rate >= 65 ? 10.0 : ml_bull_rate >= 55 ? 6.0 : ml_bull_rate >= 50 ? 3.0 : 0.0
ml_b += mtf_stack_bull == 2 ? 10.0 : mtf_stack_bull == 1 ? 6.0 : 0.0
// ── BEAR SCORES ───────────────────────────────────────────────────
tr_s = 0.0
tr_s += close < ema200 ? 6.0 : 0.0
tr_s += close < ema50 ? 4.0 : 0.0
tr_s += ema21 < ema50 ? 4.0 : 0.0
tr_s += st_d > 0 ? 6.0 : 0.0
tr_s += st_d2 > 0 ? 5.0 : 0.0
h_fall3 = hl < hl[1] and hl[1] < hl[2]
consec_s = rsi14 < rsi14[1] and ms < ss and ms[1] < ss[1]
mo_s = 0.0
mo_s += (rsi_w < 48 and rsi_w > 28) ? 5.0 : 0.0
mo_s += (rsi7 < 46 and rsi7 > 20) ? 4.0 : 0.0
mo_s += ml < sl_m ? 5.0 : 0.0
mo_s += ms < ss ? 4.0 : 0.0
mo_s += h_fall3 ? 5.0 : 0.0
mo_s += stoch_k < 50 and stoch_k < stoch_d ? 2.0 : 0.0
vl_s = 0.0
vl_s += vol_spike and close < open ? 8.0 : 0.0
vl_s += delta_bear ? 6.0 : 0.0
vl_s += obv_v < obv_ema ? 4.0 : 0.0
vl_s += absorb_bear ? 2.0 : 0.0
vw_s = 0.0
vw_s += close < vwap_v ? 7.0 : 0.0
vw_s += open < vwap_v ? 3.0 : 0.0
vw_s += high < vwap_v ? 4.0 : 0.0
vw_s += close < bbm ? 4.0 : 0.0
vw_s += not delta_div_bull ? 2.0 : 0.0
pa_s = 0.0
pa_s += c_br > 0.60 ? 4.0 : 0.0
pa_s += bear_eng ? 4.0 : 0.0
pa_s += (close - low) < (high - close) * 0.35 ? 2.0 : 0.0
smc_s = 0.0
smc_s += smc_bear_bias ? 6.0 : 0.0
smc_s += bos_bear ? 5.0 : 0.0
smc_s += choch_bear ? 4.0 : 0.0
smc_s += in_bear_ob ? 5.0 : 0.0
ml_s = 0.0
ml_s += ml_bear_rate >= 65 ? 10.0 : ml_bear_rate >= 55 ? 6.0 : ml_bear_rate >= 50 ? 3.0 : 0.0
ml_s += mtf_stack_bear == 2 ? 10.0 : mtf_stack_bear == 1 ? 6.0 : 0.0
// ── FINAL PROBABILITY ─────────────────────────────────────────────
raw_bull = ((tr_b/25.0)*w_trend + (mo_b/25.0)*w_mom + (vl_b/20.0)*w_vol +
(vw_b/20.0)*w_vwap + (pa_b/10.0)*w_pa + (smc_b/20.0)*w_smc +
(ml_b/20.0)*w_ml) * 100
raw_bear = ((tr_s/25.0)*w_trend + (mo_s/25.0)*w_mom + (vl_s/20.0)*w_vol +
(vw_s/20.0)*w_vwap + (pa_s/10.0)*w_pa + (smc_s/20.0)*w_smc +
(ml_s/20.0)*w_ml) * 100
// Regime boost: strong trend amplifies, chop suppresses
reg_mult = regime == REGIME_STRONG ? 1.15 : regime == REGIME_CHOP ? 0.60 : 1.0
// Options decay & OTM penalty
opt_mult = decay_penalty * otm_penalty
prob_bull = math.min(raw_bull * reg_mult * opt_mult, 99)
prob_bear = math.min(raw_bear * reg_mult * opt_mult, 99)
// Mutual exclusion — suppress weaker side
prob_bull := prob_bull > prob_bear + 8 ? prob_bull : prob_bull > prob_bear ? prob_bull * 0.80 : prob_bull * 0.65
prob_bear := prob_bear > prob_bull + 8 ? prob_bear : prob_bear > prob_bull ? prob_bear * 0.80 : prob_bear * 0.65
// Suppress signals in chop
prob_bull := choppy ? prob_bull * 0.50 : prob_bull
prob_bear := choppy ? prob_bear * 0.50 : prob_bear
// ╔══════════════════════════════════════════════════════════════════╗
// ║ SIGNAL HEAT SCORE (1–10) ║
// ╚══════════════════════════════════════════════════════════════════╝
heat_b = 0.0
heat_b += prob_bull >= 85 ? 3.0 : prob_bull >= 75 ? 2.5 : prob_bull >= 68 ? 2.0 : 1.0
heat_b += mtf_stack_bull == 2 ? 2.5 : mtf_stack_bull == 1 ? 1.5 : 0.0
heat_b += smc_bull_bias ? 1.5 : 0.0
heat_b += delta_bull ? 1.0 : 0.0
heat_b += bull_pat ? 0.5 : 0.0
heat_b += in_bull_ob ? 1.0 : 0.0
heat_b += sess_quality * 0.5
heat_s = 0.0
heat_s += prob_bear >= 85 ? 3.0 : prob_bear >= 75 ? 2.5 : prob_bear >= 68 ? 2.0 : 1.0
heat_s += mtf_stack_bear == 2 ? 2.5 : mtf_stack_bear == 1 ? 1.5 : 0.0
heat_s += smc_bear_bias ? 1.5 : 0.0
heat_s += delta_bear ? 1.0 : 0.0
heat_s += bear_pat ? 0.5 : 0.0
heat_s += in_bear_ob ? 1.0 : 0.0
heat_s += sess_quality * 0.5
bull_heat = math.min(math.round(heat_b), 10)
bear_heat = math.min(math.round(heat_s), 10)
heat_blk(s) =>
s >= 9 ? "██████████" : s >= 8 ? "█████████░" : s >= 7 ? "████████░░" : s >= 6 ? "███████░░░" : s >= 5 ? "██████░░░░" : s >= 4 ? "█████░░░░░" : s >= 3 ? "████░░░░░░" : s >= 2 ? "███░░░░░░░" : s >= 1 ? "██░░░░░░░░" : "█░░░░░░░░░"
heat_clr(s) =>
s >= 9 ? color.new(#00E676, 0) : s >= 7 ? color.new(#76FF03, 0) : s >= 5 ? color.new(#FFD600, 0) : s >= 3 ? color.new(#FF6D00, 0) : color.new(#FF1744, 0)
// ╔══════════════════════════════════════════════════════════════════╗
// ║ FINAL ENTRY SIGNALS ║
// ╚══════════════════════════════════════════════════════════════════╝
bull_bias = ema9 > ema21 and close > ema21
bear_bias = ema9 < ema21 and close < ema21
consec_ok_b = not req_consec or consec_b
consec_ok_s = not req_consec or consec_s
call_sig = prob_bull >= min_prob
and bull_bias and st_d < 0
and cpat_ok_b and consec_ok_b
and mtf_ok_bull and ob_ok_bull
and not delta_div_bear
and in_sess and not choppy
put_sig = prob_bear >= min_prob
and bear_bias and st_d > 0
and cpat_ok_s and consec_ok_s
and mtf_ok_bear and ob_ok_bear
and not delta_div_bull
and in_sess and not choppy
warmup_b = show_warmup and prob_bull >= warmup_thr and prob_bull < min_prob and bull_bias and st_d < 0 and in_sess
warmup_s = show_warmup and prob_bear >= warmup_thr and prob_bear < min_prob and bear_bias and st_d > 0 and in_sess
// ╔══════════════════════════════════════════════════════════════════╗
// ║ INTELLIGENT SL ENGINE — 5-layer structure-aware placement ║
// ║ ║
// ║ For 1-min Nifty scalping, a flat ATR-multiple SL is too naive. ║
// ║ Price noise alone eats through fixed-distance stops. Instead: ║
// ║ ║
// ║ Layer 1 — Recent swing low/high (last 5 bars) ║
// ║ The lowest low (for calls) or highest high (for puts) of the ║
// ║ past 5 bars is the real structural invalidation point. ║
// ║ If price goes below that low, the setup is broken — not when ║
// ║ it hits an arbitrary ATR distance. ║
// ║ ║
// ║ Layer 2 — Candle wick anatomy ║
// ║ If the entry candle has a lower wick > 30% of its range, ║
// ║ that wick IS the proven rejection. SL goes just below it ║
// ║ (1 tick buffer). This is tighter AND more logical than ATR. ║
// ║ ║
// ║ Layer 3 — Order block floor/ceiling ║
// ║ If inside a bull OB, SL goes below the OB bottom. ║
// ║ If inside a bear OB, SL goes above the OB top. ║
// ║ OB zones ARE institutional rejection — if price exits them ║
// ║ the thesis is invalidated. ║
// ║ ║
// ║ Layer 4 — Volatility envelope (floor + ceiling) ║
// ║ SL is clamped between 0.4× ATR (minimum — avoids noise stop) ║
// ║ and 1.6× ATR (maximum — avoids unacceptable R:R). ║
// ║ In a BB squeeze, tighten to 0.35× ATR floor (low volatility ║
// ║ = price moves less = tighter SL is safe). ║
// ║ ║
// ║ Layer 5 — VWAP buffer ║
// ║ For calls, if VWAP is between close and the raw SL, ║
// ║ place SL just below VWAP (VWAP is the strongest intraday ║
// ║ magnet — a close below it on 1-min invalidates bull thesis). ║
// ║ Same logic for puts above VWAP. ║
// ║ ║
// ║ Final SL = best (tightest logical) of all applicable layers, ║
// ║ then clamped to the volatility envelope. ║
// ║ Targets scale from this final SL distance, not raw ATR. ║
// ╚══════════════════════════════════════════════════════════════════╝
// ── Layer 1: recent structure low/high (5-bar lookback) ───────────
struct_low = ta.lowest(low, 5) // last 5 bars lowest low
struct_high = ta.highest(high, 5) // last 5 bars highest high
// ── Layer 2: candle wick anatomy ──────────────────────────────────
entry_low_wick = math.min(open, close) - low // lower wick size
entry_high_wick = high - math.max(open, close) // upper wick size
candle_rng = high - low
wick_ratio_low = candle_rng > 0 ? entry_low_wick / candle_rng : 0.0
wick_ratio_high = candle_rng > 0 ? entry_high_wick / candle_rng : 0.0
tick = syminfo.mintick
// Wick-based SL candidates
wick_sl_bull = wick_ratio_low > 0.30 ? low - tick * 2 : na // just below wick
wick_sl_bear = wick_ratio_high > 0.30 ? high + tick * 2 : na // just above wick
// ── Layer 3: order block floor/ceiling ────────────────────────────
ob_sl_bull = in_bull_ob and not na(ob_bull_bot) ? ob_bull_bot - tick * 2 : na
ob_sl_bear = in_bear_ob and not na(ob_bear_top) ? ob_bear_top + tick * 2 : na
// ── Layer 4: volatility envelope ──────────────────────────────────
atr_floor_mult = bb_squeeze ? 0.35 : 0.40 // tighter floor in squeeze
atr_ceil_mult = strong_trend ? 1.80 : 1.60 // slightly wider in strong trend
atr_floor_bull = close - atr_v * atr_floor_mult
atr_floor_bear = close + atr_v * atr_floor_mult
atr_ceil_bull = close - atr_v * atr_ceil_mult
atr_ceil_bear = close + atr_v * atr_ceil_mult
// ── Layer 5: VWAP buffer ──────────────────────────────────────────
// For calls: if VWAP is below close but above raw struct_low → use VWAP - 1 tick
// For puts: if VWAP is above close but below raw struct_high → use VWAP + 1 tick
vwap_sl_bull = (vwap_v < close and vwap_v > struct_low) ? vwap_v - tick * 3 : na
vwap_sl_bear = (vwap_v > close and vwap_v < struct_high) ? vwap_v + tick * 3 : na
// ── Assemble final SL: pick the HIGHEST (tightest) valid bull SL ──
// Priority: OB > Wick > VWAP > Structure > ATR floor
// Then clamp: must not be BELOW the ATR ceiling (too wide = bad R:R)
// must not be ABOVE the ATR floor (too close = noise stop)
raw_sl_bull = struct_low - tick * 2 // structure-based baseline
raw_sl_bear = struct_high + tick * 2
// Apply wick if valid and tighter than structure
raw_sl_bull := not na(wick_sl_bull) and wick_sl_bull > raw_sl_bull ? wick_sl_bull : raw_sl_bull
raw_sl_bear := not na(wick_sl_bear) and wick_sl_bear < raw_sl_bear ? wick_sl_bear : raw_sl_bear
// Apply VWAP if valid and tighter than current best
raw_sl_bull := not na(vwap_sl_bull) and vwap_sl_bull > raw_sl_bull ? vwap_sl_bull : raw_sl_bull
raw_sl_bear := not na(vwap_sl_bear) and vwap_sl_bear < raw_sl_bear ? vwap_sl_bear : raw_sl_bear
// Apply OB if valid and tighter
raw_sl_bull := not na(ob_sl_bull) and ob_sl_bull > raw_sl_bull ? ob_sl_bull : raw_sl_bull
raw_sl_bear := not na(ob_sl_bear) and ob_sl_bear < raw_sl_bear ? ob_sl_bear : raw_sl_bear
// Clamp to volatility envelope: floor (not too tight) and ceiling (not too wide)
call_sl = math.max(math.min(raw_sl_bull, atr_floor_bull), atr_ceil_bull)
put_sl = math.min(math.max(raw_sl_bear, atr_floor_bear), atr_ceil_bear)
// ── Actual risk distance from these intelligent SLs ───────────────
sl_d_call = math.max(close - call_sl, atr_v * 0.4) // true risk in points
sl_d_put = math.max(put_sl - close, atr_v * 0.4)
// ── Targets scale from actual SL distance, not flat ATR ───────────
// This keeps R:R ratios honest regardless of how tight/wide SL ended up
call_t1 = close + sl_d_call * rr1
call_t2 = close + sl_d_call * rr2
call_t3 = close + sl_d_call * rr3
put_t1 = close - sl_d_put * rr1
put_t2 = close - sl_d_put * rr2
put_t3 = close - sl_d_put * rr3
// Trailing SL — based on Supertrend value + ATR buffer
trl_b_sl = stv2 - atr_v * trail_mult
trl_s_sl = stv2 + atr_v * trail_mult
// sl_d for legacy uses (BE detection uses call/put specific now)
sl_d = atr_v * sl_mult
// ╔══════════════════════════════════════════════════════════════════╗
// ║ COLOUR PALETTE ║
// ╚══════════════════════════════════════════════════════════════════╝
C_W = color.white
C_DARK = color.new(#060A12, 0)
LC_SL = color.new(#FF2D2D, 15)
LC_T1_C = color.new(#00E676, 15)
LC_T2_C = color.new(#00C853, 15)
LC_T3_C = color.new(#00BCD4, 10)
LC_BE = color.new(#00E5FF, 15)
LC_TSL = color.new(#FFB300, 10)
LC_T1_P = color.new(#FF9100, 15)
LC_T2_P = color.new(#C62828, 15)
LC_T3_P = color.new(#7B1FA2, 10)
// ╔══════════════════════════════════════════════════════════════════╗
// ║ PERSISTENT HANDLES ║
// ╚══════════════════════════════════════════════════════════════════╝
var line ln_sl = na
var line ln_t1 = na
var line ln_t2 = na
var line ln_t3 = na
var line ln_be = na
var line ln_tsl = na
var label lb_sl = na
var label lb_t1 = na
var label lb_t2 = na
var label lb_t3 = na
var label lb_be = na
var label lb_tsl = na
var float sv_sl = na
var float sv_t1 = na
var float sv_t2 = na
var float sv_t3 = na
var bool sv_call = false
var bool act_call = false
var bool act_put = false
var float entry_px = na
var bool t1_hit = false
var bool be_on = false
// ╔══════════════════════════════════════════════════════════════════╗
// ║ TRADE LIFECYCLE ENGINE ║
// ║ ║
// ║ States: IDLE → ACTIVE → (T1 HIT → BE/TRAIL) → CLOSED ║
// ║ ║
// ║ SL breach detection runs EVERY bar: ║
// ║ • Before T1: breach = close crosses sv_sl ║
// ║ • After T1 with trail: breach = close crosses TSL level ║
// ║ • After T1 with BE: breach = close crosses entry_px ║
// ║ ║
// ║ On breach: ║
// ║ 1. STOPPED label fires at breach bar ║
// ║ 2. All lines + labels wiped ║
// ║ 3. Trade state reset to IDLE ║
// ║ 4. call_sig / put_sig can fire immediately on same bar ║
// ║ → new signal = new lines + targets drawn right away ║
// ╚══════════════════════════════════════════════════════════════════╝
// ── T1 detection ──────────────────────────────────────────────────
if act_call and not na(sv_t1) and not t1_hit
if high >= sv_t1
t1_hit := true
be_on := use_be
if act_put and not na(sv_t1) and not t1_hit
if low <= sv_t1
t1_hit := true
be_on := use_be
// ── SL / TSL breach detection — runs every bar BEFORE new signal ──
var bool sl_just_hit = false
sl_just_hit := false
if act_call and not na(sv_sl)
// Before T1: hard SL breach
plain_sl_breach = not t1_hit and low <= sv_sl
// After T1 + trailing: TSL breach
trail_sl_breach = t1_hit and use_trail and low <= trl_b_sl
// After T1 + BE: BE breach (price returned below entry)
be_breach = t1_hit and be_on and low < entry_px
if plain_sl_breach or trail_sl_breach or be_breach
sl_just_hit := true
// STOPPED label
stop_txt = plain_sl_breach ? " ✕ STOPPED SL hit " : trail_sl_breach ? " ✕ STOPPED TSL hit " : " ✕ STOPPED BE breach "
label.new(bar_index, low, stop_txt,
style=label.style_label_up, color=color.new(#FF0000, 0),
textcolor=color.white, yloc=yloc.belowbar, size=size.small)
// Wipe all lines and labels
line.delete(ln_sl)
line.delete(ln_t1)
line.delete(ln_t2)
line.delete(ln_t3)
line.delete(ln_be)
line.delete(ln_tsl)
label.delete(lb_sl)
label.delete(lb_t1)
label.delete(lb_t2)
label.delete(lb_t3)
label.delete(lb_be)
label.delete(lb_tsl)
// Reset trade state → IDLE
act_call := false
act_put := false
entry_px := na
t1_hit := false
be_on := false
sv_sl := na
sv_t1 := na
sv_t2 := na
sv_t3 := na
if act_put and not na(sv_sl)
plain_sl_breach = not t1_hit and high >= sv_sl
trail_sl_breach = t1_hit and use_trail and high >= trl_s_sl
be_breach = t1_hit and be_on and high > entry_px
if plain_sl_breach or trail_sl_breach or be_breach
sl_just_hit := true
stop_txt = plain_sl_breach ? " ✕ STOPPED SL hit " : trail_sl_breach ? " ✕ STOPPED TSL hit " : " ✕ STOPPED BE breach "
label.new(bar_index, high, stop_txt,
style=label.style_label_down, color=color.new(#FF0000, 0),
textcolor=color.white, yloc=yloc.abovebar, size=size.small)
line.delete(ln_sl)
line.delete(ln_t1)
line.delete(ln_t2)
line.delete(ln_t3)
line.delete(ln_be)
line.delete(ln_tsl)
label.delete(lb_sl)
label.delete(lb_t1)
label.delete(lb_t2)
label.delete(lb_t3)
label.delete(lb_be)
label.delete(lb_tsl)
act_call := false
act_put := false
entry_px := na
t1_hit := false
be_on := false
sv_sl := na
sv_t1 := na
sv_t2 := na
sv_t3 := na
// ── T3 / trade complete detection ─────────────────────────────────
var bool trade_done = false
trade_done := false
if act_call and not na(sv_t3) and high >= sv_t3
trade_done := true
label.new(bar_index, high, " ✓ T3 HIT TRADE COMPLETE ",
style=label.style_label_down, color=color.new(#00BCD4, 0),
textcolor=color.black, yloc=yloc.abovebar, size=size.small)
line.delete(ln_sl)
line.delete(ln_t1)
line.delete(ln_t2)
line.delete(ln_t3)
line.delete(ln_be)
line.delete(ln_tsl)
label.delete(lb_sl)
label.delete(lb_t1)
label.delete(lb_t2)
label.delete(lb_t3)
label.delete(lb_be)
label.delete(lb_tsl)
act_call := false
act_put := false
entry_px := na
t1_hit := false
be_on := false
sv_sl := na
sv_t1 := na
sv_t2 := na
sv_t3 := na
if act_put and not na(sv_t3) and low <= sv_t3
trade_done := true
label.new(bar_index, low, " ✓ T3 HIT TRADE COMPLETE ",
style=label.style_label_up, color=color.new(#00BCD4, 0),
textcolor=color.black, yloc=yloc.belowbar, size=size.small)
line.delete(ln_sl)
line.delete(ln_t1)
line.delete(ln_t2)
line.delete(ln_t3)
line.delete(ln_be)
line.delete(ln_tsl)
label.delete(lb_sl)
label.delete(lb_t1)
label.delete(lb_t2)
label.delete(lb_t3)
label.delete(lb_be)
label.delete(lb_tsl)
act_call := false
act_put := false
entry_px := na
t1_hit := false
be_on := false
sv_sl := na
sv_t1 := na
sv_t2 := na
sv_t3 := na
// ── NEW SIGNAL: only fires when IDLE (no active trade) ────────────
// After SL breach: state resets to IDLE on same bar → new signal
// can fire immediately if AI conditions are met
if show_lines and (call_sig or put_sig) and not act_call and not act_put
line.delete(ln_sl)
line.delete(ln_t1)
line.delete(ln_t2)
line.delete(ln_t3)
line.delete(ln_be)
line.delete(ln_tsl)
act_call := call_sig
act_put := put_sig
entry_px := close
t1_hit := false
be_on := false
sv_call := call_sig
bx = bar_index
if call_sig
sv_sl := call_sl
sv_t1 := call_t1
sv_t2 := call_t2
sv_t3 := call_t3
ln_sl := line.new(bx, call_sl, bx, call_sl, xloc=xloc.bar_index, extend=extend.right, color=LC_SL, width=2, style=line.style_dotted)
ln_t1 := line.new(bx, call_t1, bx, call_t1, xloc=xloc.bar_index, extend=extend.right, color=LC_T1_C, width=1, style=line.style_dashed)
ln_t2 := line.new(bx, call_t2, bx, call_t2, xloc=xloc.bar_index, extend=extend.right, color=LC_T2_C, width=2, style=line.style_dashed)
ln_t3 := line.new(bx, call_t3, bx, call_t3, xloc=xloc.bar_index, extend=extend.right, color=LC_T3_C, width=3, style=line.style_solid)
if put_sig
sv_sl := put_sl
sv_t1 := put_t1
sv_t2 := put_t2
sv_t3 := put_t3
ln_sl := line.new(bx, put_sl, bx, put_sl, xloc=xloc.bar_index, extend=extend.right, color=LC_SL, width=2, style=line.style_dotted)
ln_t1 := line.new(bx, put_t1, bx, put_t1, xloc=xloc.bar_index, extend=extend.right, color=LC_T1_P, width=1, style=line.style_dashed)
ln_t2 := line.new(bx, put_t2, bx, put_t2, xloc=xloc.bar_index, extend=extend.right, color=LC_T2_P, width=2, style=line.style_dashed)
ln_t3 := line.new(bx, put_t3, bx, put_t3, xloc=xloc.bar_index, extend=extend.right, color=LC_T3_P, width=3, style=line.style_solid)
// ── Breakeven line ─────────────────────────────────────────────────
if show_lines and be_on and (act_call or act_put) and not na(entry_px)
line.delete(ln_be)
line.delete(ln_sl)
ln_be := line.new(bar_index, entry_px, bar_index, entry_px,
xloc=xloc.bar_index, extend=extend.right,
color=color.new(#00E5FF, 15), width=2, style=line.style_solid)
// ── Trailing SL line ───────────────────────────────────────────────
if show_lines and use_trail and t1_hit and (act_call or act_put)
line.delete(ln_tsl)
trl = act_call ? trl_b_sl : trl_s_sl
ln_tsl := line.new(bar_index, trl, bar_index, trl,
xloc=xloc.bar_index, extend=extend.right,
color=LC_TSL, width=2, style=line.style_solid)
// ╔══════════════════════════════════════════════════════════════════╗
// ║ DYNAMIC PILL LABELS — right edge, live intelligence ║
// ║ ║
// ║ Each label is rebuilt every bar with real-time context: ║
// ║ • SL → distance in pts + SAFE / AT RISK / BREACHED status ║
// ║ • T1 → ● HIT / ○ NEXT / ◌ PENDING + pts-to-target ║
// ║ • T2 → same + colour shifts as price approaches ║
// ║ • T3 → same ║
// ║ • TSL → live trail value + pts from current price ║
// ║ • BE → PROTECTED when price safely beyond entry ║
// ║ ║
// ║ Colour intelligence: ║
// ║ CALL targets: grey=far → gold=50% there → bright=close ║
// ║ SL: green=safe → amber=warning → red=danger ║
// ╚══════════════════════════════════════════════════════════════════╝
if barstate.islast and show_lines and not na(sv_sl)
rx = bar_index
label.delete(lb_sl)
label.delete(lb_t1)
label.delete(lb_t2)
label.delete(lb_t3)
label.delete(lb_be)
label.delete(lb_tsl)
// ── Live distance helpers ────────────────────────────────────────
// How far is current price from each level, in points
d_sl = math.abs(close - sv_sl)
d_t1 = math.abs(close - sv_t1)
d_t2 = math.abs(close - sv_t2)
d_t3 = math.abs(close - sv_t3)
// Trade range = entry to T3 (full range of the trade)
trade_rng = math.abs(sv_t3 - entry_px)
// Progress ratio toward each target (0.0 = at entry, 1.0 = at target)
prog_t1 = trade_rng > 0 ? math.min(math.abs(close - entry_px) / math.abs(sv_t1 - entry_px), 1.0) : 0.0
prog_t2 = trade_rng > 0 ? math.min(math.abs(close - entry_px) / math.abs(sv_t2 - entry_px), 1.0) : 0.0
prog_t3 = trade_rng > 0 ? math.min(math.abs(close - entry_px) / math.abs(sv_t3 - entry_px), 1.0) : 0.0
// SL proximity ratio (0 = safe far away, 1 = right at SL)
sl_rng = math.abs(entry_px - sv_sl)
sl_prox = sl_rng > 0 ? math.min(d_sl / sl_rng, 1.0) : 1.0
// Has price actually breached each level in the correct direction?
t1_done = sv_call ? close >= sv_t1 : close <= sv_t1
t2_done = sv_call ? close >= sv_t2 : close <= sv_t2
t3_done = sv_call ? close >= sv_t3 : close <= sv_t3
sl_hit = sv_call ? close <= sv_sl : close >= sv_sl
// ── SL label — colour & text changes based on proximity ─────────
// safe (>80% range away) → warning (40-80%) → danger (<40%) → breached
sl_status = sl_hit ? " ✕ BREACHED " : sl_prox > 0.80 ? " ✓ SAFE " : sl_prox > 0.50 ? " ⚠ WARNING " : " ✕ DANGER "
sl_clr = sl_hit ? color.new(#FF0000, 0) : sl_prox > 0.80 ? color.new(#1B5E20, 0) : sl_prox > 0.50 ? color.new(#E65100, 0) : color.new(#FF2D2D, 0)
sl_arrow = sv_call ? "▼ SL " : "▲ SL "
if not be_on
lb_sl := make_pill(rx, sv_sl,
" " + sl_arrow + f_price(sv_sl) + " " + f_pts(d_sl) + sl_status,
sl_clr, C_W)
// ── Target label builder — shared logic for T1/T2/T3 ────────────
// Status tag: ● HIT | ○ NEXT | ◌ PENDING
// Colour: dims when hit, brightens as price approaches
// ── T1 ───────────────────────────────────────────────────────────
t1_status = t1_done ? " ● HIT " : prog_t1 > 0.75 ? " ○ NEXT ▶▶ " : prog_t1 > 0.40 ? " ○ NEXT ▶ " : " ◌ PENDING "
t1_pct_str = t1_done ? "" : " (" + str.tostring(math.round(prog_t1 * 100, 0)) + "%)"
if sv_call
t1_bg = t1_done ? color.new(#546E7A, 0) : prog_t1 > 0.75 ? color.new(#00E676, 0) : prog_t1 > 0.40 ? color.new(#FFD600, 0) : color.new(#37474F, 0)
t1_tc = t1_done or prog_t1 <= 0.40 ? C_W : C_DARK
lb_t1 := make_pill(rx, sv_t1,
" ▲ T1 " + f_price(sv_t1) + " " + f_pts(d_t1) + t1_pct_str + t1_status,
t1_bg, t1_tc)
else
t1_bg = t1_done ? color.new(#546E7A, 0) : prog_t1 > 0.75 ? color.new(#FF9100, 0) : prog_t1 > 0.40 ? color.new(#FFD600, 0) : color.new(#37474F, 0)
t1_tc = t1_done or prog_t1 <= 0.40 ? C_W : C_DARK
lb_t1 := make_pill(rx, sv_t1,
" ▼ T1 " + f_price(sv_t1) + " " + f_pts(d_t1) + t1_pct_str + t1_status,
t1_bg, t1_tc)
// ── T2 ───────────────────────────────────────────────────────────
t2_status = t2_done ? " ● HIT " : t1_done and prog_t2 > 0.75 ? " ○ NEXT ▶▶ " : t1_done and prog_t2 > 0.40 ? " ○ NEXT ▶ " : " ◌ PENDING "
t2_pct_str = t2_done ? "" : " (" + str.tostring(math.round(prog_t2 * 100, 0)) + "%)"
if sv_call
t2_bg = t2_done ? color.new(#546E7A, 0) : t1_done and prog_t2 > 0.75 ? color.new(#00C853, 0) : t1_done and prog_t2 > 0.40 ? color.new(#FFD600, 0) : t1_done ? color.new(#1B5E20, 0) : color.new(#263238, 0)
t2_tc = t2_done or (not t1_done) ? C_W : C_DARK
lb_t2 := make_pill(rx, sv_t2,
" ▲ T2 " + f_price(sv_t2) + " " + f_pts(d_t2) + t2_pct_str + t2_status,
t2_bg, t2_tc)
else
t2_bg = t2_done ? color.new(#546E7A, 0) : t1_done and prog_t2 > 0.75 ? color.new(#C62828, 0) : t1_done and prog_t2 > 0.40 ? color.new(#FFD600, 0) : t1_done ? color.new(#7B1A1A, 0) : color.new(#263238, 0)
t2_tc = C_W
lb_t2 := make_pill(rx, sv_t2,
" ▼ T2 " + f_price(sv_t2) + " " + f_pts(d_t2) + t2_pct_str + t2_status,
t2_bg, t2_tc)
// ── T3 ───────────────────────────────────────────────────────────
t3_status = t3_done ? " ● HIT " : t2_done and prog_t3 > 0.75 ? " ○ NEXT ▶▶ " : t2_done and prog_t3 > 0.40 ? " ○ NEXT ▶ " : " ◌ PENDING "
t3_pct_str = t3_done ? "" : " (" + str.tostring(math.round(prog_t3 * 100, 0)) + "%)"
if sv_call
t3_bg = t3_done ? color.new(#546E7A, 0) : t2_done and prog_t3 > 0.75 ? color.new(#00BCD4, 0) : t2_done and prog_t3 > 0.40 ? color.new(#FFD600, 0) : t2_done ? color.new(#006064, 0) : color.new(#1C313A, 0)
t3_tc = t3_done or (not t2_done) ? C_W : C_DARK
lb_t3 := make_pill(rx, sv_t3,
" ▲ T3 " + f_price(sv_t3) + " " + f_pts(d_t3) + t3_pct_str + t3_status,
t3_bg, t3_tc)
else
t3_bg = t3_done ? color.new(#546E7A, 0) : t2_done and prog_t3 > 0.75 ? color.new(#7B1FA2, 0) : t2_done and prog_t3 > 0.40 ? color.new(#FFD600, 0) : t2_done ? color.new(#4A148C, 0) : color.new(#1C313A, 0)
t3_tc = C_W
lb_t3 := make_pill(rx, sv_t3,
" ▼ T3 " + f_price(sv_t3) + " " + f_pts(d_t3) + t3_pct_str + t3_status,
t3_bg, t3_tc)
// ── BE label — shows PROTECTED once safe ─────────────────────────
if be_on and not na(entry_px)
be_safe = sv_call ? close > entry_px + atr_v * 0.3 : close < entry_px - atr_v * 0.3
be_status = be_safe ? " ✓ PROTECTED" : " ≈ AT ENTRY "
be_clr = be_safe ? color.new(#00E5FF, 0) : color.new(#0288D1, 0)
lb_be := make_pill(rx, entry_px,
" ═ BE " + f_price(entry_px) + be_status,
be_clr, C_DARK)
// ── TSL label — live trailing distance ───────────────────────────
if use_trail and t1_hit and (act_call or act_put)
trl_lbl = act_call ? trl_b_sl : trl_s_sl
tsl_dist = math.abs(close - trl_lbl)
tsl_arrow = act_call ? " ↑ TSL " : " ↓ TSL "
tsl_status = act_call ? (close > trl_lbl ? " ↑ trailing" : " ✕ CROSSED") : (close < trl_lbl ? " ↓ trailing" : " ✕ CROSSED")
tsl_clr = (act_call and close <= trl_lbl) or (act_put and close >= trl_lbl) ? color.new(#FF0000, 0) : color.new(#FFB300, 0)
lb_tsl := make_pill(rx, trl_lbl,
tsl_arrow + f_price(trl_lbl) + " " + f_pts(tsl_dist) + tsl_status,
tsl_clr, C_DARK)
// ╔══════════════════════════════════════════════════════════════════╗
// ║ ENTRY / WARMUP / STRUCTURE LABELS ║
// ╚══════════════════════════════════════════════════════════════════╝
if call_sig
label.new(bar_index, low,
" ▲ CALL " + str.tostring(math.round(prob_bull,1)) + "% " + str.tostring(int(bull_heat)) + "/10 ",
style=label.style_label_up, color=color.new(#00C853, 0),
textcolor=C_W, yloc=yloc.belowbar, size=size.normal)
if put_sig
label.new(bar_index, high,
" ▼ PUT " + str.tostring(math.round(prob_bear,1)) + "% " + str.tostring(int(bear_heat)) + "/10 ",
style=label.style_label_down, color=color.new(#FF2D2D, 0),
textcolor=C_W, yloc=yloc.abovebar, size=size.normal)
if warmup_b and not call_sig
label.new(bar_index, low, " ⚡ " + str.tostring(math.round(prob_bull,1)) + "% ",
style=label.style_label_up, color=color.new(#FF8F00, 20),
textcolor=C_W, yloc=yloc.belowbar, size=size.small)
if warmup_s and not put_sig
label.new(bar_index, high, " ⚡ " + str.tostring(math.round(prob_bear,1)) + "% ",
style=label.style_label_down, color=color.new(#FF8F00, 20),
textcolor=C_W, yloc=yloc.abovebar, size=size.small)
if in_decay
label.new(bar_index, high, " ⏱ DECAY ",
style=label.style_label_down, color=color.new(#FF6F00, 25),
textcolor=C_W, yloc=yloc.abovebar, size=size.tiny)
// ╔══════════════════════════════════════════════════════════════════╗
// ║ FULL HUD DASHBOARD ║
// ╚══════════════════════════════════════════════════════════════════╝
var table hud = table.new(position.bottom_right, 2, 30,
bgcolor=color.new(#060A12, 8), border_width=1,
border_color=color.new(#1C2B3A, 30),
frame_width=2, frame_color=color.new(#00BCD4, 50))
H_HDR = color.new(#0D1F2D, 0)
H_ROW = color.new(#0A1520, 15)
H_DIV = color.new(#060D18, 0)
H_BULL = color.new(#003D1F, 15)
H_BEAR = color.new(#3D0000, 15)
H_WARN = color.new(#3D2600, 15)
H_NEUT = color.new(#111820, 35)
TS = color.new(#8EABC0, 0)
if barstate.islast
// Header
rg_str = regime == REGIME_STRONG ? "STRONG" : regime == REGIME_WEAK ? "WEAK" : regime == REGIME_RANGE ? "RANGE" : "CHOP"
rg_clr = regime == REGIME_STRONG ? color.new(#00E676,0) : regime == REGIME_WEAK ? color.new(#76FF03,0) : regime == REGIME_RANGE ? color.new(#FFB300,0) : color.new(#FF5252,0)
table.cell(hud, 0, 0, " NIFTY AI v7 [1min]", text_color=color.new(#00BCD4,0), bgcolor=H_HDR, text_size=size.small)
table.cell(hud, 1, 0, in_sess ? "● LIVE" : in_decay ? "⏱ DECAY" : "○ OFF",
text_color=in_sess ? color.new(#00E676,0) : in_decay ? color.new(#FF6F00,0) : color.new(#FF5252,0),
bgcolor=H_HDR, text_size=size.small)
// Regime row
table.cell(hud, 0, 1, "Regime", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 1, rg_str, text_color=rg_clr, text_size=size.small, bgcolor=H_ROW)
// Probabilities
table.cell(hud, 0, 2, "AI CALL %", text_color=TS, text_size=size.small, bgcolor=H_ROW)
table.cell(hud, 1, 2, str.tostring(math.round(prob_bull,1)) + "%",
text_color=prob_bull >= min_prob ? color.new(#00E676,0) : prob_bull >= warmup_thr ? color.new(#FFB300,0) : color.new(#546E7A,0),
bgcolor=prob_bull >= min_prob ? H_BULL : prob_bull >= warmup_thr ? H_WARN : H_NEUT,
text_size=size.normal)
table.cell(hud, 0, 3, "AI PUT %", text_color=TS, text_size=size.small, bgcolor=H_ROW)
table.cell(hud, 1, 3, str.tostring(math.round(prob_bear,1)) + "%",
text_color=prob_bear >= min_prob ? color.new(#FF5252,0) : prob_bear >= warmup_thr ? color.new(#FFB300,0) : color.new(#546E7A,0),
bgcolor=prob_bear >= min_prob ? H_BEAR : prob_bear >= warmup_thr ? H_WARN : H_NEUT,
text_size=size.normal)
// Heat meter
act_heat = prob_bull > prob_bear ? int(bull_heat) : int(bear_heat)
table.cell(hud, 0, 4, "Signal Heat", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 4, heat_blk(act_heat) + " " + str.tostring(act_heat) + "/10",
text_color=heat_clr(act_heat), text_size=size.tiny, bgcolor=H_ROW)
// Divider: Score Breakdown
table.cell(hud, 0, 5, " MODULE SCORES", text_color=color.new(#2A4A62,0), bgcolor=H_DIV, text_size=size.tiny)
table.cell(hud, 1, 5, "", bgcolor=H_DIV)
table.cell(hud, 0, 6, "Trend", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 6, str.tostring(math.round(tr_b,0)) + " / 25", text_color=score_col(tr_b,25), text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 0, 7, "Momentum", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 7, str.tostring(math.round(mo_b,0)) + " / 25", text_color=score_col(mo_b,25), text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 0, 8, "Vol Delta", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 8, str.tostring(math.round(vl_b,0)) + " / 20", text_color=score_col(vl_b,20), text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 0, 9, "VWAP / BB", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 9, str.tostring(math.round(vw_b,0)) + " / 20", text_color=score_col(vw_b,20), text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 0, 10, "Price Action",text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 10, str.tostring(math.round(pa_b,0)) + " / 10", text_color=score_col(pa_b,10), text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 0, 11, "SMC", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 11, str.tostring(math.round(smc_b,0)) + " / 20", text_color=score_col(smc_b,20), text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 0, 12, "ML / MTF", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 12, str.tostring(math.round(ml_b,0)) + " / 20", text_color=score_col(ml_b,20), text_size=size.tiny, bgcolor=H_ROW)
// Divider: Smart Money
table.cell(hud, 0, 13, " SMART MONEY", text_color=color.new(#2A4A62,0), bgcolor=H_DIV, text_size=size.tiny)
table.cell(hud, 1, 13, "", bgcolor=H_DIV)
table.cell(hud, 0, 14, "Structure", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 14,
bos_bull ? "BOS ▲" : bos_bear ? "BOS ▼" : choch_bull ? "CHoCH ▲" : choch_bear ? "CHoCH ▼" : smc_bull_bias ? "Bias ▲" : smc_bear_bias ? "Bias ▼" : "—",
text_color=smc_bull_bias ? color.new(#00E676,0) : smc_bear_bias ? color.new(#FF5252,0) : color.new(#546E7A,0),
text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 0, 15, "Order Block", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 15,
in_bull_ob ? "IN BULL OB" : in_bear_ob ? "IN BEAR OB" : "—",
text_color=in_bull_ob ? color.new(#00E676,0) : in_bear_ob ? color.new(#FF5252,0) : color.new(#546E7A,0),
text_size=size.tiny, bgcolor=H_ROW)
// Divider: Confluence
table.cell(hud, 0, 16, " MTF CONFLUENCE", text_color=color.new(#2A4A62,0), bgcolor=H_DIV, text_size=size.tiny)
table.cell(hud, 1, 16, "", bgcolor=H_DIV)
table.cell(hud, 0, 17, "5min Bias", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 17, mtf5_bull ? "BULL ▲" : mtf5_bear ? "BEAR ▼" : "NEUTRAL",
text_color=mtf5_bull ? color.new(#00E676,0) : mtf5_bear ? color.new(#FF5252,0) : color.new(#FFB300,0),
text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 0, 18, "15min Bias", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 18, mtf15_bull ? "BULL ▲" : mtf15_bear ? "BEAR ▼" : "NEUTRAL",
text_color=mtf15_bull ? color.new(#00E676,0) : mtf15_bear ? color.new(#FF5252,0) : color.new(#FFB300,0),
text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 0, 19, "Stack", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
stack_bull_str = mtf_stack_bull == 2 ? "2/2 ●●" : mtf_stack_bull == 1 ? "1/2 ●○" : "0/2 ○○"
stack_bear_str = mtf_stack_bear == 2 ? "2/2 ●●" : mtf_stack_bear == 1 ? "1/2 ●○" : "0/2 ○○"
table.cell(hud, 1, 19,
prob_bull > prob_bear ? stack_bull_str : stack_bear_str,
text_color=color.new(#00BCD4,0), text_size=size.tiny, bgcolor=H_ROW)
// Divider: Volume & ML
table.cell(hud, 0, 20, " VOLUME & ML", text_color=color.new(#2A4A62,0), bgcolor=H_DIV, text_size=size.tiny)
table.cell(hud, 1, 20, "", bgcolor=H_DIV)
table.cell(hud, 0, 21, "Delta", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 21, delta_bull ? "BUY PRES" : delta_bear ? "SELL PRES" : "NEUTRAL",
text_color=delta_bull ? color.new(#00E676,0) : delta_bear ? color.new(#FF5252,0) : color.new(#546E7A,0),
text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 0, 22, "ML Bull%", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 22, str.tostring(math.round(ml_bull_rate,0)) + "% (" + str.tostring(pat_total) + " bars)",
text_color=ml_bull_rate >= 60 ? color.new(#00E676,0) : ml_bull_rate >= 50 ? color.new(#FFB300,0) : color.new(#FF5252,0),
text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 0, 23, "IV Regime", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 23, iv_regime,
text_color=iv_regime == "LOW" ? color.new(#00E676,0) : iv_regime == "HIGH" ? color.new(#FF5252,0) : color.new(#FFB300,0),
text_size=size.tiny, bgcolor=H_ROW)
// Divider: Filters
table.cell(hud, 0, 24, " FILTERS", text_color=color.new(#2A4A62,0), bgcolor=H_DIV, text_size=size.tiny)
table.cell(hud, 1, 24, "", bgcolor=H_DIV)
table.cell(hud, 0, 25, "Candle Pat", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 25, bull_pat ? "BULL OK" : bear_pat ? "BEAR OK" : "—",
text_color=bull_pat or bear_pat ? color.new(#00E676,0) : color.new(#546E7A,0),
text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 0, 26, "2-Bar Consec",text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 26, consec_b ? "BULL OK" : consec_s ? "BEAR OK" : "—",
text_color=consec_b or consec_s ? color.new(#00E676,0) : color.new(#546E7A,0),
text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 0, 27, "Delta Div", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 27, delta_div_bull ? "BULL DIV" : delta_div_bear ? "BEAR DIV" : "none",
text_color=delta_div_bull ? color.new(#00E676,0) : delta_div_bear ? color.new(#FF5252,0) : color.new(#546E7A,0),
text_size=size.tiny, bgcolor=H_ROW)
// Divider: Trade
// Trade state banner
trade_state_str = act_call ? "▲ CALL ACTIVE" : act_put ? "▼ PUT ACTIVE" : sl_just_hit ? "✕ STOPPED" : trade_done ? "✓ COMPLETE" : "○ IDLE"
trade_state_clr = act_call ? color.new(#00E676,0) : act_put ? color.new(#FF5252,0) : sl_just_hit ? color.new(#FF0000,0) : trade_done ? color.new(#00BCD4,0) : color.new(#546E7A,0)
trade_state_bg = act_call ? H_BULL : act_put ? H_BEAR : H_DIV
table.cell(hud, 0, 28, " TRADE", text_color=color.new(#2A4A62,0), bgcolor=H_DIV, text_size=size.tiny)
table.cell(hud, 1, 28, trade_state_str, text_color=trade_state_clr, bgcolor=trade_state_bg, text_size=size.tiny)
trl_disp = act_call ? trl_b_sl : act_put ? trl_s_sl : na
// Live target progress rows
table.cell(hud, 0, 29, " LIVE TRADE", text_color=color.new(#2A4A62,0), bgcolor=H_DIV, text_size=size.tiny)
table.cell(hud, 1, 29, "", bgcolor=H_DIV)
// We need extra rows — extend table dynamically via cell updates
// T1/T2/T3 hit status
t1_done_d = not na(sv_sl) and (sv_call ? close >= sv_t1 : close <= sv_t1)
t2_done_d = not na(sv_sl) and (sv_call ? close >= sv_t2 : close <= sv_t2)
t3_done_d = not na(sv_sl) and (sv_call ? close >= sv_t3 : close <= sv_t3)
sl_hit_d = not na(sv_sl) and (sv_call ? close <= sv_sl : close >= sv_sl)
tgt_str = (t3_done_d ? "T3●" : "T3○") + " " + (t2_done_d ? "T2●" : "T2○") + " " + (t1_done_d ? "T1●" : "T1○")
tgt_clr = t3_done_d ? color.new(#00BCD4,0) : t2_done_d ? color.new(#00C853,0) : t1_done_d ? color.new(#00E676,0) : color.new(#546E7A,0)
table.cell(hud, 0, 28, "Targets", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 28, tgt_str, text_color=tgt_clr, text_size=size.tiny,
bgcolor=t3_done_d ? color.new(#003040,20) : t1_done_d ? H_BULL : sl_hit_d ? H_BEAR : H_ROW)
table.cell(hud, 0, 29, "TSL / BE", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 29,
be_on and not na(entry_px) ? "═ BE: " + f_price(entry_px) : t1_hit and not na(trl_disp) ? "TSL: " + f_price(trl_disp) : "— await T1",
text_color=be_on ? color.new(#00E5FF,0) : color.new(#FFB300,0),
text_size=size.tiny, bgcolor=H_ROW)
// SL intelligence row — show which layer set the SL and risk in points
sl_source = not na(ob_sl_bull) and call_sl == math.max(math.min(ob_sl_bull, atr_floor_bull), atr_ceil_bull) ? "OB floor" : not na(vwap_sl_bull) and vwap_v < close and vwap_v > struct_low ? "VWAP" : not na(wick_sl_bull) and wick_ratio_low > 0.30 ? "Wick" : "Structure"
sl_source_bear = not na(ob_sl_bear) and put_sl == math.min(math.max(ob_sl_bear, atr_floor_bear), atr_ceil_bear) ? "OB ceil" : not na(vwap_sl_bear) and vwap_v > close and vwap_v < struct_high ? "VWAP" : not na(wick_sl_bear) and wick_ratio_high > 0.30 ? "Wick" : "Structure"
risk_pts_call = math.round(close - call_sl, 0)
risk_pts_put = math.round(put_sl - close, 0)
table.cell(hud, 0, 28, "SL Source", text_color=TS, text_size=size.tiny, bgcolor=H_ROW)
table.cell(hud, 1, 28,
act_call ? sl_source + " (" + str.tostring(risk_pts_call) + "p)" : act_put ? sl_source_bear + " (" + str.tostring(risk_pts_put) + "p)" : "—",
text_color=color.new(#00BCD4,0), text_size=size.tiny, bgcolor=H_ROW)
// ╔══════════════════════════════════════════════════════════════════╗
// ║ CHART PLOTS & BACKGROUNDS ║
// ╚══════════════════════════════════════════════════════════════════╝
plot(ema200, "EMA 200", color=color.new(#ECEFF1, 25), linewidth=2)
plot(ema50, "EMA 50", color=color.new(#CE93D8, 30), linewidth=1)
plot(ema21, "EMA 21", color=color.new(#42A5F5, 15))
plot(ema9, "EMA 9", color=color.new(#FFA726, 10))
plot(vwap_v, "VWAP", color=color.new(#FFEE58, 15), linewidth=2)
// Regime backgrounds — global scope (bgcolor cannot be in local scope in Pine v6)
bgcolor(show_regime and regime == REGIME_STRONG and st_d < 0 ? color.new(#00E676, 95) : na)
bgcolor(show_regime and regime == REGIME_STRONG and st_d > 0 ? color.new(#FF2D2D, 95) : na)
bgcolor(show_regime and regime == REGIME_WEAK and st_d < 0 ? color.new(#00E676, 97) : na)
bgcolor(show_regime and regime == REGIME_WEAK and st_d > 0 ? color.new(#FF2D2D, 97) : na)
bgcolor(show_regime and regime == REGIME_RANGE ? color.new(#FFB300, 98) : na)
bgcolor(show_regime and regime == REGIME_CHOP ? color.new(#FF5252, 98) : na)
bgcolor(in_sess ? color.new(#00BCD4, 98) : na)
bgcolor(in_decay ? color.new(#FF6F00, 97) : na)
bgcolor(warmup_b and not call_sig ? color.new(#FF8F00, 97) : na)
bgcolor(warmup_s and not put_sig ? color.new(#FF8F00, 97) : na)
// Squeeze dots
plotshape(bb_squeeze, "Squeeze", shape.circle, location.bottom, color=color.new(#FF6D00, 40), size=size.tiny)
// Volume absorption markers
plotshape(absorb_bull, "Absorb Bull", shape.diamond, location.belowbar, color=color.new(#00E676, 30), size=size.tiny)
plotshape(absorb_bear, "Absorb Bear", shape.diamond, location.abovebar, color=color.new(#FF5252, 30), size=size.tiny)
0 Comments