← К каталогу
Исходный код · ID 4206

Luxy UT GOD - UT-BOT Forecast

indicator_luxy_ut_god_mode_ut_bot_forecast,_signals,_zones_and_risk.pine

Похожие материалы по тегам

ares_indicator.pineTradingView · 1 общих теговgold_trend_revers.mq5MQL5 / MetaTrader 5 · 1 общих тегов!!!-mt4 x-xardg-rsi.mq5MQL5 / MetaTrader 5 · 1 общих тегов! cycle-identifier.mq5MQL5 / MetaTrader 5 · 1 общих тегов!!! rsi ma simple+arrows 1.2 (mtf).mq5MQL5 / MetaTrader 5 · 1 общих теговprecisionflowea.mq5MQL5 / MetaTrader 5 · 1 общих тегов
Вы автор или правообладатель?

Сообщите нам, если считаете, что материал размещён без разрешения.

Краткий обзор

О программе

Это индикатор для TradingView, написанный на Pine Script v6 и предназначенный для отображения на графике сигналов Buy/Sell, линий скользящего стопа, уровней стоп-лосса и тейк-профита, а также информационной панели. Индикатор не является торговым советником и не совершает сделок; он только визуализирует расчётные уровни и условия.

В основе лежит расчёт трейлинг-стопа на основе ATR с адаптацией к волатильности и типу актива. Сигналы фильтруются набором условий: режим ADX, кулдаун, подтверждение по барам, фильтры волатильности, объёма, RSI, Hull MA, SuperTrend, зоны поддержки/сопротивления, а также подтверждение по старшему таймфрейму. Дополнительно отображаются дивергенции RSI и прогноз длительности тренда на основе исторических данных.

Индикатор предоставляет множество пользовательских настроек для управления отображением, фильтрами, расчётом стоп-лосса и тейк-профита, а также калькулятором риска. Все расчёты выполняются на стороне TradingView, оповещения формируются через alertcondition и alert.

Настройки программы

НастройкаОписание
utShowLabels Показывает метки Buy/Sell на графике.
labelSizeStr Размер меток на графике.
utShowLine Показывает линию трейлинг-стопа UT.
utShowRibbon Показывает градиентную заливку между ценой и линией UT.
utColorBars Окрашивает бары в зависимости от направления тренда.
i_showTable Показывает информационную таблицу на графике.
i_tablePos Позиция таблицы на графике.
i_tableSize Размер текста таблицы.
utAtrPeriod Период ATR для расчёта трейлинг-стопа.
i_enableLayer1 Включает фильтр Anti-Whipsaw на основе ADX.
i_adxPeriod Период расчёта ADX для определения режима тренда.
i_adxThreshold Порог ADX, выше которого рынок считается трендовым.
i_cooldownBars Минимальное количество баров между сигналами.
i_confirmBars Количество баров для подтверждения направления тренда.
i_assetType Тип актива для автоматической или ручной настройки множителя чувствительности.
i_adaptiveMode Режим адаптации ключевого значения к волатильности: Fixed (без адаптации), Dynamic (умеренная), Aggressive (широкая).
i_useVolatility Включает фильтр высокой волатильности.
i_volLookback Период для расчёта среднего ATR при фильтре волатильности.
i_volThresh Порог отношения текущего ATR к среднему для фильтра волатильности.
utUseSwingFilter Включает фильтр свинг-структуры.
swingLen Период поиска свинг-максимумов и минимумов.
utUsePctFilter Включает фильтр минимального процентного изменения.
utPctThr Минимальное процентное изменение между барами для фильтра.
utUseDelay Требует 2 последовательных бара для подтверждения направления.
i_useVolFilter Включает фильтр объёма.
i_volSmaLen Период SMA для среднего объёма.
i_volThreshold Порог отношения объёма к среднему для фильтра объёма.
i_useRsiFilter Включает фильтр RSI.
i_rsiLen Период RSI для фильтра.
i_rsiOB Уровень перекупленности RSI, выше которого блокируются покупки.
i_rsiOS Уровень перепроданности RSI, ниже которого блокируются продажи.
i_useHullConfirm Включает подтверждение по Hull MA.
i_hullPeriod Период Hull MA для подтверждения направления.
i_useSuperTrend Включает фильтр SuperTrend.
i_stAtrPeriod Период ATR для расчёта SuperTrend.
i_stMult Множитель ATR для SuperTrend.
i_showStLine Показывает линию SuperTrend на графике.
i_useFullCandle Требует, чтобы вся свеча находилась выше или ниже линии UT.
utShowZones Показывает зоны поддержки и сопротивления на графике.
i_useZoneFilter Блокирует покупки в зоне сопротивления и продажи в зоне поддержки.
i_zoneWidthMult Ширина зоны как множитель ATR.
i_zonePivotLen Количество баров для подтверждения пивота при построении зон.
entryShow Показывает линию входа на графике.
linesLimit10 Ограничивает линии SL, TP и Entry 10 барами.
slShow Показывает линию стоп-лосса на графике.
slMethod Метод расчёта стоп-лосса: ATR, процент, тики, свинг, масштабированный ATR, Smart Adaptive, Safer.
tpDisplayMode Стиль отображения тейк-профитов: Minimal или Detailed.
tpFreezeOnTouch Замораживает линии тейк-профита при касании.
slAtrLen Период ATR для расчёта стоп-лосса.
slAtrMult Множитель ATR для расчёта стоп-лосса.
slPctStop Процент от цены входа для стоп-лосса.
slTickStop Количество тиков от цены входа для стоп-лосса.
slExtraTicks Дополнительные тики буфера за расчётным стоп-лоссом.
tpShow Показывает линии тейк-профита на графике.
tp1On Включает уровень тейк-профита 1R.
tp15On Включает уровень тейк-профита 1.5R.
tp2On Включает уровень тейк-профита 2R.
tp3On Включает уровень тейк-профита 3R.
i_useMTF Включает подтверждение по старшему таймфрейму.
i_mtfTimeframe Старший таймфрейм для подтверждения сигналов.
i_statsLookback Количество дней для сбора статистики сделок.
i_showDivergence Показывает дивергенции RSI на графике.
i_divRsiLen Период RSI для расчёта дивергенции.
i_divLookback Количество баров для подтверждения пивота при поиске дивергенции.
i_showRisk Показывает калькулятор риска в таблице.
i_riskMode Режим расчёта риска: процент от счёта или фиксированная сумма.
i_riskPct Процент от счёта для риска на сделку.
i_riskFixed Фиксированная сумма риска на сделку при режиме Fixed Amount.
i_useLiveRates Использовать живые курсы валют для калькулятора риска.
i_manualRate Ручной обменный курс для калькулятора риска.
i_enablePrediction Включает прогноз длительности тренда на основе исторических данных.
i_predMode Режим прогноза: Simple, Standard, Advanced.
i_predSamples Количество прошлых трендов для анализа при прогнозе.
i_showPredBoxes Показывает градиентные блоки прогноза длительности тренда.
i_showPredLabels Показывает метки вероятности на прогнозе.
Получить полный код

Поиск по коду файла

indicator("Luxy UT GOD - UT-BOT Forecast", shorttitle="Luxy UT God Mode", overlay=true, max_bars_back=5000, max_lines_count=500, max_labels_count=500, max_boxes_count=500)

GROUP_UT      = "================== UT Bot Settings =================="
GROUP_L1      = "🛡️ Anti-Whipsaw (Regime) ___________________________"
GROUP_FILTERS = "🎯 Signal Filters __________________________________"
GROUP_SL      = "💵 Stoploss and Take Profit_________________________"
GROUP_L2      = "🔄 Adaptive Parameters _____________________________"
GROUP_L3      = "📈 MTF Confirmation ________________________________"
GROUP_CALC    = "🔢 Risk Calculator _________________________________"
GROUP_PRED    = "🔮 Trend Prediction ________________________________"

const float TP1   = 1.0
const float TP1_5 = 1.5
const float TP2   = 2.0
const float TP3   = 3.0

const string ASSET_AUTO    = "Auto-Detect"
const string ASSET_STOCK   = "Stock"
const string ASSET_CRYPTO  = "Crypto"
const string ASSET_FOREX   = "Forex"
const string ASSET_FUTURES = "Futures"
const string ASSET_INDEX   = "Index"
const string ASSET_FUND    = "Fund/ETF"
const string ASSET_CFD     = "CFD"
const string ASSET_BOND    = "Bond"

const string ADAPT_FIXED      = "Fixed"
const string ADAPT_DYNAMIC    = "Dynamic"
const string ADAPT_AGGRESSIVE = "Aggressive"

const string MTF_AUTO   = "Auto (×4)"
const string MTF_5M     = "5m"
const string MTF_15M    = "15m"
const string MTF_30M    = "30m"
const string MTF_1H     = "1H"
const string MTF_4H     = "4H"
const string MTF_D      = "D"
const string MTF_W      = "W"

utShowLabels = input.bool(true,  "Buy/Sell Labels", group=GROUP_UT, inline="ut2")
labelSizeStr = input.string("Small", "| Size", options=["Tiny", "Small", "Normal", "Large"], group=GROUP_UT, inline="ut2", tooltip = "Size of all labels on chart\n• Tiny: Minimal\n• Small: Default ⭐\n• Normal: Medium\n• Large: Easy to see")
utShowLine   = input.bool(false, "UT Line",         group=GROUP_UT, inline="ut3")
utShowRibbon = input.bool(false, "Ribbon Fill",     group=GROUP_UT, inline="ut3", tooltip = "Buy/Sell Labels: Show BUY/SELL signals on chart\nUT Line: Plot the ATR trailing stop line\nColor Bars: Aqua=bullish, Orange=bearish\nRibbon Fill: Gradient fill between price and UT line")
utColorBars  = input.bool(false, "Color Bars",      group=GROUP_UT, inline="ut3")

