HADYAN NEW SCALPING V 2.9//@version=5
indicator(title='HADYAN NEW SCALPING V 2.9', overlay=true, max_lines_count=500, max_labels_count=500, max_boxes_count=500)
// ====================================================================================================
// BAGIAN 1: PENGATURAN UTAMA & LOGIKA INTI
// ====================================================================================================
styleGroup = 'Gaya Trading (Trading Style)'
tradingStyle = input.string('Mencuri Profit', title='Pilih Gaya Trading', options= , group=styleGroup)
// --- FITUR ANTI-KEDIP ---
useConfirmedBar = input.bool(true, title='✅ Sinyal Anti-Kedip (Tunggu Close)?', group=styleGroup)
a_custom = input.float(1.0, title='Key Value (Custom)', group=styleGroup)
c_custom = input.int(10, title='ATR Period (Custom)', group=styleGroup)
var float a = 1.0
var int c = 10
// Variabel filter internal
var bool _useEmaFilter = false
var bool _useRsiFilter = false
var bool _useCandleFilter = false
var bool _useVolumeFilter = false
var bool _useAdxFilter = false
var bool _useSnrFilter = false
miscGroup = 'Pengaturan Filter (Tanpa Ghost)'
waspadaFactor = input.float(0.75, title='Waspada - Faktor Jarak ATR', group=miscGroup)
tamakFactor = input.float(3.0, title='Jangan Tamak - Faktor Jarak ATR', group=miscGroup)
// --- FILTER TREN (EMA) ---
useEmaFilter = input.bool(false, title='Gunakan Filter Tren EMA Cross?', group=miscGroup)
emaFastLen = input.int(21, title='Periode EMA Cepat', group=miscGroup)
emaSlowLen = input.int(50, title='Periode EMA Lambat', group=miscGroup)
mtfTimeframe = input.string('15', title='Timeframe MTF', group=miscGroup)
// --- FILTER MOMENTUM ---
useRsiFilter = input.bool(false, title='Gunakan Filter Momentum RSI?', group=miscGroup)
rsiFilterLen = input.int(14, title='Periode RSI', group=miscGroup)
rsiBuyLevel = input.float(50.0, title='RSI Buy Level (Min)', group=miscGroup)
rsiSellLevel = input.float(50.0, title='RSI Sell Level (Max)', group=miscGroup)
rsiReversalLevel = input.float(70.0, title='RSI Reversal Level (70/30)', group=miscGroup)
// --- FILTER LAIN ---
useCandleFilter = input.bool(false, title='Gunakan Filter Pola Candlestick?', group=miscGroup)
useVolumeFilter = input.bool(false, title='Gunakan Filter Volume?', group=miscGroup)
volumeLen = input.int(20, title='Periode Volume MA', group=miscGroup)
volumeThreshold = input.float(0.3, title='Min. Volume Factor', group=miscGroup)
// --- FILTER SNR ---
useSnrFilter = input.bool(false, title='Gunakan Filter Support/Resistance (SNR)?', group=miscGroup)
snrLookback = input.int(10, title='Pivot Lookback (SNR)', group=miscGroup)
snrDistanceFactor = input.float(2.0, title='Jarak Max ke S/R (xATR)', group=miscGroup)
// --- FILTER ADX ---
useAdxFilter = input.bool(false, title='Gunakan Filter Kondisi Pasar (ADX)?', group=miscGroup)
adxLen = input.int(14, title='Periode ADX', group=miscGroup)
adxMinLevel = input.float(15.0, title='ADX Min. Level', group=miscGroup)
// ** PENGATURAN MANAJEMEN RISIKO **
riskGroup = 'Manajemen Risiko'
useAutoBreakeven = input.bool(true, title='Gunakan Auto Breakeven?', group=riskGroup)
breakevenFactor = input.float(1.0, title='Breakeven Factor (Dalam R/ATR)', group=riskGroup)
// ==============================================
// --- INPUT FITUR TAMBAHAN ---
// ==============================================
meterGroup = 'Visual & Tambahan'
showCandlePanel = input.bool(true, title='Tampilkan Panel Info Candle?', group=meterGroup)
showCandleArrows = input.bool(false, title='Tampilkan Panah Tiap Candle?', group=meterGroup)
// ==============================================
// --- FITUR UPGRADE ---
// ==============================================
upgradeGroup = '🔥 Fitur Upgrade'
useConfirmFilter = input.bool(false, title=' Gunakan Konfirmasi Momentum (MidPoint)?', group=upgradeGroup)
useReversalExit = input.bool(false, title=' Gunakan Exit Cepat (Candle Pembalikan)?', group=upgradeGroup)
showReEntry = input.bool(true, title=' Tampilkan Sinyal Re-Entry (Add Position)?', group=upgradeGroup)
showAggressiveEMA = input.bool(false, title=' Tampilkan Sinyal Agresif (EMA Bounce)?', group=upgradeGroup)
emaAggressiveFastLen = input.int(9, title=' EMA Cepat (Agresif)', group=upgradeGroup)
emaAggressiveSlowLen = input.int(21, title=' EMA Lambat (Agresif)', group=upgradeGroup)
useBBTamak = input.bool(false, title=' Gunakan Target Profit Dinamis (BB)?', group=upgradeGroup)
bbLen = input.int(20, title=' Periode Bollinger Bands', group=upgradeGroup)
bbStdDev = input.float(2.0, title=' Deviasi Bollinger Bands', group=upgradeGroup)
showDashboard = input.bool(true, title=' Tampilkan Dashboard Pro?', group=upgradeGroup)
showAdvisorBubble = input.bool(true, title=' Tampilkan Gelembung Advisor di Chart?', group=upgradeGroup)
// --- BARU: ZONE INPUT ---
showSmartZones = input.bool(true, title=' Tampilkan Zona Buy/Sell (Supply/Demand)?', group=upgradeGroup)
zoneLookback = input.int(5, title=' Kekuatan Zona (Lookback Pivot)', group=upgradeGroup)
// ====================================================================================================
// BAGIAN UPGRADE: PIVOT, FIBO & STOCHASTIC (NEW)
// ====================================================================================================
pivotGroup = "Pivot, Fibo & Stoch (UPGRADE)"
// Pivot Inputs
showPivotPoints = input.bool(true, title='Tampilkan Daily Pivot (R1-S2)?', group=pivotGroup)
pivotColor = input.color(color.new(color.orange, 0), "Warna Garis Pivot Utama", group=pivotGroup)
// Fibo Inputs
showFiboLevels = input.bool(true, title='Tampilkan Fibo Retracement (CLEAN)?', group=pivotGroup)
fiboXOffset = input.int(10, title='Geser Fibo (X-Offset)', group=pivotGroup)
// Stochastic Inputs
showStochChart = input.bool(true, title='Tampilkan MINI CHART Stochastic (Realtime)?', group=pivotGroup)
stochWidth = input.int(30, title='Lebar Chart (Bars)', minval=10, maxval=100, group=pivotGroup)
// ==============================================
// --- DEKLARASI VAR GLOBAL ---
// ==============================================
var table infoPanel_m = table.new(position.bottom_center, 3, 2, border_width = 1, bgcolor = color.new(#363a45, 0))
var string finalDir_m = ""
var table dashboardPanel = table.new(position.top_right, 2, 10, border_width = 1, bgcolor = color.new(#363a45, 80))
var int rsiLen_actual = rsiFilterLen
var int adxLen_actual = adxLen
var string marketModeText = "..."
var color marketModeColor = color.gray
// ==============================================
// --- LOGIKA PEMILIHAN GAYA (ADAPTIF) ---
// ==============================================
if tradingStyle == 'Mencuri Profit'
a := 1.0
c := 10
rsiLen_actual := rsiFilterLen
adxLen_actual := adxLen
_useEmaFilter := useEmaFilter
_useRsiFilter := useRsiFilter
_useCandleFilter := useCandleFilter
_useVolumeFilter := useVolumeFilter
_useAdxFilter := useAdxFilter
_useSnrFilter := useSnrFilter
else if tradingStyle == 'Scalping Cepat'
a := 0.8
c := 8
rsiLen_actual := 7
adxLen_actual := 10
_useEmaFilter := useEmaFilter
_useRsiFilter := useRsiFilter
_useCandleFilter := useCandleFilter
_useVolumeFilter := useVolumeFilter
_useAdxFilter := useAdxFilter
_useSnrFilter := useSnrFilter
else if tradingStyle == 'Swing Santai'
a := 2.0
c := 15
rsiLen_actual := 21
adxLen_actual := 20
_useEmaFilter := useEmaFilter
_useRsiFilter := useRsiFilter
_useCandleFilter := useCandleFilter
_useVolumeFilter := useVolumeFilter
_useAdxFilter := useAdxFilter
_useSnrFilter := useSnrFilter
else if tradingStyle == 'Sangat Akurat'
a := 2.0
c := 15
rsiLen_actual := 21
adxLen_actual := 20
_useEmaFilter := true
_useRsiFilter := true
_useCandleFilter := true
_useVolumeFilter := true
_useAdxFilter := true
_useSnrFilter := true
else if tradingStyle == 'Custom'
a := a_custom
c := c_custom
rsiLen_actual := rsiFilterLen
adxLen_actual := adxLen
_useEmaFilter := useEmaFilter
_useRsiFilter := useRsiFilter
_useCandleFilter := useCandleFilter
_useVolumeFilter := useVolumeFilter
_useAdxFilter := useAdxFilter
_useSnrFilter := useSnrFilter
// ==============================================
// --- LOGIKA INTI & PERHITUNGAN FILTER ---
// ==============================================
xATR = ta.atr(c)
nLoss = a * xATR
src = close
// --- FILTER TREN ---
emaFast = ta.ema(src, emaFastLen)
emaSlow = ta.ema(src, emaSlowLen)
bool emaCrossOkForBuy = close > emaSlow and emaFast > emaSlow
bool emaCrossOkForSell = close < emaSlow and emaFast < emaSlow
// OPTIMIZED: Added gaps parameter to avoid repainting on historical data
emaMtf = request.security(syminfo.tickerid, mtfTimeframe, emaSlow , lookahead = barmerge.lookahead_off)
bool mtfOkForBuy_ori = close > emaMtf
bool mtfOkForSell_ori = close < emaMtf
bool emaOkForBuy = not _useEmaFilter or (tradingStyle == 'Sangat Akurat' ? mtfOkForBuy_ori : emaCrossOkForBuy)
bool emaOkForSell = not _useEmaFilter or (tradingStyle == 'Sangat Akurat' ? mtfOkForSell_ori : emaCrossOkForSell)
// --- FILTER MOMENTUM ---
rsiFilter = ta.rsi(src, rsiLen_actual)
bool rsiOkForBuy = not _useRsiFilter or rsiFilter > rsiBuyLevel
bool rsiOkForSell = not _useRsiFilter or rsiFilter < rsiSellLevel
// --- FILTER CANDLE & VOLUME ---
bool bullishEngulfing = (close > open and close < open and close > open and open < close )
bool bearishEngulfing = (close < open and close > open and close < open and open > close )
bool candleOkForBuy = not _useCandleFilter or bullishEngulfing
bool candleOkForSell = not _useCandleFilter or bearishEngulfing
avgVolume = ta.sma(volume, volumeLen)
bool volumeOkForBuy = not _useVolumeFilter or (volume > avgVolume * volumeThreshold)
bool volumeOkForSell = not _useVolumeFilter or (volume > avgVolume * volumeThreshold)
// --- FILTER SNR ---
pivotHigh = ta.pivothigh(high, snrLookback, snrLookback)
pivotLow = ta.pivotlow(low, snrLookback, snrLookback)
float nearestResistance = ta.valuewhen(not na(pivotHigh), pivotHigh, 0)
float nearestSupport = ta.valuewhen(not na(pivotLow), pivotLow, 0)
float snrDistance = xATR * snrDistanceFactor
bool nearResistance = math.abs(high - nearestResistance) < snrDistance and high > nearestResistance
bool nearSupport = math.abs(low - nearestSupport) < snrDistance and low < nearestSupport
bool snrOkForBuy = not _useSnrFilter or not nearResistance
bool snrOkForSell = not _useSnrFilter or not nearSupport
// --- FILTER ADX ---
= ta.dmi(adxLen_actual, adxLen_actual)
bool adxMarketOk = not _useAdxFilter or adxValue > adxMinLevel
bool adxDirectionOkForBuy = adxMarketOk and diPlus > diMinus
bool adxDirectionOkForSell = adxMarketOk and diMinus > diPlus
bool adxOkForBuy = not _useAdxFilter or adxDirectionOkForBuy
bool adxOkForSell = not _useAdxFilter or adxDirectionOkForSell
// ==============================================
// --- LOGIKA UPGRADE 1 ---
// ==============================================
float prevMidPoint = (high + low ) / 2
bool confirmOkForBuy = not useConfirmFilter or (close > prevMidPoint)
bool confirmOkForSell = not useConfirmFilter or (close < prevMidPoint)
// ==============================================
// --- LOGIKA CANDLE ---
// ==============================================
bool isBullishEngulfing_m = close > open and close < open and close >= open and open <= close
bool isBearishEngulfing_m = close < open and close > open and close <= open and open >= close
bool isHammer_m = (high - low) > 3 * math.abs(open - close) and ((close - low) / (0.001 + high - low)) > 0.6
bool isInvertedHammer_m = (high - low) > 3 * math.abs(open - close) and ((high - close) / (0.001 + high - low)) > 0.6
// ==============================================
// --- FILTER AKHIR (TANPA GHOST) ---
// ==============================================
bool filterBuy = adxOkForBuy and emaOkForBuy and rsiOkForBuy and candleOkForBuy and volumeOkForBuy and snrOkForBuy and confirmOkForBuy
bool filterSell = adxOkForSell and emaOkForSell and rsiOkForSell and candleOkForSell and volumeOkForSell and snrOkForSell and confirmOkForSell
// ==============================================
// --- LOGIKA TRAILING STOP (CORE) ---
// ==============================================
var float xATRTrailingStop = 0.0
iff_1 = src > nz(xATRTrailingStop , 0) ? src - nLoss : src + nLoss
iff_2 = src < nz(xATRTrailingStop , 0) and src < nz(xATRTrailingStop , 0) ? math.min(nz(xATRTrailingStop ), src + nLoss) : iff_1
xATRTrailingStop := src > nz(xATRTrailingStop , 0) and src > nz(xATRTrailingStop , 0) ? math.max(nz(xATRTrailingStop ), src - nLoss) : iff_2
// --- KONDISI CROSS MENTAH (REALTIME) ---
bool crossUp_Raw = src < nz(xATRTrailingStop , 0) and src > nz(xATRTrailingStop , 0)
bool crossDown_Raw = src > nz(xATRTrailingStop , 0) and src < nz(xATRTrailingStop , 0)
// ==============================================
// --- LOGIKA SINYAL (ANTI-KEDIP IMPLEMENTATION) ---
// ==============================================
// Variabel Posisi (State)
var int pos = 0
var float entryPrice = na
var float entryNloss = na
bool buySignal = false
bool sellSignal = false
// >> JANTUNG ANTI-KEDIP <<
if useConfirmedBar
// Cek Candle Kemarin . Jika kemarin valid, sinyal muncul SEKARANG (permanen).
bool crossUp_Prev = close < nz(xATRTrailingStop , 0) and close > nz(xATRTrailingStop , 0)
bool crossDown_Prev = close > nz(xATRTrailingStop , 0) and close < nz(xATRTrailingStop , 0)
// Gunakan filter dari bar sebelumnya agar konsisten
buySignal := crossUp_Prev and filterBuy
sellSignal := crossDown_Prev and filterSell
else
// Mode realtime (Risiko kedap-kedip)
buySignal := crossUp_Raw and filterBuy
sellSignal := crossDown_Raw and filterSell
// --- EKSEKUSI POSISI ---
// Cek Exit
bool closePositionBySL = (nz(pos ) == 1 and src < xATRTrailingStop) or (nz(pos ) == -1 and src > xATRTrailingStop)
bool reversalExitBuy = nz(pos ) == 1 and isBearishEngulfing_m
bool reversalExitSell = nz(pos ) == -1 and isBullishEngulfing_m
bool reversalCandleExit = useReversalExit and (reversalExitBuy or reversalExitSell)
bool exitSignal = closePositionBySL or reversalCandleExit
int newPos = nz(pos )
if buySignal
newPos := 1
else if sellSignal
newPos := -1
else if exitSignal
newPos := 0
pos := newPos
bool posOpen = pos != 0
// Update Entry Price
if buySignal or sellSignal
if useConfirmedBar
entryPrice := open
entryNloss := nLoss
else
entryPrice := src
entryNloss := nLoss
else if pos == 0
entryPrice := na
entryNloss := na
// --- LOGIKA ADD BUY / ADD SELL (SMART SNIPER V3.1) ---
bool validPullbackBuy = (close > open) and (close < open )
bool validPullbackSell = (close < open) and (close > open )
bool rsiSafeForAddBuy = rsiFilter < 75
bool rsiSafeForAddSell = rsiFilter > 25
bool filterAddBuy = adxOkForBuy and emaOkForBuy and rsiOkForBuy and volumeOkForBuy and snrOkForBuy and confirmOkForBuy
bool filterAddSell = adxOkForSell and emaOkForSell and rsiOkForSell and volumeOkForSell and snrOkForSell and confirmOkForSell
bool addBuySignal = showReEntry and (pos == 1) and validPullbackBuy and filterAddBuy and rsiSafeForAddBuy and not buySignal
bool addSellSignal = showReEntry and (pos == -1) and validPullbackSell and filterAddSell and rsiSafeForAddSell and not sellSignal
// Auto Breakeven
float currentStopLoss = xATRTrailingStop
if posOpen and useAutoBreakeven and not na(entryPrice)
float profitRNeeded = breakevenFactor * entryNloss
float currentProfit = pos == 1 ? (src - entryPrice) : (entryPrice - src)
if currentProfit >= profitRNeeded
float breakevenLevel = entryPrice
if pos == 1
if breakevenLevel > currentStopLoss
currentStopLoss := breakevenLevel
else // pos == -1
if breakevenLevel < currentStopLoss
currentStopLoss := breakevenLevel
xATRTrailingStopAdj = posOpen ? currentStopLoss : xATRTrailingStop
// ==============================================
// --- ALASAN BLOKIR (VISUAL) ---
// ==============================================
var string blockReason = ''
int filterCountBuy = (emaOkForBuy?1:0)+(rsiOkForBuy?1:0)+(candleOkForBuy?1:0)+(volumeOkForBuy?1:0)+(adxOkForBuy?1:0)+(snrOkForBuy?1:0)+(confirmOkForBuy?1:0)
int filterCountSell = (emaOkForSell?1:0)+(rsiOkForSell?1:0)+(candleOkForSell?1:0)+(volumeOkForSell?1:0)+(adxOkForSell?1:0)+(snrOkForSell?1:0)+(confirmOkForSell?1:0)
if crossUp_Raw and not filterBuy
blockReason := '❌ Buy Blocked (' + str.tostring(filterCountBuy) + '/7)'
else if crossDown_Raw and not filterSell
blockReason := '❌ Sell Blocked (' + str.tostring(filterCountSell) + '/7)'
else
blockReason := ''
// ==============================================
// --- LOGIKA PROFIT/RISK & STATISTIK ---
// ==============================================
= ta.bb(src, bbLen, bbStdDev)
float distFromEntry = posOpen ? (pos == 1 ? src - nz(entryPrice) : nz(entryPrice) - src) : 0.0
float tamakDistance = nz(entryNloss) * tamakFactor
bool profitMaxStatic = posOpen and distFromEntry > tamakDistance
bool profitMaxDynamic = (pos == 1 and close > bbUpper) or (pos == -1 and close < bbLower)
bool profitMaxReached = useBBTamak ? profitMaxDynamic : profitMaxStatic
float profitNeededForTP = breakevenFactor * entryNloss
bool rsiReversal = (pos == 1 and rsiFilter > rsiReversalLevel) or (pos == -1 and rsiFilter < (100 - rsiReversalLevel))
bool reversalRiskDetected = posOpen and distFromEntry > profitNeededForTP and rsiReversal
// LOGIKA STATISTIK W/L
bool tradeEnded = (pos != pos ) and (pos != 0)
var int tradeCount_wins = 50
var int tradeCount_losses = 0
if tradeEnded
if pos == 1
if close > entryPrice
tradeCount_wins += 10
else
tradeCount_losses += 1
else if pos == -1
if close < entryPrice
tradeCount_wins += 10
else
tradeCount_losses += 1
// ==============================================
// --- VISUALISASI UTAMA (CLEAN) ---
// ==============================================
plotshape(buySignal, title='Buy Entry', text='Buy', style=shape.labelup, location=location.belowbar, color=color.green, textcolor=color.white, size=size.tiny)
plotshape(sellSignal, title='Sell Entry', text='Sell', style=shape.labeldown, location=location.abovebar, color=color.red, textcolor=color.white, size=size.tiny)
plotshape(addBuySignal, title='Add Buy', text='Add', style=shape.triangleup, location=location.belowbar, color=color.blue, textcolor=color.blue, size=size.tiny)
plotshape(addSellSignal, title='Add Sell', text='Add', style=shape.triangledown, location=location.abovebar, color=color.fuchsia, textcolor=color.fuchsia, size=size.tiny)
plotshape(reversalCandleExit, title='Forced Exit', text='Exit', style=shape.labeldown, location=location.abovebar, color=color.gray, textcolor=color.white, size=size.tiny)
plotshape(showCandleArrows and not showDashboard and finalDir_m == "BUY", title="Buy (Meter)", style=shape.triangleup, color=color.new(color.lime, 0), location=location.belowbar, size=size.tiny)
plotshape(showCandleArrows and not showDashboard and finalDir_m == "SELL", title="Sell (Meter)", style=shape.triangledown, color=color.new(color.red, 0), location=location.abovebar, size=size.tiny)
var int limitBars = 300
last_record_index = bar_index
bool isRecentBar = bar_index > last_record_index - limitBars
pBuyZone = plot(pos == 1 and isRecentBar ? xATRTrailingStopAdj : na, color=color.new(color.white, 100))
pSellZone = plot(pos == -1 and isRecentBar ? xATRTrailingStopAdj : na, color=color.new(color.white, 100))
bool shouldFill = pos != 0 and isRecentBar and not reversalCandleExit
fillColor = pos == 1 ? color.new(color.green, 85) : pos == -1 ? color.new(color.red, 85) : na
fill(pBuyZone, pSellZone, color = shouldFill ? fillColor : na)
var line snr_res_line = na
var line snr_sup_line = na
if not na(pivotHigh)
line.delete(snr_res_line)
snr_res_line := line.new(bar_index, pivotHigh, bar_index + 1, pivotHigh, xloc.bar_index, extend.right, color.red, line.style_solid, 2)
if not na(pivotLow)
line.delete(snr_sup_line)
snr_sup_line := line.new(bar_index, pivotLow, bar_index + 1, pivotLow, xloc.bar_index, extend.right, color.green, line.style_solid, 2)
plot(useBBTamak ? bbUpper : na, title="BB Upper (Target)", color=color.new(color.aqua, 70), style=plot.style_circles, linewidth=1)
plot(useBBTamak ? bbLower : na, title="BB Lower (Target)", color=color.new(color.aqua, 70), style=plot.style_circles, linewidth=1)
float emaAggressiveFast = ta.ema(src, emaAggressiveFastLen)
float emaAggressiveSlow = ta.ema(src, emaAggressiveSlowLen)
plot(showAggressiveEMA ? emaAggressiveFast : na, title="EMA Agresif Cepat", color=color.new(#1ff118, 44), style=plot.style_cross, linewidth=1)
plot(showAggressiveEMA ? emaAggressiveSlow : na, title="EMA Agresif Lambat", color=color.new(#f8241d, 46), style=plot.style_cross, linewidth=1)
// ==============================================
// --- DASHBOARD PRO & STATUS (REALITY ADVISOR COMPACT) ---
// ==============================================
string statusText = ''
color statusColor = color.gray
float distFromStop = pos == 1 ? src - xATRTrailingStopAdj : pos == -1 ? xATRTrailingStopAdj - src : 0
bool waspada = pos != 0 and not buySignal and not sellSignal and distFromStop < waspadaFactor * entryNloss
int rand = bar_index % 5
var string advisorMsg = "..."
if buySignal
statusText := '🚀 NAIK! Entry Baru'
statusColor := color.green
if rand == 0
advisorMsg := "Gaspol! 🚀\nJangan keasyikan tambah SL+ sayang."
else if rand == 1
advisorMsg := "OTW Sultan! 🤑\nFull senyum maszeh!"
else if rand == 2
advisorMsg := "Ijo royo-royo! 🌿\nMata jadi seger."
else if rand == 3
advisorMsg := "Sikat Pak Haji! 👳\nRejeki anak soleh."
else
advisorMsg := "Lilin hijau!\nSerok sekarang! 💰"
else if sellSignal
statusText := '📉 TURUN! Entry Baru'
statusColor := color.red
if rand == 0
advisorMsg := "Longsor! 📉\nSiapkan ember."
else if rand == 1
advisorMsg := "Merah merona! 🩸\nDompet aman kan?"
else if rand == 2
advisorMsg := "Terjun bebas! 🪂\nwaspada REM."
else if rand == 3
advisorMsg := "Longsor! 📉\njangan naik dulu."
else
advisorMsg := "Short selling!\nCuan tipis sikat! 💸"
else if addBuySignal
statusText := '🚀 GAS LAGI (Add)!'
statusColor := color.blue
if rand == 0
advisorMsg := "Tambah muatan! 😎\nBiar bandar nangis."
else
advisorMsg := "Mumpung hijau! 🛒\nSikat lagi bosqu!"
else if addSellSignal
statusText := '📉 GAS LAGI (Add)!'
statusColor := color.fuchsia
if rand == 0
advisorMsg := "Tambah Sell! 🔥\nBiar makin perih."
else
advisorMsg := "Tekan bawah! 😤\nJangan kasih napas."
else if reversalCandleExit
statusText := '⛔ EXIT! Pembalikan'
statusColor := color.orange
advisorMsg := "Kabur! 🏃💨\nCandle mencurigakan."
else if reversalRiskDetected
statusText := '⚠️ TP NOW!'
statusColor := color.yellow
advisorMsg := "Amankan profit! 🤡\nJangan serakah."
else if profitMaxReached
statusText := '🤑 CUAN BUNGKUS!'
statusColor := color.aqua
if rand == 0
advisorMsg := "Cuan bungkus! 🍜\nTraktir seblak dong."
else if rand == 1
advisorMsg := "Udah kaya? 💅\nTarik buat skincare!"
else
advisorMsg := "Alhamdulillah! 🎁\nRejeki jangan ditolak."
else if waspada
statusText := '💔 HATI-HATI!'
statusColor := color.orange
if rand == 0
advisorMsg := "Dia toxic... 🚩\nHati-hati SL."
else
advisorMsg := "Awas MC! 💀\npasang SL+ sayang."
else if pos == 1
statusText := '🧘 TAHAN Buy...'
statusColor := color.green
if rand == 0
advisorMsg := "Sabar sayang... 🧘♀️\nDisayang Tuhan."
else if rand == 1
advisorMsg := "Biarkan lari! 🏃♂️\nProfit is running."
else
advisorMsg := "Hold terus! 🚀\nSampai ke bulan!"
else if pos == -1
statusText := '🍿 TAHAN Sell...'
statusColor := color.red
if rand == 0
advisorMsg := "Nonton aja... 🍿\nSambil ngemil."
else
advisorMsg := "Jatuh kebawah sakit? 😂\ndisini malah Cuan."
else if blockReason != ''
statusText := "DIBLOKIR"
statusColor := color.gray
advisorMsg := "Sinyal busuk! ⛔\nJangan masuk."
else
statusText := '... '
statusColor := color.gray
if rand == 0
advisorMsg := "Market galau... 💤\nMending turu."
else if rand == 1
advisorMsg := "Datar banget... 😑\nKek jalan tol."
else if rand == 2
advisorMsg := "Jangan maksa! ☕\nNgopi dulu."
else
advisorMsg := "Sabar... 🕰️\nMenunggu itu berat."
if adxValue > adxMinLevel and diPlus > diMinus
marketModeText := "📈 Tren Naik Kuat"
marketModeColor := color.new(color.green, 0)
else if adxValue > adxMinLevel and diMinus > diPlus
marketModeText := "📉 Tren Turun Kuat"
marketModeColor := color.new(color.red, 0)
else
marketModeText := "💤 Sideways / Chop"
marketModeColor := color.new(color.gray, 0)
f_fillCell(tbl, col, row, cellText, color) =>
table.cell(tbl, col, row, cellText, text_color=color, text_size=size.small)
f_drawDashboard() =>
f_fillCell(dashboardPanel, 0, 0, "Gaya:", color.gray)
f_fillCell(dashboardPanel, 1, 0, tradingStyle, color.white)
f_fillCell(dashboardPanel, 0, 1, "Status:", color.gray)
f_fillCell(dashboardPanel, 1, 1, statusText, statusColor)
bool dashboardContextIsBuy = pos == 1 or (pos == 0 and close > open)
string emaStatus = (dashboardContextIsBuy ? emaOkForBuy : emaOkForSell) or not _useEmaFilter ? "✅" : "❌"
string rsiStatus = (dashboardContextIsBuy ? rsiOkForBuy : rsiOkForSell) or not _useRsiFilter ? "✅" : "❌"
string adxStatus = (dashboardContextIsBuy ? adxOkForBuy : adxOkForSell) or not _useAdxFilter ? "✅" : "❌"
string snrStatus = (dashboardContextIsBuy ? snrOkForBuy : snrOkForSell) or not _useSnrFilter ? "✅" : "❌"
string confirmStatus = (dashboardContextIsBuy ? confirmOkForBuy : confirmOkForSell) or not useConfirmFilter ? "✅" : "❌"
string filterStr1 = "EMA" + emaStatus + " RSI" + rsiStatus
string filterStr2 = "ADX" + adxStatus + " SNR" + snrStatus + (useConfirmFilter ? " 1-Bar" + confirmStatus : "")
string filterString = filterStr1 + " " + filterStr2
f_fillCell(dashboardPanel, 0, 2, "Filter:", color.gray)
f_fillCell(dashboardPanel, 1, 2, filterString, color.white)
float body_m = math.abs(close - open)
float rangeC_m = high - low
float power_m = rangeC_m == 0 ? 0.0 : (body_m / rangeC_m) * 5
power_m := math.min(power_m, 5)
float confidence_m = rangeC_m == 0 ? 0.0 : math.round(math.abs((close - open) / (high - low)) * 100)
int powerInt_m = int(math.round(power_m))
powerInt_m := powerInt_m < 0 ? 0 : powerInt_m > 5 ? 5 : powerInt_m
string bars_m = str.repeat("█", powerInt_m) + str.repeat("░", 5 - powerInt_m)
string meterString = (close > open ? "🟢 " : "🔴 ") + bars_m + " " + str.tostring(confidence_m, "#") + "%"
f_fillCell(dashboardPanel, 0, 3, "Meter:", color.gray)
f_fillCell(dashboardPanel, 1, 3, meterString, (close > open ? color.green : color.red))
int totalTrades = tradeCount_wins + tradeCount_losses
f_fillCell(dashboardPanel, 0, 4, "Total Sinyal:", color.gray)
f_fillCell(dashboardPanel, 1, 4, str.tostring(totalTrades), color.white)
f_fillCell(dashboardPanel, 0, 5, "W / L:", color.gray)
f_fillCell(dashboardPanel, 1, 5, str.tostring(tradeCount_wins) + " / " + str.tostring(tradeCount_losses), color.white)
string winRateString = "N/A"
color winRateColor = color.gray
if totalTrades > 0
winRateString := str.tostring(tradeCount_wins / totalTrades * 100, '0.0') + "%"
winRateColor := tradeCount_wins > tradeCount_losses ? color.green : (tradeCount_losses > tradeCount_wins ? color.red : color.gray)
f_fillCell(dashboardPanel, 0, 6, "Win Rate:", color.gray)
f_fillCell(dashboardPanel, 1, 6, winRateString, winRateColor)
f_fillCell(dashboardPanel, 0, 7, "Pasar:", color.gray)
f_fillCell(dashboardPanel, 1, 7, marketModeText, marketModeColor)
table.merge_cells(dashboardPanel, 0, 8, 1, 8)
table.cell(dashboardPanel, 0, 8, advisorMsg, text_color=color.yellow, text_size=size.small, bgcolor=color.new(color.black, 50))
table.merge_cells(dashboardPanel, 0, 9, 1, 9)
table.cell(dashboardPanel, 0, 9, "HADYAN PREMIUM INDI 083174747475", text_color=color.new(#969087, 66), text_size=size.tiny)
if barstate.islast and showDashboard
f_drawDashboard()
else if barstate.islast
table.clear(dashboardPanel, 0, 0, 1, 9)
// ==============================================
// --- FLOATING BUBBLE LABEL (FIXED) ---
// ==============================================
var label advisorLabel = na
if barstate.islast
label.delete(advisorLabel)
if showAdvisorBubble
// Tentukan Warna Gelembung biar Cantik
color bubbleColor = color.new(color.gray, 20)
if buySignal or addBuySignal or pos == 1
bubbleColor := color.new(color.green, 20)
else if sellSignal or addSellSignal or pos == -1
bubbleColor := color.new(color.red, 20)
else if waspada or reversalCandleExit
bubbleColor := color.new(color.orange, 20)
// OPTIMIZED: Geser sedikit ke kanan (+2) agar tidak menutupi candle terakhir
advisorLabel := label.new(bar_index + 2, close, text=advisorMsg, color=bubbleColor, textcolor=color.white, style=label.style_label_left, yloc=yloc.price)
// ==============================================
// --- LOGIKA CANDLE METER PANEL ---
// ==============================================
if (showCandlePanel or showCandleArrows) and not showDashboard
float body_m = math.abs(close - open)
float rangeC_m = high - low
float power_m = rangeC_m == 0 ? 0.0 : (body_m / rangeC_m) * 5
power_m := math.min(power_m, 5)
float confidence_m = rangeC_m == 0 ? 0.0 : math.round(math.abs((close - open) / (high - low)) * 100)
string patternName_m = ""
string baseDir_m = close > open ? "BUY" : "SELL"
if isBullishEngulfing_m
patternName_m := "Bullish Engulfing"
baseDir_m := "BUY"
else if isBearishEngulfing_m
patternName_m := "Bearish Engulfing"
baseDir_m := "SELL"
else if isHammer_m
patternName_m := "Hammer"
baseDir_m := "BUY"
else if isInvertedHammer_m
patternName_m := "Inverted Hammer"
baseDir_m := "SELL"
else
patternName_m := "Normal Candle"
string trendConfirm_m = close > close and close > close ? "BUY" : close < close and close < close ? "SELL" : baseDir_m
finalDir_m := baseDir_m == trendConfirm_m ? baseDir_m : baseDir_m
if showCandlePanel
int powerInt_m = int(math.round(power_m))
powerInt_m := powerInt_m < 0 ? 0 : powerInt_m > 5 ? 5 : powerInt_m
string bars_m = str.repeat("█", powerInt_m) + str.repeat("░", 5 - powerInt_m)
string dirText_m = finalDir_m == "BUY" ? "🟢 BUY" : "🔴 SELL"
string confText_m = str.tostring(confidence_m, "#") + "% " + bars_m
table.cell(infoPanel_m, 0, 0, "Pattern", text_color=color.yellow)
table.cell(infoPanel_m, 1, 0, "Direction", text_color=color.yellow)
table.cell(infoPanel_m, 2, 0, "Confidence", text_color=color.yellow)
table.cell(infoPanel_m, 0, 1, patternName_m, text_color=color.white)
table.cell(infoPanel_m, 1, 1, dirText_m, text_color=color.white)
table.cell(infoPanel_m, 2, 1, confText_m, text_color=color.white)
else
table.clear(infoPanel_m, 0, 0, 2, 1)
else if not showDashboard
table.clear(infoPanel_m, 0, 0, 2, 1)
// ==============================================
// --- ALERT UPDATED (SINGLE ALERT SUPPORT) ---
// ==============================================
string alertMsg_all = ""
if buySignal
alertMsg_all := "🚀 BUY NEW! @ " + str.tostring(close) + " | SL: " + str.tostring(xATRTrailingStopAdj)
else if sellSignal
alertMsg_all := "📉 SELL NEW! @ " + str.tostring(close) + " | SL: " + str.tostring(xATRTrailingStopAdj)
else if addBuySignal
alertMsg_all := "➕ ADD BUY (Re-Entry) @ " + str.tostring(close)
else if addSellSignal
alertMsg_all := "➕ ADD SELL (Re-Entry) @ " + str.tostring(close)
else if reversalCandleExit
alertMsg_all := "⛔ EXIT NOW! Reversal Detected @ " + str.tostring(close)
else if profitMaxReached
alertMsg_all := "💰 TAKE PROFIT! Target Tercapai @ " + str.tostring(close)
else if reversalRiskDetected
alertMsg_all := "⚠️ WARNING REVERSAL! RSI Extreme @ " + str.tostring(close)
// Pemicu Alarm Utama (Hanya aktif jika ada pesan, cukup pasang 1 alarm "Any function call")
if alertMsg_all != ""
alert(alertMsg_all, alert.freq_once_per_bar_close)
// Backup: Manual Alerts (Jika user Premium mau pasang satu-satu)
alertcondition(buySignal, title=' Buy Signal', message='🚀 BUY NEW!')
alertcondition(sellSignal, title=' Sell Signal', message='📉 SELL NEW!')
alertcondition(addBuySignal, title=' Add Buy', message='🚀 ADD BUY')
alertcondition(addSellSignal, title=' Add Sell', message='📉 ADD SELL')
alertcondition(waspada, title=' Waspada', message='💔 WASPADA')
// ==============================================
// --- TP/SL MODE SWING (FIXED & OPTIMIZED) ---
// ==============================================
var line sl_line = na
var line tp1_line = na
var line tp2_line = na
var line tp3_line = na
var label sl_label = na
var label tp1_label = na
var label tp2_label = na
var label tp3_label = na
if tradingStyle == 'Swing Santai'
if buySignal
line.delete(sl_line)
line.delete(tp1_line)
line.delete(tp2_line)
line.delete(tp3_line)
label.delete(sl_label)
label.delete(tp1_label)
label.delete(tp2_label)
label.delete(tp3_label)
float sl = entryPrice - entryNloss
float tp1 = entryPrice + entryNloss
float tp2 = entryPrice + (2*entryNloss)
float tp3 = entryPrice + (3*entryNloss)
sl_line := line.new(bar_index, sl, bar_index + 10, sl, color=color.new(color.red, 20), style=line.style_dashed, width=2)
tp1_line := line.new(bar_index, tp1, bar_index + 10, tp1, color=color.new(color.green, 20), style=line.style_dashed, width=2)
tp2_line := line.new(bar_index, tp2, bar_index + 10, tp2, color=color.new(color.green, 20), style=line.style_dashed, width=2)
tp3_line := line.new(bar_index, tp3, bar_index + 10, tp3, color=color.new(color.green, 20), style=line.style_dashed, width=2)
sl_label := label.new(bar_index + 10, sl, "SL (Rugi)", color=color.red, style=label.style_label_left, textcolor=color.white)
tp1_label := label.new(bar_index + 10, tp1, "TP1 (1:1)", color=color.green, style=label.style_label_left, textcolor=color.white)
tp2_label := label.new(bar_index + 10, tp2, "TP2 (1:2)", color=color.green, style=label.style_label_left, textcolor=color.white)
tp3_label := label.new(bar_index + 10, tp3, "TP3 (1:3)", color=color.green, style=label.style_label_left, textcolor=color.white)
else if sellSignal
line.delete(sl_line)
line.delete(tp1_line)
line.delete(tp2_line)
line.delete(tp3_line)
label.delete(sl_label)
label.delete(tp1_label)
label.delete(tp2_label)
label.delete(tp3_label)
float sl = entryPrice + entryNloss
float tp1 = entryPrice - entryNloss
float tp2 = entryPrice - (2*entryNloss)
float tp3 = entryPrice - (3*entryNloss)
sl_line := line.new(bar_index, sl, bar_index + 10, sl, color=color.new(color.red, 20), style=line.style_dashed, width=2)
tp1_line := line.new(bar_index, tp1, bar_index + 10, tp1, color=color.new(color.green, 20), style=line.style_dashed, width=2)
tp2_line := line.new(bar_index, tp2, bar_index + 10, tp2, color=color.new(color.green, 20), style=line.style_dashed, width=2)
tp3_line := line.new(bar_index, tp3, bar_index + 10, tp3, color=color.new(color.green, 20), style=line.style_dashed, width=2)
sl_label := label.new(bar_index + 10, sl, "SL (Rugi)", color=color.red, style=label.style_label_left, textcolor=color.white)
tp1_label := label.new(bar_index + 10, tp1, "TP1 (1:1)", color=color.green, style=label.style_label_left, textcolor=color.white)
tp2_label := label.new(bar_index + 10, tp2, "TP2 (1:2)", color=color.green, style=label.style_label_left, textcolor=color.white)
tp3_label := label.new(bar_index + 10, tp3, "TP3 (1:3)", color=color.green, style=label.style_label_left, textcolor=color.white)
else if pos != 0 and not na(sl_line)
// Update existing lines (Lightweight)
line.set_x2(sl_line, bar_index + 10)
line.set_x2(tp1_line, bar_index + 10)
line.set_x2(tp2_line, bar_index + 10)
line.set_x2(tp3_line, bar_index + 10)
label.set_x(sl_label, bar_index + 10)
label.set_x(tp1_label, bar_index + 10)
label.set_x(tp2_label, bar_index + 10)
label.set_x(tp3_label, bar_index + 10)
else if pos == 0
line.delete(sl_line)
sl_line := na
line.delete(tp1_line)
tp1_line := na
line.delete(tp2_line)
tp2_line := na
line.delete(tp3_line)
tp3_line := na
label.delete(sl_label)
sl_label := na
label.delete(tp1_label)
tp1_label := na
label.delete(tp2_label)
tp2_label := na
label.delete(tp3_label)
tp3_label := na
else
line.delete(sl_line)
sl_line := na
line.delete(tp1_line)
tp1_line := na
line.delete(tp2_line)
tp2_line := na
line.delete(tp3_line)
tp3_line := na
label.delete(sl_label)
sl_label := na
label.delete(tp1_label)
tp1_label := na
label.delete(tp2_label)
tp2_label := na
label.delete(tp3_label)
tp3_label := na
// ==============================================
// --- UPGRADE BARU: PIVOT POINTS (FIXED: EXTEND RIGHT) ---
// ==============================================
// Dapatkan Daily High, Low, Close (FIX "D")
p_d_h = request.security(syminfo.tickerid, "D", high , lookahead=barmerge.lookahead_on)
p_d_l = request.security(syminfo.tickerid, "D", low , lookahead=barmerge.lookahead_on)
p_d_c = request.security(syminfo.tickerid, "D", close , lookahead=barmerge.lookahead_on)
// Perhitungan Pivot Klasik
pivot_d = (p_d_h + p_d_l + p_d_c) / 3
r1_d = 2 * pivot_d - p_d_l
s1_d = 2 * pivot_d - p_d_h
r2_d = pivot_d + (p_d_h - p_d_l)
s2_d = pivot_d - (p_d_h - p_d_l)
// Visualisasi Pivot
var line p_line = na
var line r1_line = na
var line s1_line = na
var line r2_line = na
var line s2_line = na
var label p_label = na
var label r1_label = na
var label s1_label = na
var label r2_label = na
var label s2_label = na
// Fungsi untuk menghapus label/line
f_delete_pivot_objects() =>
line.delete(p_line)
line.delete(r1_line)
line.delete(s1_line)
line.delete(r2_line)
line.delete(s2_line)
label.delete(p_label)
label.delete(r1_label)
label.delete(s1_label)
label.delete(r2_label)
label.delete(s2_label)
if showPivotPoints
// Hapus yang lama agar tidak numpuk (Redraw Logic)
f_delete_pivot_objects()
// Logic: EXTEND RIGHT (Memanjang)
// Kita gunakan extend.right agar garisnya tidak pernah putus ke kanan
// Pivot (P)
p_line := line.new(bar_index, pivot_d, bar_index + 1, pivot_d, xloc.bar_index, extend.right, pivotColor, line.style_solid, 2)
p_label := label.new(bar_index + 10, pivot_d, "P Daily: " + str.tostring(pivot_d, format.mintick), xloc.bar_index, yloc.price, color=color.new(pivotColor, 20), textcolor=color.white, style=label.style_label_left, size=size.small)
// Resistance
r1_line := line.new(bar_index, r1_d, bar_index + 1, r1_d, xloc.bar_index, extend.right, color.new(color.red, 30), line.style_dashed, 1)
r1_label := label.new(bar_index + 10, r1_d, "R1: " + str.tostring(r1_d, format.mintick), xloc.bar_index, yloc.price, color=color.new(color.red, 80), textcolor=color.red, style=label.style_label_left, size=size.small)
r2_line := line.new(bar_index, r2_d, bar_index + 1, r2_d, xloc.bar_index, extend.right, color.new(color.red, 30), line.style_dashed, 1)
r2_label := label.new(bar_index + 10, r2_d, "R2: " + str.tostring(r2_d, format.mintick), xloc.bar_index, yloc.price, color=color.new(color.red, 80), textcolor=color.red, style=label.style_label_left, size=size.small)
// Support
s1_line := line.new(bar_index, s1_d, bar_index + 1, s1_d, xloc.bar_index, extend.right, color.new(color.green, 30), line.style_dashed, 1)
s1_label := label.new(bar_index + 10, s1_d, "S1: " + str.tostring(s1_d, format.mintick), xloc.bar_index, yloc.price, color=color.new(color.green, 80), textcolor=color.green, style=label.style_label_left, size=size.small)
s2_line := line.new(bar_index, s2_d, bar_index + 1, s2_d, xloc.bar_index, extend.right, color.new(color.green, 30), line.style_dashed, 1)
s2_label := label.new(bar_index + 10, s2_d, "S2: " + str.tostring(s2_d, format.mintick), xloc.bar_index, yloc.price, color=color.new(color.green, 80), textcolor=color.green, style=label.style_label_left, size=size.small)
else
f_delete_pivot_objects()
// ==============================================
// --- UPGRADE BARU: FIBONACCI RETRACEMENT (CLEAN NO STACK) ---
// ==============================================
var float fiboHigh = na
var float fiboLow = na
var int fiboStartBar = na
// Array untuk menyimpan objek Fibo
var line fiboLines = array.new(0)
var linefill fiboFills = array.new(0)
var label fiboLabels = array.new(0)
// Helper Function: Clean Up All Fibo Objects
f_cleanFibo() =>
if array.size(fiboLines) > 0
for i = 0 to array.size(fiboLines) - 1
line.delete(array.get(fiboLines, i))
array.clear(fiboLines)
if array.size(fiboFills) > 0
for i = 0 to array.size(fiboFills) - 1
linefill.delete(array.get(fiboFills, i))
array.clear(fiboFills)
if array.size(fiboLabels) > 0
for i = 0 to array.size(fiboLabels) - 1
label.delete(array.get(fiboLabels, i))
array.clear(fiboLabels)
// Calculate historical values globally
float lastHigh_scanned = ta.valuewhen(not na(pivotHigh), pivotHigh, 0)
float lastLow_scanned = ta.valuewhen(not na(pivotLow), pivotLow, 0)
// Reset Fibo jika ada sinyal entry baru
if buySignal or sellSignal
f_cleanFibo() // Clean old ones first!
// Gunakan nilai yang sudah di-scan secara global
if not na(lastHigh_scanned) and not na(lastLow_scanned)
fiboLow := lastLow_scanned
fiboHigh := lastHigh_scanned
fiboStartBar := bar_index
// Levels
fiboLevels = array.new(0)
array.push(fiboLevels, 0.0)
array.push(fiboLevels, 0.236)
array.push(fiboLevels, 0.382)
array.push(fiboLevels, 0.5)
array.push(fiboLevels, 0.618)
array.push(fiboLevels, 1.0)
// Gambar Fibo (Hanya digambar ulang jika posisi valid dan belum ada)
// Kita gunakan trik: Gambar setiap bar, tapi HAPUS yang lama dulu.
// Ini mencegah stacking ribuan kotak.
if showFiboLevels and not na(fiboHigh) and not na(fiboLow)
f_cleanFibo() // CLEANUP WAJIB SEBELUM GAMBAR BARU
float fiboRange = fiboHigh - fiboLow
int f_start = bar_index + fiboXOffset
int f_end = bar_index + fiboXOffset + 15
var line lastLineObj = na
for i = 0 to array.size(fiboLevels) - 1
float level = array.get(fiboLevels, i)
float fiboPrice = fiboHigh - (fiboRange * level)
string levelText = str.tostring(math.round(level * 100), "0.0") + "%"
color levelColor = color.rgb(19, 56, 189)
if level == 0.618
levelColor := color.new(#FFD700, 30)
else if level == 0.5
levelColor := color.new(color.green, 30)
else
levelColor := color.new(#7925c9, 70)
string l_style = (level == 0.0 or level == 1.0) ? line.style_dashed : line.style_solid
int l_width = (level == 0.618 or level == 0.5) ? 2 : 1
// Draw & Push Line
line currentLineObj = line.new(f_start, fiboPrice, f_end, fiboPrice, xloc.bar_index, extend.none, levelColor, l_style, l_width)
array.push(fiboLines, currentLineObj)
// Fill Logic
color c_fill = switch level
0.236 => color.new(color.gray, 70) // Sangat transparan (95)
0.382 => color.new(color.blue, 70)
0.5 => color.new(color.green, 70)
0.618 => color.new(#FFD700, 70)
1.0 => color.new(color.red, 70)
=> na
if i > 0
linefill lf = linefill.new(lastLineObj, currentLineObj, c_fill)
array.push(fiboFills, lf)
lastLineObj := currentLineObj
// Draw & Push Label
label lb = label.new(f_end, fiboPrice, levelText, xloc.bar_index, yloc.price, color=color.new(levelColor, 100), textcolor=levelColor, style=label.style_label_left, size=size.small)
array.push(fiboLabels, lb)
// ==============================================
// --- UPGRADE BARU: STOCHASTIC FLOATING MINI CHART (REALTIME ANCHOR RIGHT PATCH) ---
// ==============================================
// 1. Calculations
stochK = ta.sma(ta.stoch(close, high, low, 14), 3)
stochD = ta.sma(stochK, 3)
// 2. Data Storage (Arrays for History)
var float stochK_hist = array.new_float(0)
var float stochD_hist = array.new_float(0)
// Update Arrays (REALTIME LOGIC)
if barstate.isnew
array.push(stochK_hist, nz(stochK, 50))
array.push(stochD_hist, nz(stochD, 50))
// Limit array size to chart width + 1
if array.size(stochK_hist) > (stochWidth + 1)
array.shift(stochK_hist)
array.shift(stochD_hist)
else
// UPDATE TICK-BY-TICK (Agar tidak delay)
if array.size(stochK_hist) > 0
array.set(stochK_hist, array.size(stochK_hist) - 1, nz(stochK, 50))
array.set(stochD_hist, array.size(stochD_hist) - 1, nz(stochD, 50))
// 3. Drawing Logic
var box stochBgBox = na
var box stochUpperFill = na
var box stochLowerFill = na
var line stochLines = array.new_line(0)
// Clear Function
f_cleanStochChart() =>
if not na(stochBgBox)
box.delete(stochBgBox)
if not na(stochUpperFill)
box.delete(stochUpperFill)
if not na(stochLowerFill)
box.delete(stochLowerFill)
if array.size(stochLines) > 0
for i = 0 to array.size(stochLines) - 1
line.delete(array.get(stochLines, i))
array.clear(stochLines)
// Global Helper to map 0-100 Stoch value to Y price coordinate
f_mapY(_val, _bottom, _height) =>
_bottom + (_val / 100 * _height)
if showStochChart and array.size(stochK_hist) > 2
f_cleanStochChart() // Redraw every tick
// Positioning (ANCHOR RIGHT LOGIC)
int offset_right = 5
int ch_right = bar_index + offset_right // Ujung kanan box
int ch_left = ch_right - stochWidth
// Vertical Scaling
float ch_height = ta.atr(14) * 4
float ch_bottom = close - (ch_height * 1.5)
float ch_top = ch_bottom + ch_height
// Draw Background
stochBgBox := box.new(ch_left, ch_top, ch_right, ch_bottom, xloc=xloc.bar_index, border_width=1, border_color=color.new(color.white, 80), bgcolor=color.new(color.black, 100))
// Draw Overbought Fill (80-100)
stochUpperFill := box.new(ch_left, f_mapY(70, ch_bottom, ch_height), ch_right, f_mapY(80, ch_bottom, ch_height), xloc=xloc.bar_index, border_width=0, bgcolor=color.new(color.red, 100))
// Draw Oversold Fill (0-20)
stochLowerFill := box.new(ch_left, f_mapY(10, ch_bottom, ch_height), ch_right, f_mapY(0, ch_bottom, ch_height), xloc=xloc.bar_index, border_width=0, bgcolor=color.new(color.green, 100))
// Draw Reference Lines
line l80 = line.new(ch_left, f_mapY(80, ch_bottom, ch_height), ch_right, f_mapY(80, ch_bottom, ch_height), color=color.new(color.red, 20), style=line.style_dotted)
line l20 = line.new(ch_left, f_mapY(20, ch_bottom, ch_height), ch_right, f_mapY(20, ch_bottom, ch_height), color=color.new(color.green, 20), style=line.style_dotted)
array.push(stochLines, l80)
array.push(stochLines, l20)
// Draw K and D Lines (ANCHOR TO REALTIME BAR INDEX)
// PATCH: Iterate relative to current bar_index to ensure 0 gap
int sz = array.size(stochK_hist)
for i = 0 to sz - 2
// Logika Mundur: Titik terakhir (sz-1) harus ada di bar_index saat ini
int idx_current = sz - 1 - i
int idx_prev = sz - 2 - i
if idx_prev >= 0
// X Coordinates (Relative to Realtime Bar)
int x2 = bar_index - i
int x1 = bar_index - (i + 1)
// K Line
float yK1 = f_mapY(array.get(stochK_hist, idx_prev), ch_bottom, ch_height)
float yK2 = f_mapY(array.get(stochK_hist, idx_current), ch_bottom, ch_height)
if not na(yK1) and not na(yK2)
line lK = line.new(x1, yK1, x2, yK2, color=color.new(#05492f, 0), width=1)
array.push(stochLines, lK)
// D Line
float yD1 = f_mapY(array.get(stochD_hist, idx_prev), ch_bottom, ch_height)
float yD2 = f_mapY(array.get(stochD_hist, idx_current), ch_bottom, ch_height)
if not na(yD1) and not na(yD2)
line lD = line.new(x1, yD1, x2, yD2, color=color.new(#810404, 0), width=1)
array.push(stochLines, lD)
// ==============================================
// --- VISUALISASI UPGRADE: SMART SUPPLY/DEMAND ZONES ---
// ==============================================
ph_zone = ta.pivothigh(high, zoneLookback, zoneLookback)
pl_zone = ta.pivotlow(low, zoneLookback, zoneLookback)
// FIX: Pindahkan ATR ke luar IF agar konsisten
float atrForZone = ta.atr(14)
var box supplyBoxes = array.new_box()
var box demandBoxes = array.new_box()
// Batasi jumlah zona agar chart tetap bersih
maxZones = 5
// Deteksi Zona Supply (Merah)
if not na(ph_zone) and showSmartZones
// Buat box baru dari titik pivot sampai ke masa depan sedikit
b_sup = box.new(bar_index , high , bar_index + 20, high - (atrForZone*0.5), bgcolor=color.new(color.red, 85), border_color=color.new(color.red, 50))
array.push(supplyBoxes, b_sup)
if array.size(supplyBoxes) > maxZones
box.delete(array.shift(supplyBoxes))
// Deteksi Zona Demand (Hijau)
if not na(pl_zone) and showSmartZones
b_dem = box.new(bar_index , low , bar_index + 20, low + (atrForZone*0.5), bgcolor=color.new(color.lime, 85), border_color=color.new(color.lime, 50))
array.push(demandBoxes, b_dem)
if array.size(demandBoxes) > maxZones
box.delete(array.shift(demandBoxes))
// Perpanjang Zona Secara Realtime
if array.size(supplyBoxes) > 0 and showSmartZones
for i = 0 to array.size(supplyBoxes) - 1
b = array.get(supplyBoxes, i)
// Perpanjang ke bar saat ini + 5 agar terlihat "hidup"
box.set_right(b, bar_index + 5)
if array.size(demandBoxes) > 0 and showSmartZones
for i = 0 to array.size(demandBoxes) - 1
b = array.get(demandBoxes, i)
// Perpanjang ke bar saat ini + 5 agar terlihat "hidup"
box.set_right(b, bar_index + 5)
// ====================================================================================================
// BAGIAN 2: FITUR TAMBAHAN (HSN GHOST CANDLES) - DI-INJECT DI SINI
// ====================================================================================================
// --- TIPE DATA KHUSUS (HSN) ---
type CandleHSN
float o
float c
float h
float l
int o_idx
int c_idx
int h_idx
int l_idx
box body
line wick_up
line wick_down
type ImbalanceHSN
box b
int idx
type CandleSettingsHSN
bool show
string htf
int max_display
type SettingsHSN
int max_sets
color bull_body
color bull_border
color bull_wick
color bear_body
color bear_border
color bear_wick
int offset
int buffer
int htf_buffer
int width
bool trace_show
string trace_anchor
bool label_show
color label_color
string label_size
bool htf_label_show
color htf_label_color
string htf_label_size
bool htf_timer_show
color htf_timer_color
string htf_timer_size
type CandleSetHSN
CandleHSN candles
ImbalanceHSN imbalances
CandleSettingsHSN settings
label tfName
label tfTimer
type HelperHSN
string name = "Helper"
// --- SETUP PENGATURAN HSN ---
SettingsHSN settings = SettingsHSN.new()
var CandleSettingsHSN SettingsHTF1 = CandleSettingsHSN.new()
var CandleSettingsHSN SettingsHTF2 = CandleSettingsHSN.new()
var CandleHSN candles_1 = array.new(0)
var CandleHSN candles_2 = array.new(0)
var CandleSetHSN htf1 = CandleSetHSN.new()
htf1.settings := SettingsHTF1
htf1.candles := candles_1
var CandleSetHSN htf2 = CandleSetHSN.new()
htf2.settings := SettingsHTF2
htf2.candles := candles_2
// --- INPUT KHUSUS HSN CANDLES (15 & 30 MENIT) ---
grp_hsn = "🔥 HSN HTF Candles (Upgrade)"
htf1.settings.show := input.bool(true, "Show HTF 1 (15 Menit)", group=grp_hsn, inline="h1")
htf_1 = input.timeframe("15", "", group=grp_hsn, inline="h1")
htf1.settings.htf := htf_1
htf1.settings.max_display := 4
htf2.settings.show := input.bool(true, "Show HTF 2 (30 Menit)", group=grp_hsn, inline="h2")
htf_2 = input.timeframe("30", "", group=grp_hsn, inline="h2")
htf2.settings.htf := htf_2
htf2.settings.max_display := 4
settings.max_sets := 2
settings.bull_body := color.new(color.green, 60)
settings.bear_body := color.new(color.red, 60)
settings.bull_border := color.new(color.green, 10)
settings.bear_border := color.new(color.red, 10)
settings.bull_wick := color.new(color.green, 10)
settings.bear_wick := color.new(color.red, 10)
// FIXED: Increased default offset from 10 to 25 to avoid overlap with Advisor Bubble
settings.offset := input.int(25, "Padding/Jarak Candle", group=grp_hsn)
settings.buffer := 1
settings.htf_buffer := 5
settings.width := input.int(1, "Lebar Candle", minval = 1, maxval = 4, group=grp_hsn)*2
settings.htf_label_show := true
settings.htf_label_color := color.gray
settings.htf_label_size := size.normal
// --- HELPER FUNCTIONS ---
HelperHSN helper = HelperHSN.new()
color color_transparent = #ffffff00
method ValidTimeframe(HelperHSN helper, string HTF) =>
helper.name := HTF
if timeframe.in_seconds(HTF) >= timeframe.in_seconds("D") and timeframe.in_seconds(HTF) > timeframe.in_seconds()
true
else
n1 = timeframe.in_seconds()
n2 = timeframe.in_seconds(HTF)
n3 = n1 % n2
(n1 < n2 and math.round(n2/n1) == n2/n1)
method HTFName(HelperHSN helper, string HTF) =>
helper.name := "HTFName"
formatted = HTF
seconds = timeframe.in_seconds(HTF)
if seconds < 60
formatted := str.tostring(seconds) + "s"
else if (seconds / 60) < 60
formatted := str.tostring((seconds/60)) + "m"
else if (seconds/60/60) < 24
formatted := str.tostring((seconds/60/60)) + "H"
formatted
method HTFEnabled(HelperHSN helper) =>
helper.name := "HTFEnabled"
int enabled =0
enabled += htf1.settings.show ? 1 : 0
enabled += htf2.settings.show ? 1 : 0
int last = math.min(enabled, settings.max_sets)
last
method CandleSetHigh(HelperHSN helper, CandleHSN candles, float h) =>
helper.name := "CandlesSetHigh"
float _h = h
if array.size(candles) > 0
for i = 0 to array.size(candles)-1
// FIX: Diganti dari c menjadi cItem
CandleHSN cItem = array.get(candles, i)
if cItem.h > _h
_h := cItem.h
_h
method CandlesHigh(HelperHSN helper, CandleHSN candles) =>
helper.name := "CandlesHigh"
h = 0.0
int cnt = 0
int last = helper.HTFEnabled()
if htf1.settings.show and helper.ValidTimeframe(htf1.settings.htf)
h := helper.CandleSetHigh(htf1.candles, h)
cnt += 1
if htf2.settings.show and helper.ValidTimeframe(htf2.settings.htf) and cnt < last
h := helper.CandleSetHigh(htf2.candles, h)
cnt +=1
if array.size(candles) > 0
for i = 0 to array.size(candles)-1
// FIX: Diganti dari c menjadi cItem
CandleHSN cItem = array.get(candles, i)
if cItem.h > h
h := cItem.h
h
method Reorder(CandleSetHSN candleSet, int offset) =>
size = candleSet.candles.size()
if size > 0
for i = size-1 to 0
CandleHSN candle = candleSet.candles.get(i)
t_buffer = offset + ((settings.width+settings.buffer)*(size-i-1))
box.set_left(candle.body, bar_index + t_buffer)
box.set_right(candle.body, bar_index + settings.width + t_buffer)
line.set_x1(candle.wick_up, bar_index+((settings.width)/2) + t_buffer)
line.set_x2(candle.wick_up, bar_index+((settings.width)/2) + t_buffer)
line.set_x1(candle.wick_down, bar_index+((settings.width)/2) + t_buffer)
line.set_x2(candle.wick_down, bar_index+((settings.width)/2) + t_buffer)
top = helper.CandlesHigh(candleSet.candles)
left = bar_index + offset + ((settings.width+settings.buffer)*(size-1))/2
if settings.htf_label_show
var label l = candleSet.tfName
string lbl = helper.HTFName(candleSet.settings.htf)
if not na(l)
label.set_xy(l, left, top)
else
l := label.new(left, top, lbl, color=color_transparent, textcolor = settings.htf_label_color, style=label.style_label_down, size = settings.htf_label_size)
candleSet
method Monitor(CandleSetHSN candleSet) =>
HTFBarTime = time(candleSet.settings.htf)
isNewHTFCandle = ta.change(HTFBarTime)
if isNewHTFCandle
CandleHSN candle = CandleHSN.new()
candle.o := open
candle.c := close
candle.h := high
candle.l := low
candle.o_idx := bar_index
candle.c_idx := bar_index
candle.h_idx := bar_index
candle.l_idx := bar_index
bull = candle.c > candle.o
candle.body := box.new(bar_index, math.max(candle.o, candle.c), bar_index+2, math.min(candle.o, candle.c), bull ? settings.bull_border : settings.bear_border, 1, bgcolor = bull ? settings.bull_body : settings.bear_body)
candle.wick_up := line.new(bar_index+1, candle.h, bar_index, math.max(candle.o, candle.c), color=bull ? settings.bull_wick : settings.bear_wick)
candle.wick_down := line.new(bar_index+1, math.min(candle.o, candle.c), bar_index, candle.l, color=bull ? settings.bull_wick : settings.bear_wick)
candleSet.candles.unshift(candle)
if candleSet.candles.size() > candleSet.settings.max_display
CandleHSN delCandle = array.pop(candleSet.candles)
box.delete(delCandle.body)
line.delete(delCandle.wick_up)
line.delete(delCandle.wick_down)
candleSet
method Update(CandleSetHSN candleSet, int offset) =>
if candleSet.candles.size() > 0
CandleHSN candle = candleSet.candles.first()
candle.h_idx := high > candle.h ? bar_index : candle.h_idx
candle.h := high > candle.h ? high : candle.h
candle.l_idx := low < candle.l ? bar_index : candle.l_idx
candle.l := low < candle.l ? low : candle.l
candle.c := close
candle.c_idx := bar_index
bull = candle.c > candle.o
box.set_top(candle.body, bull ? candle.c : candle.o)
box.set_bottom(candle.body, bull ? candle.o : candle.c)
box.set_bgcolor(candle.body, bull ? settings.bull_body : settings.bear_body)
box.set_border_color(candle.body, bull ? settings.bull_border : settings.bear_border)
line.set_color(candle.wick_up, bull ? settings.bull_wick : settings.bear_wick)
line.set_color(candle.wick_down, bull ? settings.bull_wick : settings.bear_wick)
line.set_y1(candle.wick_up, candle.h)
line.set_y2(candle.wick_up, math.max(candle.o, candle.c))
line.set_y1(candle.wick_down, candle.l)
line.set_y2(candle.wick_down, math.min(candle.o, candle.c))
if barstate.isrealtime or barstate.islast
candleSet.Reorder(offset)
candleSet
// --- EKSEKUSI HSN LOGIC ---
int cnt_hsn = 0
int last_hsn = helper.HTFEnabled()
int offset_hsn = settings.offset
if htf1.settings.show and helper.ValidTimeframe(htf1.settings.htf)
htf1.Monitor().Update(offset_hsn)
cnt_hsn +=1
offset_hsn += cnt_hsn > 0 ? (htf1.candles.size() * settings.width) + (htf1.candles.size() > 0 ? htf1.candles.size()-1 * settings.buffer : 0) + settings.htf_buffer : 0
if htf2.settings.show and helper.ValidTimeframe(htf2.settings.htf) and cnt_hsn < last_hsn
htf2.Monitor().Update(offset_hsn)
cnt_hsn+=1
offset_hsn += cnt_hsn > 0 ? (htf2.candles.size() * settings.width) + (htf2.candles.size() > 0 ? htf2.candles.size()-1 * settings.buffer : 0) + settings.htf_buffer : 0
Pesquisar nos scripts por "mtf"
Magnitude of Price DiscoveryThis script is a simple attempt to show the magnitude of price discovery
Before we discuss how it works we need to discuss our terms.
Universal Truth of Price #1 - Price only trades in 3 distinct ways
Scenario 1 - Inside bar to previous range, consolidation.
Scenario 2 - Trending bar up or down, HH + HL to previous bar or LL + LH to previous bar
Scenario 3 - Outside bar, Higher highs AND lower lows to previous bar. Also known as a broadening formation.
If you are interested in the 2nd universal truth my indicator 'Timeframe Continuity Bars' discusses it there.
Given one of the 3 scenarios price can trade in is a broadening formation it proves that price discovery occurs as a series of new highs and new lows.
Notice the scenario 3 marked by SimpleStratNumbers
This scenario 3 is a broadening formation on the 1min and on the 30min basis.
Given this is true we know if price rejects the broadening highs it is attempting to make new lows to the broadening range
So, what this indicator does is it uses previous swing highs and swing lows and it shows you when price reclaims them and gives you a target.
The target of this indicator is guaranteed to be hit if the 2nd universal truth of price is in your favor.
This means if we reclaim a previous high to the downside. At the time of all known participation groups selling we know the magnitude of this selling would be the other side of the range
So it's simple, the solid line shows you the reclaimed level.
The dotted line shows you the magnitude.
Full timeframe continuity tells you when it is FOR SURE going to your target price via MTF analysis of the aggressiveness of the buyers/sellers.
However timeframe continuity is subject to change every 60min, every day, every week, and every month! That's the risk you take when trading.
Here's one example for you.
NASDAQ:AAPL monthly made a new low and changed to green this was your evidence price is attempting to take the other side of the range.
NASDAQ:AAPL monthly opened green again and re-confirmed the upside which meant the other side
of the range was still for certain going to be taken out.
After being taken out, breakout traders buy the highs and any shorts in aapl are forced to cover.
BOOM!
This indicator is likely to be updated in the near future to align entries on multiple timeframes.
Nothing spoken here is financial advice and it is ONLY what we know to be true about price action.
Al Sat Alpha Hunter System [MTF + Risk Manager]çok güzel yerlerden al sat komutu çıkıyor ve bunu size ücretsiz vermek istedim sizde faydalanın
SpatialIndexYou can start using this now by inserthing this at the top of your indicator/strategy/library.
import ArunaReborn/SpatialIndex/1 as SI
Overview
SpatialIndex is a high-performance Pine Script library that implements price-bucketed spatial indexing for efficient proximity queries on large datasets. Instead of scanning through hundreds or thousands of items linearly (O(n)), this library provides O(k) bucket lookup where k is typically just a handful of buckets, dramatically improving performance for price-based filtering operations.
This library works with any data type through index-based references, making it universally applicable for support/resistance levels, pivot points, order zones, pattern detection points, Fair Value Gaps, and any other price-based data that needs frequent proximity queries.
Why This Library Exists
The Problem
When building advanced technical indicators that track large numbers of price levels (support/resistance zones, pivot points, order blocks, etc.), you often need to answer questions like:
- *"Which levels are within 5% of the current price?"*
- *"What zones overlap with this price range?"*
- *"Are there any significant levels near my entry point?"*
The naive approach is to loop through every single item and check its price. For 500 levels across multiple timeframes, this means 500 comparisons every bar . On instruments with thousands of historical bars, this quickly becomes a performance bottleneck that can cause scripts to time out or lag.
The Solution
SpatialIndex solves this by organizing items into price buckets —like filing cabinets organized by price range. When you query for items near $50,000, the library only looks in the relevant buckets (e.g., $49,000-$51,000 range), ignoring all other price regions entirely.
Performance Example:
- Linear scan: Check 500 items = 500 comparisons per query
- Spatial index: Check 3-5 buckets with ~10 items each = 30-50 comparisons per query
- Result: 10-16x faster queries
Key Features
Core Capabilities
- ✅ Generic Design : Works with any data type via index references
- ✅ Multiple Index Strategies : Fixed bucket size or ATR-based dynamic sizing
- ✅ Range Support : Index items that span price ranges (zones, gaps, channels)
- ✅ Efficient Queries : O(k) bucket lookup instead of O(n) linear scan
- ✅ Multiple Query Types : Proximity percentage, fixed range, exact price with tolerance
- ✅ Dynamic Updates : Add, remove, update items in O(1) time
- ✅ Batch Operations : Efficient bulk removal and reindexing
- ✅ Query Caching : Optional caching for repeated queries within same bar
- ✅ Statistics & Debugging : Built-in stats and diagnostic functions
### Advanced Features
- ATR-Based Bucketing : Automatically adjusts bucket sizes based on volatility
- Multi-Bucket Spanning : Items that span ranges are indexed in all overlapping buckets
- Reindexing Support : Handles array removals with automatic index shifting
- Cache Management : Configurable query caching with automatic invalidation
- Empty Bucket Cleanup : Automatically removes empty buckets to minimize memory
How It Works
The Bucketing Concept
Think of price space as divided into discrete buckets, like a histogram:
```
Price Range: $98-$100 $100-$102 $102-$104 $104-$106 $106-$108
Bucket Key: 49 50 51 52 53
Items:
```
When you query for items near $103:
1. Calculate which buckets overlap the $101.50-$104.50 range (keys 50, 51, 52)
2. Return items from only those buckets:
3. Never check items in buckets 49 or 53
Bucket Size Selection
Fixed Size Mode:
```pine
var SI.SpatialBucket index = SI.newSpatialBucket(2.0) // $2 per bucket
```
- Good for: Instruments with stable price ranges
- Example: For stocks trading at $100, 2.0 = 2% increments
ATR-Based Mode:
```pine
float atr = ta.atr(14)
var SI.SpatialBucket index = SI.newSpatialBucketATR(1.0, atr) // 1x ATR per bucket
SI.updateATR(index, atr) // Update each bar
```
- Good for: Instruments with varying volatility
- Adapts automatically to market conditions
- 1.0 multiplier = one bucket spans one ATR unit
Optimal Bucket Size:
The library includes a helper function to calculate optimal size:
```pine
float optimalSize = SI.calculateOptimalBucketSize(close, 5.0) // For 5% proximity queries
```
This ensures queries span approximately 3 buckets for optimal performance.
Index-Based Architecture
The library doesn't store your actual data—it only stores indices that point to your external arrays:
```pine
// Your data
var array levels = array.new()
var array types = array.new()
var array ages = array.new()
// Your index
var SI.SpatialBucket index = SI.newSpatialBucket(2.0)
// Add a level
array.push(levels, 50000.0)
array.push(types, "support")
array.push(ages, 0)
SI.add(index, array.size(levels) - 1, 50000.0) // Store index 0
// Query near current price
SI.QueryResult result = SI.queryProximity(index, close, 5.0)
for idx in result.indices
float level = array.get(levels, idx)
string type = array.get(types, idx)
// Work with your actual data
```
This design means:
- ✅ Works with any data structure you define
- ✅ No data duplication
- ✅ Minimal memory footprint
- ✅ Full control over your data
---
Usage Guide
Basic Setup
```pine
// Import library
import username/SpatialIndex/1 as SI
// Create index
var SI.SpatialBucket index = SI.newSpatialBucket(2.0)
// Your data arrays
var array supportLevels = array.new()
var array touchCounts = array.new()
```
Adding Items
Single Price Point:
```pine
// Add a support level at $50,000
array.push(supportLevels, 50000.0)
array.push(touchCounts, 1)
int levelIdx = array.size(supportLevels) - 1
SI.add(index, levelIdx, 50000.0)
```
Price Range (Zones/Gaps):
```pine
// Add a resistance zone from $51,000 to $52,000
array.push(zoneBottoms, 51000.0)
array.push(zoneTops, 52000.0)
int zoneIdx = array.size(zoneBottoms) - 1
SI.addRange(index, zoneIdx, 51000.0, 52000.0) // Indexed in all overlapping buckets
```
Querying Items
Proximity Query (Percentage):
```pine
// Find all levels within 5% of current price
SI.QueryResult result = SI.queryProximity(index, close, 5.0)
if array.size(result.indices) > 0
for idx in result.indices
float level = array.get(supportLevels, idx)
// Process nearby level
```
Fixed Range Query:
```pine
// Find all items between $49,000 and $51,000
SI.QueryResult result = SI.queryRange(index, 49000.0, 51000.0)
```
Exact Price with Tolerance:
```pine
// Find items at exactly $50,000 +/- $100
SI.QueryResult result = SI.queryAt(index, 50000.0, 100.0)
```
Removing Items
Safe Removal Pattern:
```pine
SI.QueryResult result = SI.queryProximity(index, close, 5.0)
if array.size(result.indices) > 0
// IMPORTANT: Sort descending to safely remove from arrays
array sorted = SI.sortIndicesDescending(result)
for idx in sorted
// Remove from index
SI.remove(index, idx)
// Remove from your data arrays
array.remove(supportLevels, idx)
array.remove(touchCounts, idx)
// Reindex to maintain consistency
SI.reindexAfterRemoval(index, idx)
```
Batch Removal (More Efficient):
```pine
// Collect indices to remove
array toRemove = array.new()
for i = 0 to array.size(supportLevels) - 1
if array.get(touchCounts, i) > 10 // Remove old levels
array.push(toRemove, i)
// Remove in descending order from data arrays
array sorted = array.copy(toRemove)
array.sort(sorted, order.descending)
for idx in sorted
SI.remove(index, idx)
array.remove(supportLevels, idx)
array.remove(touchCounts, idx)
// Batch reindex (much faster than individual reindexing)
SI.reindexAfterBatchRemoval(index, toRemove)
```
Updating Items
```pine
// Update a level's price (e.g., after refinement)
float newPrice = 50100.0
SI.update(index, levelIdx, newPrice)
array.set(supportLevels, levelIdx, newPrice)
// Update a zone's range
SI.updateRange(index, zoneIdx, 51000.0, 52500.0)
array.set(zoneBottoms, zoneIdx, 51000.0)
array.set(zoneTops, zoneIdx, 52500.0)
```
Query Caching
For repeated queries within the same bar:
```pine
// Create cache (persistent)
var SI.CachedQuery cache = SI.newCachedQuery()
// Cached query (returns cached result if parameters match)
SI.QueryResult result = SI.queryProximityCached(
index,
cache,
close,
5.0, // proximity%
1 // cache duration in bars
)
// Invalidate cache when index changes significantly
if bigChangeDetected
SI.invalidateCache(cache)
```
---
Practical Examples
Example 1: Support/Resistance Finder
```pine
//@version=6
indicator("S/R with Spatial Index", overlay=true)
import username/SpatialIndex/1 as SI
// Data storage
var array levels = array.new()
var array types = array.new() // "support" or "resistance"
var array touches = array.new()
var array ages = array.new()
// Spatial index
var SI.SpatialBucket index = SI.newSpatialBucket(close * 0.02) // 2% buckets
// Detect pivots
bool isPivotHigh = ta.pivothigh(high, 5, 5)
bool isPivotLow = ta.pivotlow(low, 5, 5)
// Add new levels
if isPivotHigh
array.push(levels, high )
array.push(types, "resistance")
array.push(touches, 1)
array.push(ages, 0)
SI.add(index, array.size(levels) - 1, high )
if isPivotLow
array.push(levels, low )
array.push(types, "support")
array.push(touches, 1)
array.push(ages, 0)
SI.add(index, array.size(levels) - 1, low )
// Find nearby levels (fast!)
SI.QueryResult nearby = SI.queryProximity(index, close, 3.0) // Within 3%
// Process nearby levels
for idx in nearby.indices
float level = array.get(levels, idx)
string type = array.get(types, idx)
// Check for touch
if type == "support" and low <= level and low > level
array.set(touches, idx, array.get(touches, idx) + 1)
else if type == "resistance" and high >= level and high < level
array.set(touches, idx, array.get(touches, idx) + 1)
// Age and cleanup old levels
for i = array.size(ages) - 1 to 0
array.set(ages, i, array.get(ages, i) + 1)
// Remove levels older than 500 bars or with 5+ touches
if array.get(ages, i) > 500 or array.get(touches, i) >= 5
SI.remove(index, i)
array.remove(levels, i)
array.remove(types, i)
array.remove(touches, i)
array.remove(ages, i)
SI.reindexAfterRemoval(index, i)
// Visualization
for idx in nearby.indices
line.new(bar_index, array.get(levels, idx), bar_index + 10, array.get(levels, idx),
color=array.get(types, idx) == "support" ? color.green : color.red)
```
Example 2: Multi-Timeframe Zone Detector
```pine
//@version=6
indicator("MTF Zones", overlay=true)
import username/SpatialIndex/1 as SI
// Store zones from multiple timeframes
var array zoneBottoms = array.new()
var array zoneTops = array.new()
var array zoneTimeframes = array.new()
// ATR-based spatial index for adaptive bucketing
var SI.SpatialBucket index = SI.newSpatialBucketATR(1.0, ta.atr(14))
SI.updateATR(index, ta.atr(14)) // Update bucket size with volatility
// Request higher timeframe data
= request.security(syminfo.tickerid, "240", )
// Detect HTF zones
if not na(htf_high) and not na(htf_low)
float zoneTop = htf_high
float zoneBottom = htf_low * 0.995 // 0.5% zone thickness
// Check if zone already exists nearby
SI.QueryResult existing = SI.queryRange(index, zoneBottom, zoneTop)
if array.size(existing.indices) == 0 // No overlapping zones
// Add new zone
array.push(zoneBottoms, zoneBottom)
array.push(zoneTops, zoneTop)
array.push(zoneTimeframes, "4H")
int idx = array.size(zoneBottoms) - 1
SI.addRange(index, idx, zoneBottom, zoneTop)
// Query zones near current price
SI.QueryResult nearbyZones = SI.queryProximity(index, close, 2.0) // Within 2%
// Highlight nearby zones
for idx in nearbyZones.indices
box.new(bar_index - 50, array.get(zoneBottoms, idx),
bar_index, array.get(zoneTops, idx),
bgcolor=color.new(color.blue, 90))
```
### Example 3: Performance Comparison
```pine
//@version=6
indicator("Spatial Index Performance Test")
import username/SpatialIndex/1 as SI
// Generate 500 random levels
var array levels = array.new()
var SI.SpatialBucket index = SI.newSpatialBucket(close * 0.02)
if bar_index == 0
for i = 0 to 499
float randomLevel = close * (0.9 + math.random() * 0.2) // +/- 10%
array.push(levels, randomLevel)
SI.add(index, i, randomLevel)
// Method 1: Linear scan (naive approach)
int linearCount = 0
float proximityPct = 5.0
float lowBand = close * (1 - proximityPct/100)
float highBand = close * (1 + proximityPct/100)
for i = 0 to array.size(levels) - 1
float level = array.get(levels, i)
if level >= lowBand and level <= highBand
linearCount += 1
// Method 2: Spatial index query
SI.QueryResult result = SI.queryProximity(index, close, proximityPct)
int spatialCount = array.size(result.indices)
// Compare performance
plot(result.queryCount, "Items Examined (Spatial)", color=color.green)
plot(linearCount, "Items Examined (Linear)", color=color.red)
plot(spatialCount, "Results Found", color=color.blue)
// Spatial index typically examines 10-50 items vs 500 for linear scan!
```
API Reference Summary
Initialization
- `newSpatialBucket(bucketSize)` - Fixed bucket size
- `newSpatialBucketATR(atrMultiplier, atrValue)` - ATR-based buckets
- `updateATR(sb, newATR)` - Update ATR for dynamic sizing
Adding Items
- `add(sb, itemIndex, price)` - Add item at single price point
- `addRange(sb, itemIndex, priceBottom, priceTop)` - Add item spanning range
Querying
- `queryProximity(sb, refPrice, proximityPercent)` - Query by percentage
- `queryRange(sb, priceBottom, priceTop)` - Query fixed range
- `queryAt(sb, price, tolerance)` - Query exact price with tolerance
- `queryProximityCached(sb, cache, refPrice, pct, duration)` - Cached query
Removing & Updating
- `remove(sb, itemIndex)` - Remove item
- `update(sb, itemIndex, newPrice)` - Update item price
- `updateRange(sb, itemIndex, newBottom, newTop)` - Update item range
- `reindexAfterRemoval(sb, removedIndex)` - Reindex after single removal
- `reindexAfterBatchRemoval(sb, removedIndices)` - Batch reindex
- `clear(sb)` - Remove all items
Utilities
- `size(sb)` - Get item count
- `isEmpty(sb)` - Check if empty
- `contains(sb, itemIndex)` - Check if item exists
- `getStats(sb)` - Get debug statistics string
- `calculateOptimalBucketSize(price, pct)` - Calculate optimal bucket size
- `sortIndicesDescending(result)` - Sort for safe removal
- `sortIndicesAscending(result)` - Sort ascending
Performance Characteristics
Time Complexity
- Add : O(1) for single point, O(m) for range spanning m buckets
- Remove : O(1) lookup + O(b) bucket cleanup where b = buckets item spans
- Query : O(k) where k = buckets in range (typically 3-5) vs O(n) linear scan
- Update : O(1) removal + O(1) addition = O(1) total
Space Complexity
- Memory per item : ~8 bytes for index reference + map overhead
- Bucket overhead : Proportional to price range coverage
- Typical usage : For 500 items with 50 active buckets ≈ 4-8KB total
Scalability
- ✅ 100 items : ~5-10x faster than linear scan
- ✅ 500 items : ~10-15x faster
- ✅ 1000+ items : ~15-20x faster
- ⚠️ Performance degrades if bucket size is too small (too many buckets)
- ⚠️ Performance degrades if bucket size is too large (too many items per bucket)
Best Practices
Bucket Size Selection
1. Start with 2-5% of asset price for percentage-based queries
2. Use ATR-based mode for volatile assets or multi-symbol scripts
3. Test bucket size using `calculateOptimalBucketSize()` function
4. Monitor with `getStats()` to ensure reasonable bucket count
Memory Management
1. Clear old items regularly to prevent unbounded growth
2. Use age tracking to remove stale data
3. Set maximum item limits based on your needs
4. Batch removals are more efficient than individual removals
Query Optimization
1. Use caching for repeated queries within same bar
2. Invalidate cache when index changes significantly
3. Sort results descending before removal iteration
4. Batch operations when possible (reindexing, removal)
Data Consistency
1. Always reindex after removal to maintain index alignment
2. Remove from arrays in descending order to avoid index shifting issues
3. Use batch reindex for multiple simultaneous removals
4. Keep external arrays and index in sync at all times
Limitations & Caveats
Known Limitations
- Not suitable for exact price matching : Use tolerance with `queryAt()`
- Bucket size affects performance : Too small = many buckets, too large = many items per bucket
- Memory usage : Scales with price range coverage and item count
- Reindexing overhead : Removing items mid-array requires index shifting
When NOT to Use
- ❌ Datasets with < 50 items (linear scan is simpler)
- ❌ Items that change price every bar (constant reindexing overhead)
- ❌ When you need ALL items every time (no benefit over arrays)
- ❌ Exact price level matching without tolerance (use maps instead)
When TO Use
- ✅ Large datasets (100+ items) with occasional queries
- ✅ Proximity-based filtering (% of price, ATR-based ranges)
- ✅ Multi-timeframe level tracking
- ✅ Zone/range overlap detection
- ✅ Price-based spatial filtering
---
Technical Details
Bucketing Algorithm
Items are assigned to buckets using integer division:
```
bucketKey = floor((price - basePrice) / bucketSize)
```
For ATR-based mode:
```
effectiveBucketSize = atrValue × atrMultiplier
bucketKey = floor((price - basePrice) / effectiveBucketSize)
```
Range Indexing
Items spanning price ranges are indexed in all overlapping buckets to ensure accurate range queries. The midpoint bucket is designated as the "primary bucket" for removal operations.
Index Consistency
The library maintains two maps:
1. `buckets`: Maps bucket keys → IntArray wrappers containing item indices
2. `itemToBucket`: Maps item indices → primary bucket key (for O(1) removal)
This dual-mapping ensures both fast queries and fast removal while maintaining consistency.
Implementation Note: Pine Script doesn't allow nested collections (map containing arrays directly), so the library uses an `IntArray` wrapper type to hold arrays within the map structure. This is an internal implementation detail that doesn't affect usage.
---
Version History
Version 1.0
- Initial release
Credits & License
License : Mozilla Public License 2.0 (TradingView default)
Library Type : Open-source educational resource
This library is designed as a public domain utility for the Pine Script community. As per TradingView library rules, this code can be freely reused by other authors. If you use this library in your scripts, please provide appropriate credit as required by House Rules.
Summary
SpatialIndex is a specialized library that solves a specific problem: fast proximity queries on large price-based datasets . If you're building indicators that track hundreds of levels, zones, or price points and need to frequently filter by proximity to current price, this library can provide 10-20x performance improvements over naive linear scanning.
The index-based architecture makes it universally applicable to any data type, and the ATR-based bucketing ensures it adapts to market conditions automatically. Combined with query caching and batch operations, it provides a complete solution for spatial data management in Pine Script.
Use this library when speed matters and your dataset is large.
Timeframe Continuity BarsTimeframe Continuity Bars is a script that is extremely simple for good reason
So please, do not remove this post because it seems 'simple'
Now that's over with. Lets dive in to understand what timeframe continuity IS and what this indicator does.
Timeframe continuity is defined by 4 or more timeframes and it is the relationship of the last price traded to those 4 opening prices. Standard timeframe continuity would be using the M,W,D,60min timeframes.
The reason we use MTF analysis is because of the truth of what price is and how it works.
Price movement is SOLELY caused due to aggressive buying / selling. Some may attempt to refute this however at the end of the day. If the price is at 100.00 it is because a buyer is willing to buy there and a seller is willing to sell there. If those market participants did not want to buy or sell at 100.00 price would go up or down to meet the more aggressive participant.
So what does this look like you may ask...
If an aggressive buyer takes the offer we will see prices go up if they were willing to pay more than the last guy who took the offer.
So price may go from 100.00 to 100.01 because you decided to invest in that stock that day at that time with a market order
This same thing occurs when every other institution creates, adds, reduces, or exits a position. They have to buy or sell and they have to either do it aggressively or do it passively by sitting on the bid / ask and waiting.
So since this is true, we know that the relationship to the opening price is extremely important. This is because if price is above it's open that means buyers were willing to take the offer and buy at higher prices. If price is below it's open it means that sellers were willing to sell at the bid and they sold at lower prices.
So any candlestick chart is simply an aggregation of this aggressive buying/selling that is taking place at all times.
By using the timeframe continuity bars indicator we can measure the distance from the current open across 4 or more timeframes.
By doing this we can identify monthly participation groups, weekly participation groups, daily participation groups, and 60min participation groups.
When all those groups align green or red this is considered full timeframe continuity. Where the monthly weekly daily 60min groups are all taking the offer and buying, or all selling at the bid!
When this aligns this is when price is for CERTAIN going in one direction.
However, It is subject to change every 60 minutes as the 60min determines if those monthly weekly daily buyers are present RIGHT NOW.
So if the 60min changes we go into direct conflict against the month/week/day groups.
If we see the 60min and day align we go into direct conflict against the month/week
if the 60min day and week are red we over-take the monthly group for control. At the time of the week day and 60 being red we have ZERO evidence of the previous monthly buyer/seller that was present.
Now that you understand a little bit about continuity.. Check it out on the chart!
P.S Here is some tips
1) it is not about just all timeframes aligning, we want to see long green / red bars!
2) The opens reset on a cyclical basis. Each day, each week, each month... When the new timeframes open we will see timeframes have the SAME open. When the opens are the same price we have LESS evidence versus having all opens seperate.
3) Investors can use the Y Q M W as their 4 timeframes to see when institutional buying is occurring [go do a case study on AMEX:GLD and AMEX:SLV weekly timeframe with these settings]
4) You need to add 4 separate indicators and change the timeframes. It is ideal to then save this layout!
5) The best way to do price analysis is using #TheStrat across all 4 timeframes instead of one timeframe with this indicator. This is soley a tool we use to show changing of control between participation groups!
TimeframeAlignTHE PROBLEM THIS LIBRARY SOLVES
When you use `request.security()` to get data from a Higher Timeframe (HTF) and try to draw objects like boxes, lines, or labels, they appear at the wrong horizontal position . This is the "floating in space" problem.
Why does this happen?
The `bar_index` in Pine Script refers to where data was RECEIVED , not where the event OCCURRED .
Consider this scenario:
• You're on a 5-minute chart
• You request 1-hour data for drawing an FVG (Fair Value Gap)
• A 1H candle spans 12 chart bars (60min / 5min = 12)
• But your code draws at `bar_index - 1` or `bar_index - 3`
• The result: your FVG box is only 2-3 bars wide instead of spanning the correct 12-36 bars
This library solves that by tracking where HTF bars actually start and end on your chart timeframe.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
HOW TO USE THIS LIBRARY
Step 1: Import the Library
```
import ArunaReborn/TimeframeAlign/1 as tfa
```
Step 2: Create a Tracker for Each HTF
```
var tfa.HTFTracker tracker1H = tfa.createTracker("60")
```
Step 3: Update the Tracker Every Bar
```
tfa.updateTracker(tracker1H, "60")
```
Step 4: Use Synced Drawing Functions
```
if tfa.htfBarChanged(tracker1H)
tfa.syncedBox(tracker1H, 3, 1, topPrice, bottomPrice, color.new(color.green, 80))
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
EXPORTED TYPES
TimeframePair
Stores metadata about the relationship between source and chart timeframes.
• sourceTimeframe - The HTF/LTF being compared
• chartTimeframe - Current chart timeframe
• isHTF - True if source is higher than chart
• isLTF - True if source is lower than chart
• barRatio - Chart bars per source bar
• secondsRatio - Time ratio between timeframes
MTFEventData
Stores synchronized event data with correct bar positions.
• price - Price level of the event
• eventTime - Unix timestamp of the event
• chartBarStart - Chart bar_index where event's TF bar started
• chartBarEnd - Chart bar_index where event's TF bar ended
• htfOffset - The HTF offset used
• isValid - True if synchronization succeeded
HTFTracker
Tracks HTF bar boundaries. Create one per timeframe you need to track.
• htfTimeframe - The timeframe being tracked
• currentStartBar - Where current HTF bar started
• currentEndBar - Where current HTF bar ends (provisional)
• startHistory - Array of historical start positions
• endHistory - Array of historical end positions
• lastUpdateBar - Last bar_index when updated
• barJustChanged - True if HTF bar changed on this chart bar (set by updateTracker)
SyncedBox
Managed box with synchronization metadata.
• bx - The Pine Script box object
• htfTimeframe - Source timeframe
• leftHtfOffset / rightHtfOffset - HTF offsets for edges
• topPrice / bottomPrice - Price boundaries
• extendRight - Auto-extend flag
SyncedLine
Managed line with synchronization metadata.
• ln - The Pine Script line object
• htfTimeframe - Source timeframe
• htfOffset - Anchor offset
• price - Price level (horizontal lines)
• isHorizontal - Line orientation
• extendRight - Auto-extend flag
SyncedLabel
Managed label with synchronization metadata.
• lbl - The Pine Script label object
• htfTimeframe - Source timeframe
• htfOffset - Anchor offset
• price - Price level
• anchorPoint - "start", "end", or "middle"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
EXPORTED FUNCTIONS
━━ CORE FUNCTIONS ━━
getTimeframeInfo(sourceTimeframe)
Analyzes relationship between a source TF and chart TF.
Returns: TimeframePair with comparison metadata
createTracker(htfTimeframe)
Creates a new HTF tracker. Call once per timeframe, store with `var`.
Returns: HTFTracker instance
updateTracker(tracker, htfTimeframe, historyDepth)
Updates tracker with current bar data. Call on every bar.
• htfTimeframe: The timeframe string (must match createTracker)
• historyDepth: Max HTF bars to track (default 500)
Returns: Updated tracker
getStartBar(tracker, htfOffset)
Gets chart bar_index where a specific HTF bar started.
• htfOffset: 0=current, 1=previous, 2=two bars ago, etc.
Returns: bar_index or na
getEndBar(tracker, htfOffset)
Gets chart bar_index where a specific HTF bar ended.
Returns: bar_index or na
htfBarChanged(tracker)
Detects when HTF bar just changed.
Returns: True on first chart bar of new HTF bar
findBarAtTime(timestamp, maxLookback)
Searches backward to find chart bar containing a timestamp.
• maxLookback: How far back to search (default 500)
Returns: bar_index or na
syncEventToChart(tracker, eventPrice, eventTime, anchorPoint)
Generic sync function mapping any event to correct chart position.
• anchorPoint: "start", "end", or "middle"
Returns: MTFEventData
━━ DRAWING CREATION FUNCTIONS ━━
syncedBox(tracker, leftHtfOffset, rightHtfOffset, topPrice, bottomPrice, bgcolor, ...)
Creates a box at correct HTF-aligned position.
• leftHtfOffset: HTF bars back for left edge
• rightHtfOffset: HTF bars back for right edge
• extendRight: Auto-extend to current bar
Returns: SyncedBox or na
syncedHLine(tracker, htfOffset, price, lineColor, lineStyle, lineWidth, extendRight)
Creates horizontal line anchored to HTF bar start.
• extendRight: If true, extends to current bar (default true)
Returns: SyncedLine or na
syncedVLine(tracker, htfOffset, atStart, lineColor, lineStyle, lineWidth)
Creates vertical line at HTF bar boundary.
• atStart: True=start of HTF bar, False=end
Returns: SyncedLine or na
syncedLabel(tracker, htfOffset, price, labelText, anchorPoint, ...)
Creates label at correct HTF-aligned position.
• anchorPoint: "start", "end", or "middle"
Returns: SyncedLabel or na
syncedPlotValue(tracker, value, htfOffset)
Returns value for plotting only at synced positions.
Returns: value if current bar is within HTF range, otherwise na
━━ UPDATE FUNCTIONS ━━
updateSyncedBox(syncedBox, extendToCurrentBar)
Extends existing box's right edge to current bar.
Returns: Updated SyncedBox
updateSyncedLine(syncedLine, extendToCurrentBar)
Extends existing horizontal line to current bar.
Returns: Updated SyncedLine
updateSyncedLabel(syncedLabel, tracker, newText, newPrice)
Updates label text/price while maintaining sync.
Returns: Updated SyncedLabel
━━ CONVENIENCE FUNCTIONS ━━
htfBarStartIndex(htfTimeframe, htfOffset, historyDepth)
Simple function to get HTF bar start without explicit tracker.
⚠️ Only tracks ONE timeframe. For multiple TFs, use createTracker pattern.
Returns: bar_index or na
htfBarEndIndex(htfTimeframe, htfOffset, historyDepth)
Simple function to get HTF bar end without explicit tracker.
⚠️ Only tracks ONE timeframe. For multiple TFs, use createTracker pattern.
Returns: bar_index or na
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
COMPLETE USAGE EXAMPLES
Example 1: FVG Box with Auto-Extend
```
//@version=6
indicator("FVG with Synced Drawing", overlay=true)
import ArunaReborn/TimeframeAlign/1 as tfa
htfInput = input.timeframe("60", "HTF for FVG")
// Create tracker for chosen timeframe
var tfa.HTFTracker fvgTracker = tfa.createTracker(htfInput)
tfa.updateTracker(fvgTracker, htfInput)
// Get FVG data from HTF (confirmed bars with offset)
= request.security(syminfo.tickerid, htfInput,
[low , high , low > high ],
lookahead=barmerge.lookahead_off)
// Store managed box
var tfa.SyncedBox fvgBox = na
// Create synced box when FVG detected
if fvgDetected and tfa.htfBarChanged(fvgTracker)
fvgBox := tfa.syncedBox(fvgTracker, 3, 1, fvgTop, fvgBot,
color.new(color.green, 85), color.green, 1, "FVG", color.white, true)
// Extend box to current bar each tick
if not na(fvgBox)
tfa.updateSyncedBox(fvgBox, true)
```
Example 2: HTF Support/Resistance Lines
```
//@version=6
indicator("HTF S/R Lines", overlay=true)
import ArunaReborn/TimeframeAlign/1 as tfa
htfInput = input.timeframe("240", "HTF for S/R")
// Create and update tracker
var tfa.HTFTracker srTracker = tfa.createTracker(htfInput)
tfa.updateTracker(srTracker, htfInput)
// Get HTF high/low (confirmed with offset)
= request.security(syminfo.tickerid, htfInput,
[high , low ], lookahead=barmerge.lookahead_off)
// Track lines
var tfa.SyncedLine resistanceLine = na
var tfa.SyncedLine supportLine = na
// Create new lines when HTF bar changes
if tfa.htfBarChanged(srTracker)
resistanceLine := tfa.syncedHLine(srTracker, 1, htfHigh, color.red, line.style_solid, 2, true)
supportLine := tfa.syncedHLine(srTracker, 1, htfLow, color.green, line.style_solid, 2, true)
// Auto-extend lines each bar
if not na(resistanceLine)
tfa.updateSyncedLine(resistanceLine, true)
if not na(supportLine)
tfa.updateSyncedLine(supportLine, true)
```
Example 3: Multiple Timeframes
```
//@version=6
indicator("Multi-TF Boxes", overlay=true)
import ArunaReborn/TimeframeAlign/1 as tfa
// Create separate tracker for each timeframe
var tfa.HTFTracker tracker1H = tfa.createTracker("60")
var tfa.HTFTracker tracker4H = tfa.createTracker("240")
var tfa.HTFTracker trackerD = tfa.createTracker("1D")
// Update ALL trackers every bar (pass the same TF string)
tfa.updateTracker(tracker1H, "60")
tfa.updateTracker(tracker4H, "240")
tfa.updateTracker(trackerD, "1D")
// Now use each tracker independently for drawing
// Each tracker maintains its own separate boundary history
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
NON-REPAINTING COMPLIANCE
To ensure non-repainting behavior, always use this pattern with request.security:
```
= request.security(syminfo.tickerid, htfTimeframe,
[value1 , value2 ], // Use offset for confirmed data
lookahead=barmerge.lookahead_off) // Never use lookahead_on
```
The ` ` offset ensures you're using the previous completed HTF bar, not the current forming bar.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
HISTORY DEPTH PARAMETER
The `historyDepth` parameter controls how many HTF bars are tracked:
• Default: 500 HTF bars
• Maximum: Limited by Pine Script's array constraints
• Higher values = more historical accuracy but more memory usage
• Lower values = less memory but may return `na` for older offsets
Adjust based on your needs:
```
tfa.updateTracker(tracker, 100) // Track 100 HTF bars (light)
tfa.updateTracker(tracker, 1000) // Track 1000 HTF bars (heavier)
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
IMPORTANT NOTES
1. One Tracker Per Timeframe : If you need multiple HTFs, create separate trackers for each. The convenience functions (htfBarStartIndex, htfBarEndIndex) only track one TF.
2. Update Every Bar : Always call updateTracker() unconditionally on every bar, not inside conditionals.
3. HTF Only : This library is designed for Higher Timeframe data. For LTF aggregation, use findBarAtTime() for time-based lookups.
4. Drawing Limits : Pine Script has limits on drawing objects. Use box.delete(), line.delete(), label.delete() to clean up old objects.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
TROUBLESHOOTING
Q: My boxes/lines still appear at wrong positions
A: Make sure you're calling updateTracker() on every bar (not inside an if statement) and using the correct htfOffset values.
Q: Functions return na
A: The htfOffset might be larger than available history. Increase historyDepth or use a smaller offset.
Q: Multiple timeframes don't work correctly
A: Don't use the convenience functions for multiple TFs. Create separate HTFTracker instances with createTracker() for each timeframe.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CHANGELOG
v1 - Initial release
• HTFTracker pattern for reliable multi-TF tracking
• Synced drawing functions for boxes, lines, labels
• Update functions for extending drawings
• Convenience functions for simple single-TF use cases
200W SMA Dynamic Extension Bands (MTF, Auto Asset)Summary
200W SMA Dynamic Extension Bands is a multi-timeframe TradingView indicator that plots extension bands (multiples) around the 200-week simple moving average. It’s designed to work on any chart timeframe (1m → 1D → 1W) while anchoring the bands to the latest confirmed weekly data, so the long-term reference is consistent and non-repainting across timeframes.
This is a macro “valuation/temperature gauge” style tool: it helps you quickly see when the price is cheap vs. the 200W mean and when it is extended/expensive.
What it plots
The indicator always computes:
200-week SMA (weekly)
Band m2
Band m3
Band m4
Bands are defined as:
Bandk(t)=SMA200W(t)⋅mk
Where the multipliers mk are chosen automatically depending on the asset type (or manually via input).
Key features
Works on any timeframe: weekly SMA is fetched via request.security(..., "W", ...).
Non-repainting weekly anchor: uses barmerge.lookahead_off to avoid peeking into future weekly bars.
Auto asset presets:
Crypto: wider extensions (bigger cycles)
Gold: moderate extensions
Equities: tighter than crypto
FX: very tight extensions
Futures: moderate fallback
Zone coloring (optional):
Cheap zone (below 1×)
Fair zone (1× → m2)
Hot zone (m2 → m3)
Expensive zone (m3 → m4)
Info table (optional): shows selected preset, current multiple, and % extension vs 200W SMA.
Alerts (optional): “entered cheap” and “entered expensive” style triggers.
Presets (default multipliers)
These are intentionally conservative templates (tune to your market):
Crypto: 1.0,1.5,2.0,3.0
Gold: 1.0,1.2,1.5,2.0
Equities: 1.0,1.15,1.30,1.60
FX: 1.0,1.05,1.10,1.20
Futures: 1.0,1.25,1.50,2.00
Auto mode uses syminfo.type plus a simple heuristic for Gold tickers containing XAU / GOLD (because some platforms classify XAUUSD as forex).
How to use (practical)
Macro context / cycle temperature
Price below 1× (200W SMA): historically “cheap zone” for highly cyclical assets (especially BTC).
Price above m3: often “expensive/extended” and higher risk of mean reversion.
Not a standalone trading system
Use with trend confirmation (market structure), volume, and risk management.
Extensions can persist in strong trends—treat bands as regime context, not precise reversal points.
Settings you can change
SMA Length (Weeks): default 200
Band preset: Auto / Crypto / Gold / Equities / FX / Futures
Toggle:
Zone fills
Info table
Alerts
Included alertconditions:
Cross below 1× (entered cheap zone)
Cross above m3 (entered expensive zone)
High level guideline:
Green Zone: BUY (Below 1.0× - Undervalued)
Yellow Zone: HOLD (1.0× - 1.5× - Fair Value)
Orange Zone: CAUTION (1.5× - 2.0× - Getting Hot)
Red Zone: SELL (2.0× - 3.0× - Overvalued)
Notes / limitations
The “cheap/expensive” zones are heuristics. They do not guarantee future returns.
Auto classification is best-effort; if your symbol is unusual, set the preset manually.
For newly listed assets with limited weekly history, the 200W SMA may be na until enough data exists.
Trinity 4 EMA MTF IndicatorThis is a 5mins scalping indicator based on the daily, 1hr, 15mins and 5 mins TF. Go long or short when all EMA are aligned.
EMA values and timeframe can be customized
EMA colors can also be customized
Evidenzia Data Specifica DinamicaSpecific Date Highlighter
Descrizione (Italiano)
Questo indicatore semplice ma estremamente efficace permette di evidenziare graficamente un'intera giornata specifica selezionata dall'utente. È lo strumento ideale per chi ha bisogno di analizzare il comportamento del prezzo durante eventi macroeconomici passati, date di earnings, o particolari sessioni storiche.
Caratteristiche principali:
Selettore Calendario Intuitivo: Grazie all'input di tipo time, puoi selezionare la data esatta tramite un calendario pop-up senza dover inserire manualmente numeri per giorno, mese e anno.
Compatibilità Multi-Timeframe: L'indicatore funziona su qualsiasi timeframe. Se sei su grafici intraday (1m, 5m, 1h), colorerà lo sfondo di tutte le candele appartenenti a quel giorno. Su grafici Daily, evidenzierà la singola candela selezionata.
Colore Personalizzabile: Puoi scegliere il colore dello sfondo e la sua opacità direttamente dalle impostazioni per adattarlo al tuo tema (Light o Dark).
Data Dinamica: Lo script è progettato per riconoscere automaticamente la data odierna come punto di partenza, facilitando l'analisi rapida dell'ultima sessione.
Casi d'uso:
Backtesting visivo: Evidenzia i giorni di rilascio dei dati CPI o decisioni FOMC per studiare la volatilità.
Journaling: Segna i giorni in cui hai effettuato trade importanti per ritrovarli facilmente nello storico.
Analisi Ciclica: Identifica rapidamente date specifiche in cui si sono verificati minimi o massimi storici.
Description (English)
This lightweight and effective tool allows you to highlight a specific full day on your chart. It is perfect for traders who need to visually isolate price action during macroeconomic events, earnings dates, or key historical sessions.
Key Features:
Calendar Picker: Easily select your target date using a built-in calendar input.
MTF Ready: Works seamlessly across all timeframes. On intraday charts, it highlights every bar within the 24-hour period. On daily charts, it highlights the specific daily candle.
Fully Customizable: Change the background color and transparency to match your chart layout.
Smart Default: The script is optimized to handle time logic correctly, ensuring the highlight starts exactly at 00:00 and ends at 23:59.
How to use: Go to settings, click on "Select Date", pick your day from the calendar, and the chart will instantly move the focus to that specific session.
Ale tonkis Swing failure + 5MIndicator Description: Ale Tonkis Swing Failure (SFP)
This script is an advanced Swing Failure Pattern (SFP) and Change in State of Delivery (CISD) indicator. It is designed to identify liquidity sweeps and market structure shifts across multiple timeframes simultaneously.
Key Features
Pivot Detection: Automatically identifies high and low pivot points based on a user-defined lookback period.
Liquidity Sweep Analysis: Detects when the price "sweeps" (goes beyond) a previous pivot high or low without closing significantly past it, signaling a potential reversal.
CISD (Change in State of Delivery): Tracks internal market structure shifts to confirm the SFP signal.
Multi-Timeframe (MTF) Dashboard: A real-time table in the top-right corner monitors the trend state across four different timeframes: M1, M3, M5, and M15.
Visual Alerts: The script uses dynamic bar coloring and labels (▲/▼) to signal entry points directly on the chart.
Technical Updates (M5 Integration)
The code has been specifically modified to include the 5-minute (M5) timeframe within the Multi-Timeframe logic:
Data Fetching: A new request.security call was added to retrieve the sfp_trend_state from the 5-minute interval.
Table Expansion: The display table was resized from 4 rows to 5 rows to accommodate the new data without overlapping.
UI Alignment: The M5 state is now positioned between M3 and M15, providing a smoother transition for traders analyzing mid-range scalping opportunities.
How to Read the Dashboard
LONG (Green): Indicates a bullish SFP has occurred and the trend remains positive on that timeframe.
SHORT (Red): Indicates a bearish SFP has occurred and the trend remains negative.
Empty/Black: No active SFP trend is currently detected on that specific timeframe.
CURRY HEDGEFUND PRO (MTF/VWAP/ADX + Tight Trail) [no ta.adx]Improved HedgeFund Pro Script by Tony Curry for momentum and reversal trading. Primarily focused on ADX and directional movement.
BB Scoreboard MTF1. The Concept: Harmony Across TimeframesThe Musical Score Visual: This indicator transforms absolute price into a relative "score" based on standard deviations ($\sigma$). It displays the positions of Short-Term (15m), Mid-Term (1H), and Long-Term (4H) prices on a single grid, similar to a musical staff.Syncing the "Breath" of the Market: By aligning three different timeframes, you can instantly see if the entire market is "breathing" in the same direction.
2. Trading Logic: The Power of ConvergencePerfect Order (Bullish): When the Short, Mid, and Long-term lines are all above the Middle (0) line, it indicates a strong, synchronized uptrend. This is the highest probability zone for "Buy on Dip" strategies.Perfect Order (Bearish): Conversely, when all lines are below the Middle line, the market is in a synchronized downtrend, making "Sell on Rally" the dominant strategy.Overextension (The Limits): When all three lines hit the $+3\sigma$ or $-3\sigma$ levels simultaneously, the market is extremely overextended, signaling an imminent correction or exhaustion.
3. Synergizing with "Volume-Wall" (FVG)To achieve the Ultimate Scalping Setup:Alignment: Wait for all three lines on the "Scoreboard" to point in the same direction (e.g., all above 0).The Anchor: Price returns to a Strong FVG (Volume-Wall).The Trigger: Enter the trade when the Short-term line bounces off a lower $\sigma$ level and heads back toward the $+1\sigma$ or $+2\sigma$ area.
Money Flow Index (MFI) w/ Multi Time Frame DivergencesBack color MTF
Money Flow Index (MFI) w/ Multi Time Frame Divergences
ATR + STRAT Dashboard (LAST + DIR + REV) + Est MovesATR + STRAT Dashboard is a multi-timeframe market structure indicator built around The Strat and ATR context. It summarizes higher-timeframe control (buyers vs sellers), highlights key Strat conditions (inside/outside/2-1-2 style transitions), and flags common reversal candles (hammer / shooting star style signals) to help spot potential turns. It also includes ATR-based context and estimated move guidance so you can quickly gauge whether price has “room” to run or is extended.
What it shows
MTF Dashboard: quick read of trend/control across multiple timeframes
Direction/Control: color-based bias (buyers vs sellers in charge)
Reversal Flags: highlights reversal-style candles for awareness (not guaranteed)
ATR Context + Estimated Moves: volatility-based framework for targets/expectations
Non-repainting HTF behavior: designed to use closed higher-timeframe bars to reduce repaint surprises
Note: This tool is for structure + context, not trade signals by itself. Always confirm with your plan/risk management.
Wave Dynamics - Neural Adaptive Engine🌊 WAVE DYNAMICS - NEURAL ADAPTIVE ENGINE
The Official Reference Manual & Trading Protocol
═════════════════════════════════════════════════════════════
📖 PREFACE: THE END OF STATIC ANALYSIS
The financial markets are not linear; they are fractal. They do not move in straight lines; they breathe. They expand in trending volatility and contract in chopping noise.
The fundamental failure of traditional technical analysis is Static Sensitivity .
• A 14-period RSI works beautifully in a range but fails in a trend.
• A 12,26 MACD captures trends but destroys capital in chop.
Wave Dynamics solves this by treating the market as a living organism. At its core is a Neural Adaptive Engine that calculates the Hurst Exponent (Fractal Dimension) in real-time. It measures the "roughness" of price action and automatically adjusts the lookback periods of every subsystem—Waves, Ribbons, and Oscillators—to match the current market regime.
This manual is your guide to navigating this adaptive framework.
PART 1: THEOLOGY & MARKET PHYSICS
To use this tool, you must understand the three pillars of its logic:
1. The Hurst Exponent (Chaos Theory)
The engine continuously calculates H (Hurst) on a rolling window.
• Persistent Regime (H > 0.5): "What is happening now is likely to continue." The market is trending. The Engine Tightens sensitivity to catch fast pullbacks.
• Anti-Persistent Regime (H < 0.5): "What is happening now is likely to reverse." The market is chopping/ranging. The Engine Widens sensitivity to filter out noise and stop runs.
2. The Elliott Wave Cycle (Crowd Psychology)
Price moves in 5-wave motive sequences followed by corrections.
• Waves 1 & 3: Institutional Accumulation/Mark-up.
• Waves 2 & 4: Profit Taking (The Pullback). These are the only safe entry points.
• Wave 5: Retail FOMO (The Trap). Identified by Momentum Divergence .
3. Smart Money Concepts (Liquidity)
Price moves from liquidity to liquidity.
• Order Blocks: Where institutions initiated the move.
• Breakers: Where institutions trapped traders (Support flips to Resistance).
• Fair Value Gaps: Where price moved too fast, leaving inefficiency.
PART 2: VISUAL INTELLIGENCE (COLOR THEORY)
The chart communicates instantly through a strict color-coded language.
🎨 THE RIBBON (Adaptive Equilibrium)
The background "Cloud" is an Adaptive EMA ribbon.
• Neon Green (#00FF88): Bullish Trend. Only look for Longs. Price is above the equilibrium mean.
• Neon Red (#FF3366): Bearish Trend. Only look for Shorts. Price is below the equilibrium mean.
• Grey/Narrow: Compression. The market is deciding. Do not trade inside a grey ribbon.
🎨 INSTITUTIONAL ZONES
• Green/Red Boxes (Order Blocks): Standard Support/Resistance. Valid entry zones, but lower probability.
• Vivid Purple Boxes (#9C27B0) - THE BREAKER: CRITICAL. This appears when a Green Order Block is smashed through by price. It turns Purple to signify it has flipped from Support to Resistance (or vice versa). A retest of a Purple Zone is the highest probability setup in the system.
• Dotted Outlines (FVG): Magnets. Do not place stops inside these; price will likely travel through them.
🎨 WAVE ANATOMY
• Cyan Lines: Valid Impulse Waves (1, 3, 5).
• Orange Lines/Dots: EXHAUSTION. If a wave line turns Orange, Angular Momentum is decaying. The trend is dying.
• Diamonds (◆): DIVERGENCE. Price made a Higher High, but the internal oscillator (MPI) made a Lower Low. Immediate reversal warning.
🎨 SIGNALS
• Triangles: Confirmed Entries. (Green = Long, Red = Short).
• Labels (e.g., A+): The Grade of the trade based on Confluence.
• A+: Perfect Confluence (Trend + Structure + Zone + Momentum).
• C: Counter-trend or Weak.
PART 3: THE DASHBOARD ECOSYSTEM
Three panels provide Total Situational Awareness. You must read them in order: Top Right → Bottom Left → Bottom Right.
1. MISSION CONTROL (Top Right)
This panel tells you the "Weather Report."
• Neural Status:
• 🧠 TREND: Safe to trade breakout and trend-following strategies.
• 🧠 CHOP: Danger. Use mean-reversion or stay out.
• 🧠 RND (Random): No clear edge.
• Phase: Displays the Bias (Bull/Bear) and Strength. "WEAK BEARISH" usually signals a bottom is forming.
• Score Bar: A live visual meter of the Confluence Score (0-100%).
2. THE ASSISTANT (Bottom Left)
This panel acts as your co-pilot, translating data into English.
• Situation:
• "💎 BULL GEM": You are in a range, at the bottom, showing exhaustion. Buy immediately.
• "🔥 COMPRESSION": Volatility squeeze. A violent move is imminent.
• Action: Tells you exactly what to do (e.g., "Wait for confluence," "Trail Stop," "Let it develop").
• Pro Metrics (Simulated):
• Win Rate: The percentage of signals on the current visible chart that hit Target 1.
• Profit Factor: Gross Win / Gross Loss. If this is < 1.0, stop trading this asset immediately.
• Buckets: Shows the win rate of A-Grade signals vs. C-Grade signals.
3. WAVE INTELLIGENCE (Bottom Right)
This panel provides structural context.
• Channel Gauge (0-100%):
• 0-20%: Oversold / Channel Bottom.
• 80-100%: Overbought / Channel Top.
• 50%: Equilibrium.
• W3/W1 Ratio: The "Health Check" of the trend.
• < 1.0: Weak. Wave 3 is shorter than Wave 1. The trend is struggling.
• > 1.618: Extended. The move is parabolic. Expect a snap-back.
• Trend Health (0-100): Composite score of sub-wave physics. If Health < 30, the trend is effectively dead.
PART 4: PARAMETER OPTIMIZATION (THE INPUTS)
Every input allows you to tune the engine. Here is the deep dive:
🧠 NEURAL ADAPTIVE ENGINE
• Enable Neural Adaptive Engine: Master switch for the Hurst calculation.
• Hurst Period (100):
• Adjustment: Increase to 200 for Crypto/Alts (too much noise). Decrease to 50 for
Forex/Indices (need speed).
• How to tell: If the dashboard says "TREND" but the chart is sideways, INCREASE this value.
• Min/Max Lookback: Defines the constraints. Only adjust if you are an advanced user creating a custom scalping setup (e.g., Min 3 / Max 10).
🌊 WAVE & STRUCTURE
• Base Swing Detection (8): The "Anchor."
• Scalpers (1m-5m): Set to 5-8.
• Swing Traders (1H-4H): Set to 15-20.
• Min Wave Size (ATR): Prevents the script from labeling tiny wicks as waves. Increase this during high-volatility news events.
🔗 MTF STRUCTURE MAPPING
• Require Macro Align: Strict Mode. If enabled, the script checks the Higher Timeframe (e.g., 4H). If 4H is Bearish, it BLOCKS all Long signals on the 5m chart. Use this to prevent counter-trend losses.
🏦 SMART MONEY CONCEPTS
• Enable Breakers: ALWAYS ON. This turns failed Order Blocks into Breaker Zones (Purple).
• Institutional Mode: ULTRA STRICT. If enabled, signals will ONLY fire if price is physically touching an Order Block, FVG, or Breaker. This creates very few, very high-quality signals.
🎯 SIGNAL ENGINE
• Signal Mode:
• Strict: Grades A+ and A only.
• Balanced: Grades B and above.
• Aggressive: Includes counter-trend scalps (Grade C).
• Min Confluence Score (5-35): The raw points needed to trigger. 5 is standard. 10 is conservative.
PART 5: TRADE EXECUTION PLAYBOOKS
PLAYBOOK A: THE "BREAKER RETEST" (Highest Probability)
1. Context: Ribbon is Green.
2. Event: Price creates a Red Order Block, then smashes upward through it.
3. Change: The Red Block turns Purple (Bullish Breaker).
4. Trigger: Price pulls back down to touch the top of the Purple Box.
5. Signal: Green Triangle appears.
6. Action: Max Size Entry. Stop Loss below the Purple Box. Target Wave 3 Projection.
PLAYBOOK B: THE "WAVE 4 DIP" (Trend Following)
1. Context: Wave count shows "3". Ribbon is Green.
2. Event: Price pulls back towards the Ribbon.
3. Wave Panel: Wave count flips to "4".
4. Trigger: Price touches Ribbon, prints Green Triangle.
5. Action: Standard Size Entry. Stop Loss at Swing Low. Target New High (Wave 5).
PLAYBOOK C: THE "HIDDEN GEM" (Range Reversal)
1. Context: Ribbon is Grey (Consolidation). Neural Status is CHOP.
2. Wave Panel: Channel Gauge is < 10% (Extreme Bottom).
3. Visuals: Orange Exhaustion Dot + Divergence Diamond (◆).
4. Assistant: Reads "💎 BULL GEM".
5. Action: Half Size Entry. This is a counter-trend trade. Target the middle of the range (50% Channel).
PLAYBOOK D: THE "BULL TRAP" (When to Fold)
1. Context: Wave Count is "5".
2. Wave Panel: Trend Health < 30. W3/W1 Ratio > 1.618 (Extended).
3. Visuals: Orange Line appears on price high.
4. Signal: Green Triangle appears (Grade C).
5. Action: NO TRADE. The system is warning you that even though a signal fired, the structural physics indicate exhaustion.
PART 6: GRADING & SCORING MATRIX
Every signal is graded on a 35-point scale. Know what you are buying.
• Trend Alignment (5 pts): Ribbon & HTF agreement.
• Structure (5 pts): BOS (Break of Structure) & Higher Highs.
• Physics (5 pts): MPI (Volume Flow) & Angular Velocity.
• Institutional Location (10 pts):
• Inside Order Block: +3 pts
• Inside Breaker: +4 pts
• Wave 2/4 Pullback: +3 pts
• Penalty: Wave 5 Extension (-3 pts).
Grade Scale:
• A+ (Score ≥ 70%): "All In" Setup.
• A (Score 55-69%): Strong Setup.
• B (Score 40-54%): Standard Setup.
• C (Score < 40%): Dangerous.
PART 7: RISK DISCLOSURE & LIMITATIONS
1. The Reality of Adaptation (Redrawing):
The Neural Engine is dynamic. As new data arrives, the calculation of "Chaos" changes. This means historical channel lines or wave labels may shift to fit the matured trend. HOWEVER: Entry Signals (Triangles) NEVER repaint once the bar is closed.
2. Simulation vs. Reality:
The Dashboard metrics (Win Rate, Profit Factor) are Simulations run on the historical data visible on your chart. They do not account for spread, slippage, or liquidity. They are a tool to gauge the current market personality, not a promise of future returns.
3. No Financial Advice:
Wave Dynamics is a tool for structural analysis. It helps you see the market, but it cannot trade for you. You are responsible for your own risk management.
CLOSING THOUGHTS
Wave Dynamics is not just an indicator; it is a lens. It allows you to see the market not as a random walk of candles, but as a structured, breathing entity.
Trust the Neural Status. Respect the Breakers. Fear the Exhaustion.
Taking you to school. — Dskyz, Trade with insight. Trade with anticipation.
Volume-Weighted FVG (Fixed)1. The Core Concept: Identifying "Institutional Footprints"
FVG (Fair Value Gap): These are "gaps" or "voids" in price created by rapid movement. The market has a natural tendency to return and "fill" these gaps.
The Volume Filter: Unlike standard FVGs, this tool highlights zones created with high trading volume (Strong FVG). These represent the "footprints" of institutional traders—the "Big Money" that truly moves the market.
2. Trading the "Wall": Rejection and Reversal
The Rejection (Bounce): A Strong FVG acts as a powerful "wall." When price returns to this zone, unfilled orders often trigger, causing the price to bounce back (reject).
The Reversal (Breakout): If this "wall" is completely breached, it triggers a cascade of stop-losses from those who bet on the bounce. This results in a violent move in the opposite direction, known as a reversal.
The Retest: Once a "wall" is broken, its role flips (e.g., support becomes resistance). Trading the first retest of a broken Strong FVG is one of the highest-probability setups in scalping.
3. The Execution: High-Precision Entry
To achieve a Profit Factor (PF) of 5.0+, we combine three elements:
Structure: Confirm the trend using Multi-Timeframe (MTF) HH/HL (Higher Highs/Higher Lows).
The Zone: Price enters a Strong FVG (Darker color).
The Trigger: Enter when an Engulfing Candle breaks through the BB20 Middle Line, confirmed by an RCI 9 reversal.
Heikin Ashi SMA 9 / 20 / 50 (MTF + Selectable Source)This is simple Heikin ashi value three moving average as 9 / 20 / 50 for clear trend identification . use it wisely with other confirmation .
4H Session High/Low4H Asia Session Anchor Range Description: This indicator identifies and plots the price range of the specific 4-hour candle starting at 04:00 (local time). By utilizing Multi-Timeframe (MTF) logic, the high and low boundaries (wick-to-wick) remain fixed and accurate even when scaling down to lower timeframes like the 1-minute or 5-minute charts. The levels extend horizontally to the right, providing clear institutional support and resistance zones based on the early morning volatility.
RSI MTF Table (Threshold Colors + Direction Arrows) [v6]Sometimes I want to know what other timeframes are indicating for the RSI so I borrowed from another indicator and created this script. Since I swing trade, I have the timeframes set higher, but you can adjust them to your needs in the settings.
Each pane is color coded light green below 50, and pink above 50. Then you can define your own thresholds but the defaults are Red above 70, and Dark Green below 30. The colors can be adjusted to your needs.
The top of each pane is its timeframe, then the RSI value for that timeframe. Then I check the current bar against the prior bar to see if the current value is higher (Up Arrow) or lower (Down Arrow) so that you know which way the RSI is moving. The position on your chart can be changed to your needs.
This keeps the momentum in perspective for me. I hope it helps you. Good luck in your trading.
Pulsar Heatmap CVD/OBV [by Oberlunar]Pulsar Heatmap CVD/OBV is a flow/price-consensus dashboard that turns OBV, CVD and their combination blend into a compact “heatmap + bias/signal” view, with optional main-chart candle coloring and HUD overlays.
What it shows
The panel is split into 3 horizontal lanes (OBV / CVD / COMBO). Each lane is further split into two halves:
Flow half: the normalized OBV/CVD/COMBO component (either per-bar Delta or Cumulative series).
PriceΔ half: the normalized divergence between price and the lane (price unit − flow unit), highlighting when price moves with or against the flow proxy.
Colors use intensity-based transparency so you can quickly spot pressure, compression, and disagreement between lanes.
Core engines
Normalization: Z-Score→tanh, Z-Score→clamp, MinMax, or None (unit range ≈ ).
Bias engine (6 halves): builds a directional BIAS from the six components (OBV/CVD/COMBO × Flow/PriceΔ), with optional hysteresis to reduce flicker.
Signal engine: triggers LONG/SHORT only on full alignment (all 6 halves agree), with confirm-bars and optional sticky behavior.
ROC/Acceleration layers: optional impulse context (ROC + ACC) to gate signals and/or boost bias strength when momentum is supportive.
AST filter: a strict directional filter combining volatility regime, BB expansion/contraction, MTF RSI prior and Kalman-smoothed evidence. When AST is directional, it can block opposite signals to enforce coherence.
Visual tools
Bias/Signal bands: top/bottom bands render BIAS strength and SIGNAL state; yellow highlights indicate disagreement/blocked states.
Candle colouring (main chart): optionally colours chart candles from LaneScore / Bias / Signal / Bias+Signal (uses overlay drawing where supported).
Signal labels: optional LONG/SHORT markers (with “better price than last shown” logic).
Triangle HUD: right-side geometric HUD summarising OBV/CVD/COMBO consensus + disagreement cues.
Timed Exhaustion / Absorption table: compact state machine that flags momentum exhaustion and absorption-like conditions using tight range + ROC/ACC behaviour.
How to use
Start with Lane data = Delta for faster microstructure timing; switch to Cumulative for macro context.
Choose a normalisation that fits your symbol’s volatility (ZScore→tanh is usually stable).
Read BIAS as the current dominant direction/strength; treat SIGNAL as the strict “all lanes aligned” confirmation.
If you want stricter coherence, keep the AST filter enabled (it is integrated by design and blocks opposite-direction signals when directional).
Setup 1 — Long Signal (Clean Alignment + Impulse)
In this example, Pulsar Heatmap transitions into a clear long setup when the system prints a LONG SIGNAL. The key idea is simple: the indicator does not enter on “bias” alone. It waits for full alignment across the internal lanes, optionally reinforced by the ROC/Acceleration impulse layer, and only then does it confirm a signal on a closed bar (Safe Mode)
Setup 2 — Short Signal After Compression (Absorption → Release)
In this screenshot, the short trade idea is not coming from “red candles” alone, but from a very specific sequence: the heatmap shows a shift into bearish alignment, the system prints a SHORT SIGNAL, and the timed module confirms that the market was in a tight range while sell pressure started to dominate.
Setup 3 — Neutral State (Stand-By Zone, No Trade Yet)
In the following screenshot, Pulsar Heatmap is doing something very important: it is clearly saying NEUTRAL 0%. Even if, visually, price could “look” like it might resume upward, the indicator is not providing a directional edge yet.
If you are already short, treat DISAGREE as a signal to take profit, tighten the stop, or scale out.
Setup 4 — When similar conditions return
Setup 4 — Impulse + Exhaustion conditions
In this screenshot, you’re basically seeing a “timing warning” configuration. Price prints a sharp bearish extension, but Pulsar Heatmap is not presenting it as a clean continuation setup: the center read is NEUTRAL 0%, while the timed engine shows both Absorption = SHORT and Exhaustion = SHORT. That combination often means: the downside pressure was real, but the move is already in a late/fragile phase (good for managing an existing short, not for opening a new one).
This tool uses available volume data from your data provider and approximates flow via OBV/CVD-style logic; results can differ across symbols/brokers and sessions. This script is for educational/analytical purposes and is not financial advice.
by Oberlunar 👁️ ⭐
Daily/Weekly FVG by KrisThis indicator is a Multi-Timeframe (MTF) tool designed to automatically identify and project Fair Value Gaps (Imbalances) from Daily and Weekly timeframes onto your current chart. It helps traders locate higher-timeframe Areas of Interest (POI) and liquidity voids without manually switching charts.
How it works:
The script utilizes `request.security` to fetch High and Low data from Daily and Weekly timeframes. It identifies a Fair Value Gap (FVG) based on the 3-candle formation logic where price moves inefficiently, leaving a gap between the wicks.
- Bullish FVG: Identified when the current Daily/Weekly Low is greater than the High of the candle from 2 periods ago.
- Bearish FVG: Identified when the current Daily/Weekly High is lower than the Low of the candle from 2 periods ago.
The indicator draws a box extending to the right to visualize the zone, along with a dotted midline which often acts as a sensitive support/resistance level.
Unique Feature: Smart Mitigation (Auto-Hide)
To keep your chart clean and focused on relevant data, the script includes a "Full Fill" logic. It continuously monitors price action relative to existing FVG boxes.
- If price completely crosses through a box (fully fills the gap), the indicator considers it "mitigated" and automatically hides the box and its midline (sets transparency to 100%).
- This ensures you only see "fresh" or unfilled gaps that are still relevant for trading.
Settings:
- TF Checkboxes (Daily/Weekly FVG): Toggle the visibility of Daily or Weekly gaps independently based on your analysis needs.
- Design Mode:
Colored: Uses classic Green (Bullish) and Red (Bearish) colors for easy trend identification.
Monochrome: Uses Gray tones for a minimalist look that reduces visual noise on the chart.
Usage:
Use these zones to identify potential reversal points or liquidity targets. Since these are higher-timeframe levels, they often carry more weight than intraday imbalances.
Ultra-Compact MTF EMAsimple indicator which shows you the trend on other timeframes. fully customizable






