i_showTable     = input.bool(true, "Show Table", group=GROUP_UT, inline="tb1")
i_tablePos      = input.string("Top Right", "Position", options=["Top Left", "Top Right", "Bottom Left", "Bottom Right"], group=GROUP_UT, inline="tb1")
i_tableSize     = input.string("Normal", "Size", options=["Tiny", "Small", "Normal", "Large"], group=GROUP_UT, inline="tb1", tooltip = "Table text size\n• Tiny: Minimal footprint\n• Small: Balanced ⭐\n• Normal: Easy to read")

utKey        = input.float(1.2,  "Sensitivity",  group=GROUP_UT, step=0.1, minval=0.1, inline="ut1")
utAtrPeriod  = input.int(7,      "/ ATR Period", group=GROUP_UT, minval=1, inline="ut1", tooltip = "SENSITIVITY (Key × ATR):\nMultiplier for trailing stop distance\n• Higher = wider stop, fewer flips\n• Lower = tighter stop, more signals\n\nATR PERIOD:\nLookback for volatility\n\nPRESETS:\n• Scalp (1-5m): Key 0.9-1.2, ATR 5-7\n• Intraday (5-15m): Key 1.3-1.6, ATR 7-10 ⭐\n• Swing (D/W): Key 1.7-2.2, ATR 10-14")

labelSize = switch labelSizeStr
    "Tiny"   => size.tiny
    "Small"  => size.small
    "Normal" => size.normal
    "Large"  => size.large
    => size.small

i_enableLayer1  = input.bool(true,  "Enable Anti-Whipsaw", group=GROUP_L1, inline="L1a", tooltip = "Master switch for Anti-Whipsaw filter\n\nWhen ON: Signals filtered by ADX regime\nWhen OFF: All UT signals pass through")
i_adxPeriod     = input.int(14,     "ADX",       minval=5,  maxval=50, group=GROUP_L1, inline="L1b")
i_adxThreshold  = input.int(20,     "/ Thresh",  minval=10, maxval=40, group=GROUP_L1, inline="L1b", tooltip = "ADX PERIOD: Lookback for calculation\n• 10-14: Responsive ⭐\n• 20+: Smoother\n\nTHRESHOLD: Min ADX for 'trending'\n• < Threshold = Choppy (signals blocked)\n• >= Threshold = Trending (signals allowed)\n• 20-25: Typical ⭐")
i_cooldownBars  = input.int(3,      "Cooldown",  minval=0,  maxval=20, group=GROUP_L1, inline="L1c")
i_confirmBars   = input.int(1,      "/ Confirm", minval=1,  maxval=5,  group=GROUP_L1, inline="L1c", tooltip = "COOLDOWN: Min bars between signals\n• 0 = Disabled\n• 2-5 = Typical ⭐\n• Prevents rapid flip-flop\n\nCONFIRM: Bars to confirm direction\n• 1 = Immediate ⭐\n• 2-3 = Conservative")

i_assetType = input.string(ASSET_AUTO, "Asset Type", options=[ASSET_AUTO, ASSET_STOCK, ASSET_CRYPTO, ASSET_FOREX, ASSET_FUTURES, ASSET_INDEX, ASSET_FUND, ASSET_CFD, ASSET_BOND], group=GROUP_L2, inline="L2a")
i_adaptiveMode = input.string(ADAPT_DYNAMIC, "| Adaptive Mode", options=[ADAPT_FIXED, ADAPT_DYNAMIC, ADAPT_AGGRESSIVE], group=GROUP_L2, inline="L2a", tooltip = "ASSET TYPE:\nAffects sensitivity multipliers for Key Value\n\n• Auto-Detect: Identifies based on symbol ⭐\n• Stock: Standard (1.0×)\n• Crypto: Wider stops (1.5×) - high volatility\n• Forex: Tighter stops (0.8×) - low volatility\n• Futures: Moderate (1.2×)\n• Index: Slightly tighter (0.9×)\n• Fund/ETF: Slightly tighter (0.9×)\n• CFD: Standard (1.0×)\n• Bond: Much tighter (0.5×) - low volatility\n\n" + "ADAPTIVE MODE:\nHow Key Value adjusts to market volatility\n\n• Fixed: Use input values as-is (no auto-adjustment)\n• Dynamic: Auto-adjust based on volatility ⭐\n  - Low vol (< 0.8×): Key × 0.85\n  - Normal (0.8-1.2×): Key × 1.0\n  - High vol (> 1.2×): Key × 1.15\n• Aggressive: Wider adjustments\n  - Low vol: Key × 0.7\n  - High vol: Key × 1.3")

i_useVolatility = input.bool(false, "High Vol Filter", group=GROUP_FILTERS, inline="L1d")
i_volLookback   = input.int(50,     "/ Lookback", minval=10, maxval=200, group=GROUP_FILTERS, inline="L1d")
i_volThresh     = input.float(1.2,  "× Avg",   minval=1.0, maxval=3.0, step=0.1, group=GROUP_FILTERS, inline="L1d", tooltip = "HIGH VOLATILITY FILTER:\nDetects when current ATR is above average\n\nLOOKBACK: Bars to calculate average ATR\n• 50: Standard ⭐\n• 100+: Smoother\n\nTHRESHOLD:\n• 1.2×: Slightly elevated ⭐\n• 1.5×: High volatility\n• 2.0×: Extreme volatility\n\nWhen ON: Only allow signals in high volatility")
utUseSwingFilter= input.bool(true,  "Swing Filter", group=GROUP_FILTERS, inline="sf1")
swingLen        = input.int(8,      "/ Lookback",   group=GROUP_FILTERS, minval=1, inline="sf1", tooltip = "SWING FILTER:\nOnly signals aligned with swing structure\n\nLOOKBACK: Bars to find swing high/low\n• 5-10: Scalp/Day trading ⭐\n• 10-20: Swing trading")
utUsePctFilter  = input.bool(false, "% Filter", group=GROUP_FILTERS, inline="sf2")
utPctThr        = input.float(0.05, "/ Min %",  group=GROUP_FILTERS, step=0.05, minval=0, inline="sf2", tooltip = "% CHANGE FILTER:\nRequire minimum bar-to-bar % change\n\nMIN %: Threshold in percent\n• 0.1-0.5%: Intraday\n• 0.3-1.0%: Swing")
utUseDelay      = input.bool(false, "2-Bar Confirm", group=GROUP_FILTERS, inline="sf3", tooltip = "Require 2 consecutive bars to confirm trend direction\n\n• Reduces false signals\n• Adds slight lag\n• Good for volatile markets")
i_useVolFilter  = input.bool(false, "Volume Filter", group=GROUP_FILTERS, inline="sf4")
i_volSmaLen     = input.int(20,     "/ SMA",   minval=5,  maxval=100, group=GROUP_FILTERS, inline="sf4")
i_volThreshold  = input.float(1.0,  "× Avg",   minval=0.5, maxval=3.0, step=0.1, group=GROUP_FILTERS, inline="sf4", tooltip = "Require volume above average to confirm signals\n\nSMA: Lookback period for average volume\n• 20: Standard ⭐\n\nTHRESHOLD:\n• 0.8×: Relaxed\n• 1.0×: Above average ⭐\n• 1.5×: Strong volume required")
i_useRsiFilter  = input.bool(false, "RSI Filter",    group=GROUP_FILTERS, inline="sf5")
i_rsiLen        = input.int(14,     "/ Len",   minval=5,  maxval=50,  group=GROUP_FILTERS, inline="sf5", tooltip = "RSI MOMENTUM FILTER:\nConfirm signals with RSI direction\n\nLEN: RSI period (14 standard ⭐)")
i_rsiOB         = input.int(70,     "Overbought",      minval=60, maxval=90,  group=GROUP_FILTERS, inline="sf9")
i_rsiOS         = input.int(30,     "Oversold",      minval=10, maxval=40,  group=GROUP_FILTERS, inline="sf9", tooltip = "Overbought: Block BUY above this\n• 70: Standard ⭐\n• 80: Relaxed\n\nOversold: Block SELL below this\n• 30: Standard ⭐\n• 20: Relaxed")
i_useHullConfirm = input.bool(false, "Hull MA", group=GROUP_FILTERS, inline="sf6")
i_hullPeriod     = input.int(20,     "/ Period", minval=5, maxval=100, group=GROUP_FILTERS, inline="sf6", tooltip = "HULL MA CONFIRMATION:\nRequire Hull MA direction alignment\n\nPERIOD: Hull MA lookback\n• 14-20: Responsive ⭐\n• 30-50: Smoother\n\nBUY: Price must be above Hull MA\nSELL: Price must be below Hull MA")
i_useSuperTrend  = input.bool(false, "SuperTrend", group=GROUP_FILTERS, inline="sf7")
i_stAtrPeriod    = input.int(10,     "/ ATR",    minval=5, maxval=50, group=GROUP_FILTERS, inline="sf7")
i_stMult         = input.float(3.0,  "×",        minval=1.0, maxval=5.0, step=0.1, group=GROUP_FILTERS, inline="sf7")
i_showStLine     = input.bool(false, "Line",     group=GROUP_FILTERS, inline="sf7", tooltip = "SUPERTREND FILTER:\nRequire SuperTrend confirmation\n\nBUY: Only when SuperTrend is bullish\nSELL: Only when SuperTrend is bearish\n\nATR: Period for volatility (10 standard ⭐)\nMULT: Multiplier (3.0 standard ⭐)\nLINE: Show SuperTrend line on chart")
i_useFullCandle  = input.bool(true,  "Full Candle", group=GROUP_FILTERS, inline="sf8", tooltip = "FULL CANDLE CONFIRMATION:\nRequire entire candle above/below UT line\n\n• BUY: Low must be above trailing stop\n• SELL: High must be below trailing stop\n\nPrevents signals on candles 'straddling' the line\nReduces false signals that quickly reverse")
utShowZones      = input.bool(true,  "S/R Zones",   group=GROUP_FILTERS, inline="sfz")
i_useZoneFilter  = input.bool(false, "| Zone Filter", group=GROUP_FILTERS, inline="sfz")
i_zoneWidthMult  = input.float(0.5,  "/ Width×ATR", group=GROUP_FILTERS, minval=0.1, maxval=2.0, step=0.1, inline="sfz", tooltip = "SUPPORT/RESISTANCE ZONES:\nClusters recent pivot highs/lows into persistent price zones (unlike the rolling Structure line above, these stay fixed until price revisits and breaks them)\n\nS/R ZONES: Show zone boxes on chart\nZONE FILTER: Block BUY inside a resistance zone, SELL inside a support zone\nWIDTH: Zone half-width as ATR multiple\n• 0.3-0.5: Tight zones ⭐\n• 0.8-1.2: Wide zones")
i_zonePivotLen   = input.int(10,     "/ Pivot Strength", minval=3, maxval=50, group=GROUP_FILTERS, inline="sfz2", tooltip = "S/R PIVOT STRENGTH:\nBars each side required to confirm a swing high/low for zone clustering.\n\n• 5-7: Minor swings (more, weaker zones)\n• 10: Balanced ⭐\n• 15-20: Only major swings (fewer, stronger zones)\n\nHigher than the Divergence pivot on purpose - S/R levels should be more significant than divergence pivots.")

entryShow    = input.bool(true, "Show Entry Line", group=GROUP_SL, inline="SHOW")
linesLimit10 = input.bool(true, "Limit 10 bars",   group=GROUP_SL, inline="SHOW", tooltip = "Limit all lines (SL, TP, Entry) to 10 bars\n• ON: Cleaner chart ⭐\n• OFF: Lines extend until next signal")
slShow     = input.bool(true,  "Show Stop Loss Line", group=GROUP_SL, inline="sl1")
slMethod   = input.string("Smart Adaptive", "| SL Method", options=["ATR", "% Based", "Tick Based", "Swing", "Scaled ATR", "Smart Adaptive", "Safer"], group=GROUP_SL, inline="sl1", tooltip = "Stop Loss calculation method:\n\n⭐ SMART ADAPTIVE (Recommended):\n• Auto-adjusts to volatility\n• Low vol: 0.7× ATR | Med: 1.0× | High: 1.5×\n\nATR:\n• Standard ATR × Multiplier\n\n% BASED:\n• Fixed % from entry price\n• Good for high-price stocks\n\nTICK BASED:\n• Fixed number of ticks\n• Consistent dollar risk\n\nSWING:\n• Recent swing high/low\n\nSCALED ATR:\n• Dynamic multiplier by volatility\n\nSAFER:\n• Widest of ATR/Swing/% methods")
tpDisplayMode   = input.string("Minimal", "TP Style", options=["Minimal", "Detailed"], group=GROUP_SL, inline="DIS")
tpFreezeOnTouch = input.bool(true, "Freeze Lines on Hit", group=GROUP_SL, inline="DIS", tooltip = "LINE DISPLAY STYLE:\n\n• Minimal: Clean labels (TP1, TP2, etc.)\n• Detailed: Shows price + % gain on label\n  - Easier for trading execution\n  - Example: 'TP1 $150.25 (+2.5%)'\n\nWhen ON: marks TP with ✅ when price touches it\nUseful for trade journaling and review")

slAtrLen   = input.int(14,     "ATR",  minval=5,  maxval=50, group=GROUP_SL, inline="sl3")
slAtrMult  = input.float(1.5,  "×",    minval=0.5, maxval=3, step=0.1, group=GROUP_SL, inline="sl3", tooltip = "ATR Period & Multiplier\n• 7-10 / 1.0×: Day trading\n• 14 / 1.5×: Standard ⭐\n• 20+ / 2.0×: Swing trading")
slPctStop  = input.float(5.0,  "% Stop",    minval=0.1, maxval=10.0, step=0.1, group=GROUP_SL, inline="sl5", tooltip = "Fixed % distance from entry\n• LONG: SL = Entry × (1 - %)\n• SHORT: SL = Entry × (1 + %)\n\n• 0.5%: Tight (scalping)\n• 1.0%: Balanced ⭐\n• 2.0%: Wide (swing)")
slTickStop = input.int(50,     "Ticks",     minval=5,  maxval=500, step=5, group=GROUP_SL, inline="sl5", tooltip = "Fixed ticks from entry\n• Tick = minimum price movement\n• 20-50: Tight\n• 50-100: Normal ⭐\n• 100+: Wide")
slExtraTicks = input.int(0,    "Buffer",    minval=0, group=GROUP_SL, inline="sl6", tooltip = "Extra ticks beyond calculated SL\n• Protects against stop hunts\n• 0 = No buffer\n• 2-5 = Typical")

tpShow    = input.bool(true,  "Show TP Lines", group=GROUP_SL, inline="tp1")
tp1On     = input.bool(true,   "TP×1 (1R) |", group=GROUP_SL, inline="tp2")
tp15On    = input.bool(false,  "TP×1.5 |", group=GROUP_SL, inline="tp2")
tp2On     = input.bool(true,   "TP×2 |", group=GROUP_SL, inline="tp2")
tp3On     = input.bool(false,  "TP×3", group=GROUP_SL, inline="tp2", tooltip = "R = Risk Units (distance from entry to SL)\n\nTP1 (1R): Conservative, 1:1 risk/reward\nTP1.5 (1.5R): Intermediate target\nTP2 (2R): Balanced, 2:1 R:R ⭐\nTP3 (3R): Aggressive, 3:1 R:R\n\nRECOMMENDED:\n• Scalping: TP1 + TP1.5\n• Day Trading: TP1 + TP2 ⭐\n• Swing: TP2 + TP3")

i_useMTF      = input.bool(false, "Enable MTF", group=GROUP_L3, inline="L3a", tooltip = "Multi-Timeframe Confirmation\n\nWhen ON: Only allow signals aligned with higher timeframe trend\n• BUY: HTF must be bullish\n• SELL: HTF must be bearish\n\nReduces counter-trend entries")
i_mtfTimeframe = input.string(MTF_AUTO, "Timeframe", options=[MTF_AUTO, MTF_5M, MTF_15M, MTF_30M, MTF_1H, MTF_4H, MTF_D, MTF_W], group=GROUP_L3, inline="L3a", tooltip = "HIGHER TIMEFRAME:\n\n• Auto (×4): 4× current TF ⭐\n  - 1m → 5m\n  - 5m → 15m\n  - 15m → 1H\n  - 1H → 4H\n  - 4H → D\n  - D → W\n\n• Manual: Select specific timeframe")
i_statsLookback = input.int(60, "Stats Days", minval=1, maxval=365, group=GROUP_L3, inline="L3b", tooltip = "STATISTICS LOOKBACK:\n\nHow many days back to count trades for Win Rate and Avg Bars.\n\n• 5: Recent performance ⭐\n• 30: Monthly view\n• 90: Quarterly view")

i_showDivergence = input.bool(true, "Show Divergence", group=GROUP_L3, inline="L3c", tooltip = "DIVERGENCE DETECTION:\n\nShows RSI divergences on chart\n\n• Bullish: Price ↓ + RSI ↑ (reversal up)\n• Bearish: Price ↑ + RSI ↓ (reversal down)\n\nUseful for spotting potential reversals")
i_divRsiLen      = input.int(14, "RSI", minval=5, maxval=50, group=GROUP_L3, inline="L3c")
i_divLookback    = input.int(5, "/ Pivot", minval=2, maxval=20, group=GROUP_L3, inline="L3c", tooltip = "RSI: Period for RSI calculation (14 standard)\n\nPIVOT: Bars to confirm pivot high/low\n• 3-5: More signals\n• 5-10: Fewer, stronger signals ⭐")

i_showRisk       = input.bool(true, "Show Risk Calc", group=GROUP_CALC, inline="L3d", tooltip = "RISK CALCULATOR:\n\nCalculates position size based on:\n• Account size\n• Risk percentage OR fixed amount\n• Stop loss distance\n\nShows how many shares/contracts to buy")
i_riskMode       = input.string("% of Account", "Risk Mode", options=["% of Account", "Fixed Amount"], group=GROUP_CALC, inline="L3d", tooltip = "RISK MODE:\n\n• % of Account: Risk X% of total account\n• Fixed Amount: Risk fixed $ amount per trade\n\nFixed is useful for consistent risk across all trades")
i_accountSize    = input.float(10000, "Account $", minval=100, step=1000, group=GROUP_CALC, inline="L3e", tooltip = "Your total trading account size in account currency\n\nUsed to calculate:\n• Risk amount per trade (when using %)\n• Position size\n• Max position value")
i_riskPct        = input.float(1.0, "Risk %", minval=0.1, maxval=10, step=0.1, group=GROUP_CALC, inline="L3e", tooltip = "Percentage of account to risk per trade\n(Only used when Risk Mode = '% of Account')\n\n• 0.5-1%: Conservative ⭐\n• 1-2%: Moderate\n• 2-3%: Aggressive")
i_riskFixed      = input.float(100, "/ Fixed $", minval=1, step=10, group=GROUP_CALC, inline="L3e", tooltip = "Fixed amount to risk per trade\n(Only used when Risk Mode = 'Fixed Amount')\n\nExamples:\n• $50: Small accounts\n• $100: Medium ⭐\n• $200+: Larger accounts")
i_accountCurrency = input.string("USD", "Currency", options=["USD", "EUR", "GBP", "JPY", "CAD", "AUD", "CHF"], group=GROUP_CALC, inline="L3f", tooltip = "Your account currency\n\nAffects position sizing calculations")
i_useLiveRates   = input.bool(true, "Live Rates", group=GROUP_CALC, inline="L3f")
i_manualRate     = input.float(1.0, "/ Manual $1=", minval=0.001, maxval=10000, step=0.01, group=GROUP_CALC, inline="L3f", tooltip = "Manual exchange rate (USD to your currency)\n\nExamples:\n• USD to ILS = 3.7\n• USD to EUR = 0.92\n• USD to JPY = 150\n\nUsed when Live Rates is OFF or unavailable")

i_enablePrediction = input.bool(true, "Enable Prediction", group=GROUP_PRED, inline="pred1", tooltip = "TREND PREDICTION:\n\nPredicts how long the current trend may last based on historical patterns.\n\n• Gradient boxes show expected duration\n• Labels show survival probability %\n• Dashboard shows prediction stats")
i_predMode         = input.string("Standard", "Mode", options=["Simple", "Standard", "Advanced"], group=GROUP_PRED, inline="pred1", tooltip = "PREDICTION MODE:\n\n• Simple: Uses median duration only\n• Standard: EWA + standard deviation ⭐\n• Advanced: Adds 5 adaptive multipliers:\n  - Structure (S/R proximity)\n  - Stock Type (volatility profile)\n  - Flip Strength (volume + filters)\n  - Error Learning (self-correction)\n  - Regime (trend vs chop)")
i_predSamples      = input.int(50, "History", minval=10, maxval=100, group=GROUP_PRED, inline="pred2", tooltip = "HISTORY SIZE:\n\nNumber of past trends to analyze\n\n• 10-30: Responsive to recent changes\n• 50: Balanced ⭐\n• 100: Smoother, more stable")
i_showPredBoxes    = input.bool(true, "Boxes", group=GROUP_PRED, inline="pred2", tooltip = "Show gradient boxes visualizing predicted trend duration\n\n• Fades from solid to transparent\n• Position: Below (bull) or above (bear) UT line")
i_showPredLabels   = input.bool(true, "Labels", group=GROUP_PRED, inline="pred2", tooltip = "Show probability labels at key points\n\n• Shows survival % at 25%, 50%, 75%, 90%, 100% of prediction\n• Weibull probability distribution")

var line  slLine     = na
var label slLbl      = na
var int   slStartBar = na
var float baseSl     = na
var float slPrice    = na
var color slColor    = na

var line  tp1Line  = na
var line  tp15Line = na
var line  tp2Line  = na
var line  tp3Line  = na
var label tp1Lbl   = na
var label tp15Lbl  = na
var label tp2Lbl   = na
var label tp3Lbl   = na

var float tp1Y       = na
var float tp15Y      = na
var float tp2Y       = na
var float tp3Y       = na
var float tpInitRisk = na

var line  entryLine = na
var label entryLbl  = na
var int   entryBar  = na
var float entryPx   = na
var color entryCol  = na

var int   statTotalTrades = 0
var int   statWins        = 0
var int   statLosses      = 0
var int   statTotalBars   = 0   // Sum of bars to TP (for avg calculation)
var int   statWinBars     = 0   // Count of wins with bar data
var bool  statTradeOpen   = false

var array<int> pred_bull_durations = array.new<int>()
var array<int> pred_bear_durations = array.new<int>()
var array<int> pred_all_durations = array.new<int>()
var array<bool> pred_all_is_bullish = array.new<bool>()

var int pred_current_bars = 0
var bool pred_is_bullish = true

var float pred_avg = na
var float pred_end = na
var bool pred_using_fallback = false

var array<float> pred_last10_predicted = array.new<float>()
var array<int> pred_last10_actual = array.new<int>()
var array<bool> pred_last10_bullish = array.new<bool>()

var array<float> pred_vol_ratios = array.new<float>()
var array<float> pred_quality_scores = array.new<float>()
var array<float> pred_error_ratios = array.new<float>()

var array<box> pred_boxes = array.new<box>()
var array<label> pred_labels = array.new<label>()

var array<float> zoneResPrice    = array.new<float>()
var array<int>   zoneResTouch    = array.new<int>()
var array<int>   zoneResStartBar = array.new<int>()
var array<box>   zoneResBoxes    = array.new<box>()
var array<label> zoneResLabels   = array.new<label>()
var array<float> zoneSupPrice    = array.new<float>()
var array<int>   zoneSupTouch    = array.new<int>()
var array<int>   zoneSupStartBar = array.new<int>()
var array<box>   zoneSupBoxes    = array.new<box>()
var array<label> zoneSupLabels   = array.new<label>()

detectRegime() =>
    [diplus, diminus, adxValue] = ta.dmi(i_adxPeriod, i_adxPeriod)
    bool isTrending = adxValue >= i_adxThreshold
    isTrending

var int lastSignalBar = na
var int lastSignalDir = 0  // 1 = BUY, -1 = SELL, 0 = none
checkCooldown() =>
    bool cooldownOk = na(lastSignalBar) or (bar_index - lastSignalBar >= i_cooldownBars)
    cooldownOk

checkVolumeFilter() =>
    if not i_useVolFilter
        true
    else
        float volSma = ta.sma(volume, i_volSmaLen)
        volume >= volSma * i_volThreshold

checkRSIFilter(_isBuy) =>
    if not i_useRsiFilter
        true
    else
        float rsiVal = ta.rsi(close, i_rsiLen)
        _isBuy ? rsiVal < i_rsiOB : rsiVal > i_rsiOS

hullMA(series float src, simple int length) =>
    ta.wma(2 * ta.wma(src, length / 2) - ta.wma(src, length), math.round(math.sqrt(length)))

hullValue = i_useHullConfirm ? hullMA(close, i_hullPeriod) : close
checkHullFilter(_isBuy) =>
    if not i_useHullConfirm
        true
    else
        _isBuy ? close > hullValue : close < hullValue

currentATR = ta.atr(14)
avgATR = ta.sma(currentATR, i_volLookback)
volatilityRatio = avgATR > 0 ? currentATR / avgATR : 1.0
isHighVol = volatilityRatio >= i_volThresh
checkVolatilityFilter() =>
    if not i_useVolatility
        true
    else
        isHighVol

stAtr = ta.atr(i_stAtrPeriod)
float stUp = hl2 - (i_stMult * stAtr)
float stDn = hl2 + (i_stMult * stAtr)

var float stUpperBand = na
var float stLowerBand = na
var int   stDirection = 1  // 1 = bullish, -1 = bearish

stUpperBand := na(stUpperBand[1]) ? stUp : (stUp > stUpperBand[1] or close[1] < stUpperBand[1]) ? stUp : stUpperBand[1]
stLowerBand := na(stLowerBand[1]) ? stDn : (stDn < stLowerBand[1] or close[1] > stLowerBand[1]) ? stDn : stLowerBand[1]

stDirection := na(stDirection[1]) ? 1 :
               stDirection[1] == -1 and close > stLowerBand[1] ? 1 :
               stDirection[1] == 1 and close < stUpperBand[1] ? -1 :
               stDirection[1]

float stValue = stDirection == 1 ? stUpperBand : stLowerBand

bool stBullish = stDirection == 1
bool stBearish = stDirection == -1

float stDistance = math.abs(close - stValue)
float stStrength = math.min(100, (stDistance / stAtr) * 25)

bool stFlipBull = stDirection == 1 and stDirection[1] == -1
bool stFlipBear = stDirection == -1 and stDirection[1] == 1

checkSuperTrendFilter(_isBuy) =>
    if not i_useSuperTrend
        true
    else
        _isBuy ? stBullish : stBearish

float sbSwingHigh = ta.highest(high, swingLen)
float sbSwingLow = ta.lowest(low, swingLen)

bool sbBullishBreak = close > sbSwingHigh[1]  // Closed above previous swing high
bool sbBearishBreak = close < sbSwingLow[1]   // Closed below previous swing low

float sbAtr = ta.atr(14)
float sbMid = (sbSwingHigh[1] + sbSwingLow[1]) / 2
float sbHalfRange = (sbSwingHigh[1] - sbSwingLow[1]) / 2

float sbBullDistance = sbBullishBreak ? (close - sbSwingHigh[1]) : 0
float sbBearDistance = sbBearishBreak ? (sbSwingLow[1] - close) : 0
float sbBreakStrength = math.min(100, math.max(sbBullDistance, sbBearDistance) / sbAtr * 30)
float sbPositionStrength = sbHalfRange > 0 ? math.min(100, math.abs(close - sbMid) / sbHalfRange * 100) : 0
float sbStrength = sbBullishBreak or sbBearishBreak ? sbBreakStrength : sbPositionStrength

bool sbBullish = close > sbMid  // Above midpoint = bullish structure
bool sbBearish = close <= sbMid // At or below midpoint = bearish structure

bool l1_regimeOk      = not i_enableLayer1 or detectRegime()
bool l1_cooldownOk    = i_cooldownBars == 0 or checkCooldown()
bool l1_volumeOk      = checkVolumeFilter()
bool l1_volatilityOk  = checkVolatilityFilter()

detectAssetType() =>
    if i_assetType != ASSET_AUTO
        i_assetType
    else
        switch syminfo.type
            "crypto"  => ASSET_CRYPTO
            "forex"   => ASSET_FOREX
            "futures" => ASSET_FUTURES
            "index"   => ASSET_INDEX
            "fund"    => ASSET_FUND
            "cfd"     => ASSET_CFD
            "bond"    => ASSET_BOND
            => ASSET_STOCK  // stock or unknown → treat as stock

getAssetMultiplier(string assetType) =>
    switch assetType
        ASSET_CRYPTO  => 1.5   // Crypto: wider stops (high volatility)
        ASSET_FOREX   => 0.8   // Forex: tighter stops (low volatility)
        ASSET_FUTURES => 1.2   // Futures: moderate
        ASSET_INDEX   => 0.9   // Index: slightly tighter (diversified, less volatile)
        ASSET_FUND    => 0.9   // Fund/ETF: slightly tighter (diversified)
        ASSET_CFD     => 1.0   // CFD: standard (mirrors underlying)
        ASSET_BOND    => 0.5   // Bond: much tighter (very low volatility)
        ASSET_STOCK   => 1.0   // Stock: standard
        => 1.0

getAdaptiveMultiplier(float volRatio) =>
    if i_adaptiveMode == ADAPT_FIXED
        1.0
    else if i_adaptiveMode == ADAPT_DYNAMIC

        if volRatio < 0.8
            0.85   // Low volatility: tighter stops
        else if volRatio > 1.2
            1.15   // High volatility: wider stops
        else
            1.0    // Normal volatility
    else  // ADAPT_AGGRESSIVE

        if volRatio < 0.8
            0.7    // Low volatility: much tighter
        else if volRatio > 1.2
            1.3    // High volatility: much wider
        else
            1.0    // Normal volatility

string detectedAsset = detectAssetType()
float  assetMult     = getAssetMultiplier(detectedAsset)
float  adaptiveMult  = getAdaptiveMultiplier(volatilityRatio)

getAutoHTF() =>
    string htf = ""
    if timeframe.isintraday
        int mins = timeframe.multiplier
        if timeframe.isseconds
            mins := 1
        else if timeframe.isminutes
            mins := timeframe.multiplier

        int htfMins = mins * 4
        if htfMins < 60
            htf := str.tostring(htfMins)
        else if htfMins < 240
            htf := str.tostring(htfMins / 60) + "H"
        else if htfMins < 1440
            htf := "4H"
        else
            htf := "D"
    else if timeframe.isdaily
        htf := "W"
    else if timeframe.isweekly
        htf := "M"
    else
        htf := "D"
    htf

getSelectedHTF() =>
    if i_mtfTimeframe == MTF_AUTO
        getAutoHTF()
    else
        switch i_mtfTimeframe
            MTF_5M  => "5"
            MTF_15M => "15"
            MTF_30M => "30"
            MTF_1H  => "60"
            MTF_4H  => "240"
            MTF_D   => "D"
            MTF_W   => "W"
            => "60"

getCurrentTFMins() =>
    int mins = 0
    if timeframe.isseconds
        mins := 1
    else if timeframe.isminutes
        mins := timeframe.multiplier
    else if timeframe.isdaily
        mins := 1440
    else if timeframe.isweekly
        mins := 10080
    else if timeframe.ismonthly
        mins := 43200
    else
        mins := timeframe.multiplier
    mins

int currentTFMins = getCurrentTFMins()

[htf5mEmaFast,  htf5mEmaSlow]  = request.security(syminfo.tickerid, "5",   [ta.ema(close, 9), ta.ema(close, 21)], lookahead=barmerge.lookahead_off)
[htf15mEmaFast, htf15mEmaSlow] = request.security(syminfo.tickerid, "15",  [ta.ema(close, 9), ta.ema(close, 21)], lookahead=barmerge.lookahead_off)
[htf30mEmaFast, htf30mEmaSlow] = request.security(syminfo.tickerid, "30",  [ta.ema(close, 9), ta.ema(close, 21)], lookahead=barmerge.lookahead_off)
[htf1hEmaFast,  htf1hEmaSlow]  = request.security(syminfo.tickerid, "60",  [ta.ema(close, 9), ta.ema(close, 21)], lookahead=barmerge.lookahead_off)
[htf4hEmaFast,  htf4hEmaSlow]  = request.security(syminfo.tickerid, "240", [ta.ema(close, 9), ta.ema(close, 21)], lookahead=barmerge.lookahead_off)
[htfDEmaFast,   htfDEmaSlow]   = request.security(syminfo.tickerid, "D",   [ta.ema(close, 9), ta.ema(close, 21)], lookahead=barmerge.lookahead_off)
[htfWEmaFast,   htfWEmaSlow]   = request.security(syminfo.tickerid, "W",   [ta.ema(close, 9), ta.ema(close, 21)], lookahead=barmerge.lookahead_off)

int htf5mTrend  = htf5mEmaFast  > htf5mEmaSlow  ? 1 : htf5mEmaFast  < htf5mEmaSlow  ? -1 : 0
int htf15mTrend = htf15mEmaFast > htf15mEmaSlow ? 1 : htf15mEmaFast < htf15mEmaSlow ? -1 : 0
int htf30mTrend = htf30mEmaFast > htf30mEmaSlow ? 1 : htf30mEmaFast < htf30mEmaSlow ? -1 : 0
int htf1hTrend  = htf1hEmaFast  > htf1hEmaSlow  ? 1 : htf1hEmaFast  < htf1hEmaSlow  ? -1 : 0
int htf4hTrend  = htf4hEmaFast  > htf4hEmaSlow  ? 1 : htf4hEmaFast  < htf4hEmaSlow  ? -1 : 0
int htfDTrend   = htfDEmaFast   > htfDEmaSlow   ? 1 : htfDEmaFast   < htfDEmaSlow   ? -1 : 0
int htfWTrend   = htfWEmaFast   > htfWEmaSlow   ? 1 : htfWEmaFast   < htfWEmaSlow   ? -1 : 0

string htfTimeframe = getSelectedHTF()
int htfTrend = switch htfTimeframe
    "5"   => htf5mTrend
    "15"  => htf15mTrend
    "30"  => htf30mTrend
    "60"  => htf1hTrend
    "240" => htf4hTrend
    "D"   => htfDTrend
    "W"   => htfWTrend
    => htf1hTrend
string htfTrendStr = htfTrend == 1 ? "BULL" : htfTrend == -1 ? "BEAR" : "NEUTRAL"

trendEmoji(int t) => t == 1 ? "🟢" : t == -1 ? "🔴" : "⚪"
trendStr(int t) => t == 1 ? "BULL" : t == -1 ? "BEAR" : "NEUTRAL"

checkMTFFilter(_isBuy) =>
    if not i_useMTF
        true
    else
        _isBuy ? htfTrend >= 0 : htfTrend <= 0  // Allow neutral

float divRsi = ta.rsi(close, i_divRsiLen)

float pivotLow  = ta.pivotlow(low, i_divLookback, i_divLookback)
float pivotHigh = ta.pivothigh(high, i_divLookback, i_divLookback)
float rsiPivotLow  = ta.pivotlow(divRsi, i_divLookback, i_divLookback)
float rsiPivotHigh = ta.pivothigh(divRsi, i_divLookback, i_divLookback)

var float prevPriceLow  = na
var float prevPriceHigh = na
var float prevRsiLow    = na
var float prevRsiHigh   = na
var int   prevLowBar    = na
var int   prevHighBar   = na

var bool bullishDiv = false
var bool bearishDiv = false

bullishDiv := false
bearishDiv := false

if not na(pivotLow) and not na(rsiPivotLow)
    if not na(prevPriceLow) and not na(prevRsiLow)

        bool priceLowerLow = pivotLow < prevPriceLow

        bool rsiHigherLow = rsiPivotLow > prevRsiLow

        if priceLowerLow and rsiHigherLow
            bullishDiv := true

    prevPriceLow := pivotLow
    prevRsiLow   := rsiPivotLow
    prevLowBar   := bar_index - i_divLookback

if not na(pivotHigh) and not na(rsiPivotHigh)
    if not na(prevPriceHigh) and not na(prevRsiHigh)

        bool priceHigherHigh = pivotHigh > prevPriceHigh

        bool rsiLowerHigh = rsiPivotHigh < prevRsiHigh

        if priceHigherHigh and rsiLowerHigh
            bearishDiv := true

    prevPriceHigh := pivotHigh
    prevRsiHigh   := rsiPivotHigh
    prevHighBar   := bar_index - i_divLookback

var string lastDivType = "None"
var int    lastDivBar  = na

if bullishDiv
    lastDivType := "BULL"
    lastDivBar  := bar_index
if bearishDiv
    lastDivType := "BEAR"
    lastDivBar  := bar_index

int barsSinceDiv = na(lastDivBar) ? 999 : bar_index - lastDivBar

const int ZONE_MAX = 3

registerZone(array<float> _prices, array<int> _touches, array<int> _startBars, float _pivotPrice, float _tolerance, int _startBar, float _currentPrice) =>
    int n = array.size(_prices)
    int matchIdx = -1
    if n > 0
        for i = 0 to n - 1
            if math.abs(_pivotPrice - array.get(_prices, i)) <= _tolerance
                matchIdx := i
    if matchIdx >= 0
        array.set(_prices, matchIdx, (array.get(_prices, matchIdx) + _pivotPrice) / 2)
        array.set(_touches, matchIdx, array.get(_touches, matchIdx) + 1)
    else
        if n >= ZONE_MAX

            int worstIdx = 0
            float worstDist = math.abs(_currentPrice - array.get(_prices, 0))
            for i = 1 to n - 1
                float d = math.abs(_currentPrice - array.get(_prices, i))
                if d > worstDist
                    worstDist := d
                    worstIdx := i
            array.remove(_prices, worstIdx)
            array.remove(_touches, worstIdx)
            array.remove(_startBars, worstIdx)
        array.push(_prices, _pivotPrice)
        array.push(_touches, 1)
        array.push(_startBars, _startBar)

zoneMatch(array<float> _prices, array<int> _touches, float _tolerance, float _price) =>
    bool inside = false
    int touchCount = 0
    if array.size(_prices) > 0
        for i = 0 to array.size(_prices) - 1
            if math.abs(_price - array.get(_prices, i)) <= _tolerance
                inside := true
                touchCount := array.get(_touches, i)
    [inside, touchCount]

nearestZoneIdx(array<float> _prices, float _price, bool _wantAbove) =>
    int bestIdx = -1
    float bestDist = 0.0
    if array.size(_prices) > 0
        for i = 0 to array.size(_prices) - 1
            float zp = array.get(_prices, i)

            bool onSide = _wantAbove ? zp > _price : zp < _price
            float d = math.abs(_price - zp)
            if onSide and (bestIdx == -1 or d < bestDist)
                bestDist := d
                bestIdx := i
    bestIdx

const float ZONE_STALE_PCT = 0.06
pruneStaleZones(array<float> _prices, array<int> _touches, array<int> _startBars, float _currentPrice, float _maxDist) =>
    int idx = array.size(_prices) - 1
    while idx >= 0
        if math.abs(_currentPrice - array.get(_prices, idx)) > _maxDist
            array.remove(_prices, idx)
            array.remove(_touches, idx)
            array.remove(_startBars, idx)
        idx -= 1

float zoneTol = sbAtr * i_zoneWidthMult
float zoneStaleDist = close * ZONE_STALE_PCT

float zonePivotHigh = ta.pivothigh(high, i_zonePivotLen, i_zonePivotLen)
float zonePivotLow  = ta.pivotlow(low, i_zonePivotLen, i_zonePivotLen)

pruneStaleZones(zoneResPrice, zoneResTouch, zoneResStartBar, close, zoneStaleDist)
pruneStaleZones(zoneSupPrice, zoneSupTouch, zoneSupStartBar, close, zoneStaleDist)

if not na(zonePivotHigh)
    registerZone(zoneResPrice, zoneResTouch, zoneResStartBar, zonePivotHigh, zoneTol, bar_index - i_zonePivotLen, close)
if not na(zonePivotLow)
    registerZone(zoneSupPrice, zoneSupTouch, zoneSupStartBar, zonePivotLow, zoneTol, bar_index - i_zonePivotLen, close)

[nearResistance, nearResTouches] = zoneMatch(zoneResPrice, zoneResTouch, zoneTol, close)
[nearSupport, nearSupTouches]    = zoneMatch(zoneSupPrice, zoneSupTouch, zoneTol, close)

checkZoneFilter(_isBuy) =>
    if not i_useZoneFilter
        true
    else
        _isBuy ? not nearResistance : not nearSupport

getCurrencySymbol(string curr) =>
    switch curr
        "USD" => "$"
        "EUR" => "€"
        "GBP" => "£"
        "ILS" => "₪"
        "JPY" => "¥"
        "CAD" => "C$"
        "AUD" => "A$"
        "CHF" => "Fr"
        => "$"

string currSymbol = getCurrencySymbol(i_accountCurrency)

string fxPair = switch i_accountCurrency
    "EUR" => "EURUSD"
    "GBP" => "GBPUSD"
    "ILS" => "USDILS"
    "JPY" => "USDJPY"
    "CAD" => "USDCAD"
    "AUD" => "AUDUSD"
    "CHF" => "USDCHF"
    => ""

float liveRate = na
if i_useLiveRates and fxPair != "" and i_accountCurrency != "USD"
    liveRate := request.security(fxPair, "D", close, lookahead=barmerge.lookahead_off)

float defaultRate = switch i_accountCurrency
    "EUR" => 0.92
    "GBP" => 0.79
    "ILS" => 3.70
    "JPY" => 150.0
    "CAD" => 1.38
    "AUD" => 1.55
    "CHF" => 0.90
    => 1.0

float exchangeRate = i_accountCurrency == "USD" ? 1.0 :
                     not i_useLiveRates ? i_manualRate :
                     na(liveRate) ? (i_manualRate != 1.0 ? i_manualRate : defaultRate) :
                     (i_accountCurrency == "EUR" or i_accountCurrency == "GBP" or i_accountCurrency == "AUD") ?
                         1/liveRate : liveRate

calcPositionSize(float _entry, float _sl) =>

    float riskAmount = i_riskMode == "Fixed Amount" ? i_riskFixed : i_accountSize * (i_riskPct / 100)

    string symbolCurr = syminfo.currency
    if symbolCurr != i_accountCurrency and i_accountCurrency != "USD"
        riskAmount := riskAmount / exchangeRate  // Convert to USD first if symbol is USD-based

    float riskPerShare = math.abs(_entry - _sl)
    float shares = riskPerShare > 0 ? math.floor(riskAmount / riskPerShare) : 0
    float posValue = shares * _entry
    float maxLoss = shares * riskPerShare

    [shares, posValue, maxLoss, riskAmount]

ewa_avg(array<int> arr, float decay) =>
    float sum_w = 0.0
    float sum_v = 0.0
    int n = array.size(arr)
    for i = 0 to n - 1
        float w = math.pow(decay, n - 1 - i)
        sum_w += w
        sum_v += array.get(arr, i) * w
    sum_w > 0 ? sum_v / sum_w : 0.0

ewa_stdev(array<int> arr, float avg, float decay) =>
    float sum_w = 0.0
    float sum_sq = 0.0
    int n = array.size(arr)
    for i = 0 to n - 1
        float w = math.pow(decay, n - 1 - i)
        float diff = array.get(arr, i) - avg
        sum_w += w
        sum_sq += w * diff * diff
    sum_w > 0 ? math.sqrt(sum_sq / sum_w) : 0.0

array_median(array<int> arr) =>
    int n = array.size(arr)
    if n == 0
        0.0
    else
        array<int> sorted = array.copy(arr)
        array.sort(sorted)
        n % 2 == 1 ? float(array.get(sorted, n/2)) : (array.get(sorted, n/2-1) + array.get(sorted, n/2)) / 2.0

get_structure_mult() =>
    float pivotHi = ta.pivothigh(high, 10, 10)
    float pivotLo = ta.pivotlow(low, 10, 10)
    float atr = ta.atr(14)
    bool nearLevel = (not na(pivotHi) and math.abs(close - pivotHi) < atr) or
                     (not na(pivotLo) and math.abs(close - pivotLo) < atr)
    nearLevel ? 0.7 : 1.0

get_stock_type_mult(string _asset) =>
    switch _asset
        ASSET_CRYPTO => 0.60
        ASSET_FOREX => 0.80
        ASSET_FUTURES => 0.90
        ASSET_BOND => 1.35
        => 1.0  // Stock, Index, Fund, CFD

get_flip_strength_mult(bool _regimeOk, bool _volFilterOk, bool _stFilterOk, float _currentATR, float _avgATR) =>
    float vol_score = math.min(40, (volume / ta.sma(volume, 20) - 1) * 40)
    float atr_score = math.min(30, ((_currentATR / _avgATR) - 1) * 30)

    int filters_passed = 0
    if _regimeOk
        filters_passed += 1
    if _volFilterOk
        filters_passed += 1
    if _stFilterOk
        filters_passed += 1
    float filter_score = filters_passed * 10  // 0-30 points

    float total = vol_score + atr_score + filter_score
    0.5 + (total / 100) * 1.5  // Range: 0.5x to 2.0x

get_learning_mult() =>
    int n = array.size(pred_error_ratios)
    if n < 3
        1.0
    else
        float avg_err = array.avg(pred_error_ratios)
        if avg_err > 1.0
            1.0 - math.min((avg_err - 1.0) * 0.5, 0.15)
        else
            1.0 + math.min((1.0 - avg_err) * 0.5, 0.15)

get_regime_mult(bool _isBullish) =>
    array<int> recent = _isBullish ? pred_bull_durations : pred_bear_durations
    int n = array.size(recent)
    if n < 6
        1.0
    else
        float recent_avg = (array.get(recent, n-1) + array.get(recent, n-2) + array.get(recent, n-3)) / 3
        float hist_avg = array.avg(recent)
        float ratio = recent_avg / hist_avg
        ratio >= 1.3 ? 1.2 : ratio >= 1.1 ? 1.1 : ratio <= 0.7 ? 0.8 : ratio <= 0.9 ? 0.9 : 1.0

srcUT = close
xATR   = ta.atr(utAtrPeriod)

var float xATRTrailingStop = na
float momentum = ta.mom(srcUT, 5) / srcUT
float volRatio = volume / ta.sma(volume, 20)

float baseKey = utKey * assetMult * adaptiveMult
float adaptiveKey = baseKey * (1 + math.abs(momentum) * 2) * math.max(0.8, math.min(1.2, volRatio))
float trailDist = xATR * adaptiveKey

if na(xATRTrailingStop)
    xATRTrailingStop := srcUT
else
    float targetTrail = srcUT > xATRTrailingStop ? srcUT - trailDist : srcUT + trailDist
    float smoothing = 0.3
    xATRTrailingStop := xATRTrailingStop * (1 - smoothing) + targetTrail * smoothing

checkConfirmation(_isBuy) =>
    bool confirmed = true
    if i_confirmBars > 1
        for i = 1 to i_confirmBars - 1
            if _isBuy
                if close[i] <= xATRTrailingStop[i]
                    confirmed := false
                    break
            else
                if close[i] >= xATRTrailingStop[i]
                    confirmed := false
                    break
    confirmed

above = ta.crossover(srcUT, xATRTrailingStop)
below = ta.crossunder(srcUT, xATRTrailingStop)

atrPct = srcUT != 0 ? (xATR / srcUT * 100.0) : 0.0
float atrPctSafe = math.min(atrPct, 20.0)
kUT    = 0.50
thr    = math.max(utPctThr, atrPctSafe * kUT)

barbuy  = srcUT > xATRTrailingStop
barsell = srcUT < xATRTrailingStop

bool pred_flip_to_bull = barbuy and not barbuy[1]
bool pred_flip_to_bear = barsell and not barsell[1]
bool pred_flip = pred_flip_to_bull or pred_flip_to_bear

int pred_completed_duration = pred_current_bars

pred_current_bars := pred_flip ? 1 : pred_current_bars + 1

if pred_flip

    if pred_completed_duration > 1
        if pred_is_bullish
            array.push(pred_bull_durations, pred_completed_duration)
        else
            array.push(pred_bear_durations, pred_completed_duration)
        array.push(pred_all_durations, pred_completed_duration)
        array.push(pred_all_is_bullish, pred_is_bullish)

        if array.size(pred_all_durations) > i_predSamples
            array.shift(pred_all_durations)
            array.shift(pred_all_is_bullish)
        if array.size(pred_bull_durations) > i_predSamples
            array.shift(pred_bull_durations)
        if array.size(pred_bear_durations) > i_predSamples
            array.shift(pred_bear_durations)

    if i_enablePrediction and not na(pred_end) and pred_completed_duration > 1
        array.push(pred_last10_predicted, pred_end)
        array.push(pred_last10_actual, pred_completed_duration)
        array.push(pred_last10_bullish, pred_is_bullish)
        float error_ratio = pred_end > 0 ? float(pred_completed_duration) / pred_end : 1.0
        array.push(pred_error_ratios, error_ratio)
        if array.size(pred_last10_predicted) > 10
            array.shift(pred_last10_predicted)
            array.shift(pred_last10_actual)
            array.shift(pred_last10_bullish)
        if array.size(pred_error_ratios) > 10
            array.shift(pred_error_ratios)

    pred_is_bullish := pred_flip_to_bull

    if i_enablePrediction
        array<int> relevant = pred_is_bullish ? pred_bull_durations : pred_bear_durations
        int samples = array.size(relevant)

        if samples >= 3
            pred_using_fallback := false
            if i_predMode == "Simple"
                float median = array_median(relevant)
                pred_avg := median
                pred_end := median * 2.5
            else
                float avg = ewa_avg(relevant, 0.9)
                float stdev = ewa_stdev(relevant, avg, 0.9)
                pred_avg := avg
                pred_end := avg + 2.0 * stdev

                if i_predMode == "Advanced"

                    float total_mult = 1.0
                    total_mult *= get_structure_mult()
                    total_mult *= get_stock_type_mult(detectedAsset)
                    total_mult *= get_flip_strength_mult(l1_regimeOk, checkVolumeFilter(), checkSuperTrendFilter(pred_is_bullish), currentATR, avgATR)
                    total_mult *= get_learning_mult()
                    total_mult *= get_regime_mult(pred_is_bullish)
                    total_mult := math.max(0.4, math.min(2.0, total_mult))
                    pred_end *= total_mult
        else

            pred_using_fallback := true
            int allSamples = array.size(pred_all_durations)
            if allSamples >= 3
                float avgAll = ewa_avg(pred_all_durations, 0.9)
                float stdevAll = ewa_stdev(pred_all_durations, avgAll, 0.9)
                pred_avg := avgAll
                pred_end := avgAll + 2.0 * stdevAll
            else if allSamples >= 1
                float avgAll = ewa_avg(pred_all_durations, 0.9)
                pred_avg := avgAll
                pred_end := avgAll * 2.5
            else

                pred_avg := 8.0
                pred_end := 16.0

        array<int> capArr = pred_all_durations
        if samples >= 3
            capArr := relevant
        if not na(pred_end) and array.size(capArr) >= 3
            float p90dur = array.percentile_nearest_rank(capArr, 90)
            if p90dur > 0
                pred_end := math.min(pred_end, p90dur)

chgOk     = not utUsePctFilter or (math.abs(srcUT - srcUT[1]) / srcUT[1] * 100.0 > thr)

float _lo = na
float _hi = na
if utUseSwingFilter
    _lo := ta.lowest(srcUT, swingLen)
    _hi := ta.highest(srcUT, swingLen)

swingOkBuy  = not utUseSwingFilter or srcUT > _lo * 1.01
swingOkSell = not utUseSwingFilter or srcUT < _hi * 0.99

flipUp = above
flipDn = below
utBuy  = (utUseDelay ? ((bar_index > 1 ? flipUp[2]  : false) and (bar_index > 0 ? barbuy[1]  : false) and (bar_index > 1 ? barbuy[2]  : false)) : flipUp)  and chgOk and swingOkBuy
utSell = (utUseDelay ? ((bar_index > 1 ? flipDn[2]  : false) and (bar_index > 0 ? barsell[1] : false) and (bar_index > 1 ? barsell[2] : false)) : flipDn) and chgOk and swingOkSell

bool fullCandleBuyOk  = not i_useFullCandle or low > xATRTrailingStop   // Entire candle above line
bool fullCandleSellOk = not i_useFullCandle or high < xATRTrailingStop  // Entire candle below line

confirmRealBuy  = close > xATRTrailingStop and fullCandleBuyOk
confirmRealSell = close < xATRTrailingStop and fullCandleSellOk

bool l1_confirmBuy  = checkConfirmation(true)
bool l1_confirmSell = checkConfirmation(false)

utBuy  := utBuy  and confirmRealBuy  and l1_regimeOk and l1_cooldownOk and l1_confirmBuy  and l1_volumeOk and l1_volatilityOk and checkRSIFilter(true)  and checkHullFilter(true)  and checkSuperTrendFilter(true)  and checkMTFFilter(true)  and checkZoneFilter(true)
utSell := utSell and confirmRealSell and l1_regimeOk and l1_cooldownOk and l1_confirmSell and l1_volumeOk and l1_volatilityOk and checkRSIFilter(false) and checkHullFilter(false) and checkSuperTrendFilter(false) and checkMTFFilter(false) and checkZoneFilter(false)

utBuy  := utBuy  and lastSignalDir != 1
utSell := utSell and lastSignalDir != -1

if utBuy and barstate.isconfirmed
    lastSignalBar := bar_index
    lastSignalDir := 1
if utSell and barstate.isconfirmed
    lastSignalBar := bar_index
    lastSignalDir := -1

bool utVizGate = barstate.isconfirmed or not barstate.isrealtime

bool slFeatureOn    = slShow and utShowLabels
bool tpFeatureOn    = tpShow and utShowLabels
bool entryFeatureOn = entryShow 

ensureSLObjects(line _ln, label _lb, int _x, float _y, color _c) =>
    line ln_result = _ln
    label lb_result = _lb
    if na(ln_result) and not na(_x) and not na(_y)
        ln_result := line.new(_x, _y, _x, _y, xloc=xloc.bar_index, extend=extend.none, color=_c, width=2)
    if na(lb_result) and not na(_x) and not na(_y)
        lb_result := label.new(_x, _y, "Suggested Stop Loss", xloc=xloc.bar_index, style=label.style_label_left, textcolor=color.white, color=_c, size=labelSize)
    [ln_result, lb_result]

var bool legDone     = false
var int  legDoneBar  = na
var bool slFrozen    = false
var bool entryFrozen = false
var bool tp1Frozen   = false
var bool tp15Frozen  = false
var bool tp2Frozen   = false
var bool tp3Frozen   = false

bool slShowVis    = slFeatureOn    and (utVizGate or slFrozen or legDone)
bool tpShowVis    = tpFeatureOn    and (utVizGate or tp1Frozen or tp15Frozen or tp2Frozen or tp3Frozen or legDone)
bool entryShowVis = entryFeatureOn and (utVizGate or entryFrozen or legDone)

var bool tp1Hit  = false
var bool tp15Hit = false
var bool tp2Hit  = false
var bool tp3Hit  = false

const int MAX_SIGNAL_LABELS = 30
var array<label> signalLabels = array.new<label>()

capX2(int x) =>
    not na(legDoneBar) ? math.min(x, legDoneBar) : x
var table wm = table.new(position.bottom_right, 1, 1)
if barstate.isfirst
    table.cell(wm, 0, 0, "Telegram @SimpleForexTools", text_color = color.new(color.gray, 70), text_size = size.large)

plot(utShowLine ? xATRTrailingStop : na, title="UT Trailing Stop", color=color.orange, linewidth=2)
plot(i_showStLine ? stValue : na, title="SuperTrend", color=stBullish ? color.green : color.red, linewidth=2, style=plot.style_linebr)

bool utPlotGate = utShowLabels and utVizGate

if utPlotGate and utBuy
    label newLbl = label.new(bar_index, low, "Buy", style=label.style_label_up, color=color.aqua, textcolor=color.white, size=labelSize)
    array.push(signalLabels, newLbl)
    if array.size(signalLabels) > MAX_SIGNAL_LABELS
        label.delete(array.shift(signalLabels))
if utPlotGate and utSell
    label newLbl = label.new(bar_index, high, "Sell", style=label.style_label_down, color=color.orange, textcolor=color.white, size=labelSize)
    array.push(signalLabels, newLbl)
    if array.size(signalLabels) > MAX_SIGNAL_LABELS
        label.delete(array.shift(signalLabels))
barcolor(utColorBars ? (barbuy ? color.aqua : barsell ? color.orange : na) : na)

bool ribbon_active = utShowRibbon

color ribbonBaseColor = barbuy ? #00CED1 : #FF6B6B

get_ribbon_layer(float _start, float _end, int _step) =>
    (_start * (15 - _step) + _end * _step) / 15

float rl1  = ribbon_active ? close : na
float rl2  = ribbon_active ? get_ribbon_layer(close, xATRTrailingStop, 1) : na
float rl3  = ribbon_active ? get_ribbon_layer(close, xATRTrailingStop, 2) : na
float rl4  = ribbon_active ? get_ribbon_layer(close, xATRTrailingStop, 3) : na
float rl5  = ribbon_active ? get_ribbon_layer(close, xATRTrailingStop, 4) : na
float rl6  = ribbon_active ? get_ribbon_layer(close, xATRTrailingStop, 5) : na
float rl7  = ribbon_active ? get_ribbon_layer(close, xATRTrailingStop, 6) : na
float rl8  = ribbon_active ? get_ribbon_layer(close, xATRTrailingStop, 7) : na
float rl9  = ribbon_active ? get_ribbon_layer(close, xATRTrailingStop, 8) : na
float rl10 = ribbon_active ? get_ribbon_layer(close, xATRTrailingStop, 9) : na
float rl11 = ribbon_active ? get_ribbon_layer(close, xATRTrailingStop, 10) : na
float rl12 = ribbon_active ? get_ribbon_layer(close, xATRTrailingStop, 11) : na
float rl13 = ribbon_active ? get_ribbon_layer(close, xATRTrailingStop, 12) : na
float rl14 = ribbon_active ? get_ribbon_layer(close, xATRTrailingStop, 13) : na
float rl15 = ribbon_active ? get_ribbon_layer(close, xATRTrailingStop, 14) : na
float rl16 = ribbon_active ? xATRTrailingStop : na

color rc1  = ribbon_active ? color.new(ribbonBaseColor, 85) : na
color rc2  = ribbon_active ? color.new(ribbonBaseColor, 81) : na
color rc3  = ribbon_active ? color.new(ribbonBaseColor, 77) : na
color rc4  = ribbon_active ? color.new(ribbonBaseColor, 73) : na
color rc5  = ribbon_active ? color.new(ribbonBaseColor, 69) : na
color rc6  = ribbon_active ? color.new(ribbonBaseColor, 65) : na
color rc7  = ribbon_active ? color.new(ribbonBaseColor, 61) : na
color rc8  = ribbon_active ? color.new(ribbonBaseColor, 57) : na
color rc9  = ribbon_active ? color.new(ribbonBaseColor, 53) : na
color rc10 = ribbon_active ? color.new(ribbonBaseColor, 49) : na
color rc11 = ribbon_active ? color.new(ribbonBaseColor, 45) : na
color rc12 = ribbon_active ? color.new(ribbonBaseColor, 41) : na
color rc13 = ribbon_active ? color.new(ribbonBaseColor, 37) : na
color rc14 = ribbon_active ? color.new(ribbonBaseColor, 33) : na
color rc15 = ribbon_active ? color.new(ribbonBaseColor, 30) : na

rp1  = plot(rl1,  display=display.none, editable=false)
rp2  = plot(rl2,  display=display.none, editable=false)
rp3  = plot(rl3,  display=display.none, editable=false)
rp4  = plot(rl4,  display=display.none, editable=false)
rp5  = plot(rl5,  display=display.none, editable=false)
rp6  = plot(rl6,  display=display.none, editable=false)
rp7  = plot(rl7,  display=display.none, editable=false)
rp8  = plot(rl8,  display=display.none, editable=false)
rp9  = plot(rl9,  display=display.none, editable=false)
rp10 = plot(rl10, display=display.none, editable=false)
rp11 = plot(rl11, display=display.none, editable=false)
rp12 = plot(rl12, display=display.none, editable=false)
rp13 = plot(rl13, display=display.none, editable=false)
rp14 = plot(rl14, display=display.none, editable=false)
rp15 = plot(rl15, display=display.none, editable=false)
rp16 = plot(rl16, display=display.none, editable=false)

fill(rp1,  rp2,  ribbon_active ? rc1  : na, editable=false)
fill(rp2,  rp3,  ribbon_active ? rc2  : na, editable=false)
fill(rp3,  rp4,  ribbon_active ? rc3  : na, editable=false)
fill(rp4,  rp5,  ribbon_active ? rc4  : na, editable=false)
fill(rp5,  rp6,  ribbon_active ? rc5  : na, editable=false)
fill(rp6,  rp7,  ribbon_active ? rc6  : na, editable=false)
fill(rp7,  rp8,  ribbon_active ? rc7  : na, editable=false)
fill(rp8,  rp9,  ribbon_active ? rc8  : na, editable=false)
fill(rp9,  rp10, ribbon_active ? rc9  : na, editable=false)
fill(rp10, rp11, ribbon_active ? rc10 : na, editable=false)
fill(rp11, rp12, ribbon_active ? rc11 : na, editable=false)
fill(rp12, rp13, ribbon_active ? rc12 : na, editable=false)
fill(rp13, rp14, ribbon_active ? rc13 : na, editable=false)
fill(rp14, rp15, ribbon_active ? rc14 : na, editable=false)
fill(rp15, rp16, ribbon_active ? rc15 : na, editable=false)

int PRED_BOXES_PER_SET = 30

bool pred_draw_flip = pred_flip and utVizGate

if i_enablePrediction and pred_draw_flip

    float pe = (na(pred_end) or pred_end <= 0) ? 16.0 : pred_end
    float pa = na(pred_avg) ? pe / 2.0 : pred_avg
    bool  peFallback = pred_using_fallback or na(pred_end) or pred_end <= 0
    bool  isBull = pred_is_bullish
    color base_col = isBull ? color.green : color.red

    if array.size(pred_boxes) > 0
        for i = 0 to array.size(pred_boxes) - 1
            box.delete(array.get(pred_boxes, i))
    array.clear(pred_boxes)
    if array.size(pred_labels) > 0
        for i = 0 to array.size(pred_labels) - 1
            label.delete(array.get(pred_labels, i))
    array.clear(pred_labels)

    float predATR = ta.atr(14)
    float box_height = predATR * 0.12
    float box_top = na
    float box_bottom = na
    if isBull
        box_top := xATRTrailingStop - predATR * 0.03
        box_bottom := box_top - box_height
    else
        box_bottom := xATRTrailingStop + predATR * 0.03
        box_top := box_bottom + box_height

    float box_width = pe / PRED_BOXES_PER_SET
    array<int> relevant = isBull ? pred_bull_durations : pred_bear_durations
    array<int> survArr = array.size(relevant) >= 3 ? relevant : pred_all_durations

    if i_showPredBoxes
        for i = 0 to PRED_BOXES_PER_SET - 1
            int box_left  = bar_index + int(i * box_width)
            int box_right = bar_index + math.max(int((i + 1) * box_width), int(i * box_width) + 1)
            int opacity = 5 + int((i / 29.0) * 90)
            box nb = box.new(box_left, box_top, box_right, box_bottom, bgcolor=color.new(base_col, opacity), border_color=na)
            array.push(pred_boxes, nb)

        int header_samples = peFallback ? array.size(pred_all_durations) : array.size(relevant)
        string direction_str = isBull ? "BULLISH" : "BEARISH"
        string confidence_str = header_samples >= 30 ? "High" : header_samples >= 15 ? "Medium" : "Low"
        string fallback_note = peFallback ? "\n⚠️ Not enough " + direction_str + "-only history yet - rough estimate, sharpens as more trends complete.\n" : ""
        string header_tooltip = "📊 TREND FORECAST\n═══════════════════════\n\n🎯 Direction: " + direction_str + "\n📈 Mode: " + i_predMode + "\n\n⏱️ DURATION ESTIMATE:\n• Predicted total: " + str.tostring(pe, "#") + " bars\n• Average: " + str.tostring(pa, "#.#") + " bars\n" + fallback_note + "\n📊 DATA:\n• Sample Size: " + str.tostring(header_samples) + " trends\n• Confidence: " + confidence_str + "\n\n" + (i_predMode == "Advanced" and not peFallback ? "🔬 ADVANCED MULTIPLIERS:\n• Structure • Asset Type • Flip Strength\n• Error Learning • Regime\n\n" : "") + "💡 % labels = share of past " + direction_str + " trends that lasted at least that long.\n\n⚠️ Historical analysis, not a guarantee."
        int center_bar = bar_index + int(pe / 2)
        label lbl_center = label.new(center_bar, box_top, "🔮 Trend Analysis", style=isBull ? label.style_label_down : label.style_label_up, color=color.new(color.blue, 0), textcolor=color.white, size=size.small, tooltip=header_tooltip, yloc=yloc.price)
        array.push(pred_labels, lbl_center)

    if i_showPredLabels
        int survN = array.size(survArr)

        array<int> survPct = array.from(25, 50, 75, 90)

        float lbl_y = isBull ? box_bottom - predATR * 0.15 : low - predATR * 0.5
        for q in survPct
            int surv = 100 - q

            float dur = survN >= 4 ? array.percentile_nearest_rank(survArr, q) : pe * (q / 100.0)
            int x = bar_index + math.max(1, int(dur))
            string direction = isBull ? "BULL" : "BEAR"
            string lbl_tooltip = "🎯 Trend Survival\n\n" + str.tostring(surv) + "% of past " + direction + " trends lasted at least ~" + str.tostring(int(dur)) + " bars from the flip.\n\nBased on " + str.tostring(survN) + " past trends" + (survN >= 4 ? "" : " (modeled - low history)")
            label lbl_prob = label.new(x, lbl_y, str.tostring(surv) + "%", style=label.style_none, textcolor=base_col, text_formatting=text.format_bold, size=size.small, yloc=yloc.price, tooltip=lbl_tooltip)
            array.push(pred_labels, lbl_prob)

if i_showDivergence and bullishDiv
    string bullDivTooltip = "🟢 BULLISH DIVERGENCE\n\nPrice: Lower Low ↘\nRSI: Higher Low ↗\n\nPrevious Price Low: " + str.tostring(prevPriceLow, "#.##") + "\n" + "Current Price Low: " + str.tostring(pivotLow, "#.##") + "\n" + "Previous RSI Low: " + str.tostring(prevRsiLow, "#.#") + "\n" + "Current RSI Low: " + str.tostring(rsiPivotLow, "#.#") + "\n\n" + "📈 SIGNAL: Potential reversal UP\n" + "Selling pressure weakening despite lower prices"
    label.new(bar_index - i_divLookback, low[i_divLookback], "Bull\nDiv",
              style=label.style_label_up, color=color.new(color.green, 30),
              textcolor=color.white, size=labelSize, tooltip=bullDivTooltip)

if i_showDivergence and bearishDiv
    string bearDivTooltip = "🔴 BEARISH DIVERGENCE\n\n" + "Price: Higher High ↗\n" + "RSI: Lower High ↘\n\n" + "Previous Price High: " + str.tostring(prevPriceHigh, "#.##") + "\n" + "Current Price High: " + str.tostring(pivotHigh, "#.##") + "\n" + "Previous RSI High: " + str.tostring(prevRsiHigh, "#.#") + "\n" + "Current RSI High: " + str.tostring(rsiPivotHigh, "#.#") + "\n\n" + "📉 SIGNAL: Potential reversal DOWN\n" + "Buying pressure weakening despite higher prices" 
    label.new(bar_index - i_divLookback, high[i_divLookback], "Bear\nDiv",
              style=label.style_label_down, color=color.new(color.red, 30),
              textcolor=color.white, size=labelSize, tooltip=bearDivTooltip)

slBuf = xATR * 0.10

slATR = ta.atr(slAtrLen)
atrPercent = close != 0 ? (slATR / close * 100) : 1.0

calcLongSL(_entry) =>
    float sl = na
    float tickValue = syminfo.mintick

    if slMethod == "ATR"

        sl := _entry - (slATR * slAtrMult)

    else if slMethod == "% Based"

        sl := _entry * (1 - slPctStop / 100)

    else if slMethod == "Tick Based"

        sl := _entry - (slTickStop * tickValue)

    else if slMethod == "Swing"

        float swingFloor = ta.lowest(low, swingLen)
        sl := not na(swingFloor) and swingFloor < _entry ? swingFloor : _entry - slATR * 1.5

    else if slMethod == "Scaled ATR"

        float scaledMult = atrPercent > 5 ? 2.5 :
                          atrPercent > 3 ? 2.0 :
                          atrPercent > 1.5 ? 1.5 : 1.2
        float atrDist = slATR * s

Показано первые 50% кода (символов: 94087)

Открыть по тарифу

Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.

Разовая покупка файла

На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.

Чтобы оформить заказ, введите email и перейдите к оплате.

Стоимость полного кода
9 408,70₽ ≈ $114.99