SMC Confluence Suite
Похожие материалы по тегам
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «indicator smc confluence suite for tradingview.pine» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
SMC Confluence Suite — это индикатор для TradingView, который анализирует рыночную структуру на основе концепций SMC. Он отображает на графике прорывы структуры (BOS), смену характера (CHoCH), зоны справедливой стоимости (FVG), ордер-блоки и зоны оптимального входа (OTE). Индикатор работает поверх графика и поддерживает мультитаймфреймный анализ через получение данных с двух дополнительных таймфреймов.
Индикатор предоставляет визуальное отображение множества зон: премиум/дисконт, ликвидностные спреды, равные уровни (EQH/EQL), а также зоны с совпадением факторов (confluence). Все визуальные объекты ограничиваются настраиваемым максимальным количеством, чтобы избежать перегрузки графика. Доступны теги для максимумов и минимумов, цветовое кодирование бычьих и медвежьих зон.
Встроена система оценки совпадения факторов (Confluence Score) от 0 до 100 с буквенной оценкой и таблицей разбора каждого фактора. Индикатор рассчитывает параметры управления риском: размер позиции, стоп-лосс, тейк-профиты и соотношение риск/прибыль на основе заданного баланса аккаунта и процента риска.
Алертная система поддерживает множество настраиваемых событий — от структурных Break/Change до касаний зон и пересечения порога оценки. Действует охлаждение между оповещениями, фильтр по времени закрытия свечи и настраиваемые префиксы сообщений. На графике отображается панель с текущей информацией о настройке и статистикой оповещений.
Настройки программы
| Настройка | Описание |
|---|---|
| leftLen | Длина свинга слева — Количество баров слева для поиска свинг-хай/лоу. |
| rightLen | Длина свинга справа — Количество баров справа для поиска свинг-хай/лоу. |
| bosUseWick | Подтверждать BOS тенями — Подтверждение прорыва структуры по теням свечей вместо цен закрытия. |
| allowRetro | Разрешить ретро BOS — Разрешает отложенные прорывы структуры с поздним подтверждением. |
| maxObjects | Максимум линий/меток — Максимальное количество линий и меток, сохраняемых на графике. |
| tf1 | Таймфрейм 1 — Первый дополнительный таймфрейм для анализа структуры. |
| col1 | Цвет TF1 — Цвет отображения структуры на таймфрейме 1. |
| tf2 | Таймфрейм 2 — Второй дополнительный таймфрейм для анализа структуры. |
| col2 | Цвет TF2 — Цвет отображения структуры на таймфрейме 2. |
| show_tag | Показать метки High/Low — Отображает метки High/Low для свинг-поинтов. |
| show_fvg | Показать FVG — Отображает зоны справедливой стоимости (FVG). |
| fvgFilter | Фильтр размера FVG — Фильтр размера зон FVG: выключен, по пунктам, по ATR или оба. |
| fvgMinPts | Минимальный размер (пункты) — Минимальный размер зоны FVG в пунктах. |
| fvgMinAtr | Минимальный размер (x ATR) — Минимальный размер зоны FVG в кратных значениях ATR. |
| fvgAtrLen | Длина ATR — Период расчёта ATR для фильтра размера FVG. |
| maxFvgZones | Максимум зон FVG — Максимальное количество хранимых зон FVG на графике. |
| fvg_col_bull | Бычий цвет FVG — Цвет бычьих зон FVG. |
| fvg_col_bear | Медвежий цвет FVG — Цвет медвежьих зон FVG. |
| show_ob | Показать ордер-блоки — Отображает ордер-блоки. |
| obMode | Режим обнаружения ордер-блоков — Режим обнаружения ордер-блоков: на основе BOS (SMC) или смещение (устаревший). |
| obSource | Источник структуры — Источник структуры для обнаружения ордер-блоков: TF1, TF2 или оба. |
| obLookback | Глубина поиска ордер-блока (бары) — Глубина поиска ордер-блока в количестве баров. |
| obFallback | Использовать экстремальный бар как запас — При отсутствии противоположной свечи использовать экстремальный бар для поиска ордер-блока. |
| useExtFilter | Включить фильтр экстремальных ордер-блоков — Включает фильтр экстремальных ордер-блоков, ограничивая количество отображаемых. |
| max_ob_show | Максимум OB на свинг — Максимальное количество отображаемых ордер-блоков на один свинг. |
| maxObZones | Максимум ордер-блоков (на сторону) — Максимальное количество хранимых ордер-блоков на каждую сторону. |
| ob_col_bull | Бычий цвет ордер-блоков — Цвет бычьих ордер-блоков. |
| ob_col_bear | Медвежий цвет ордер-блоков — Цвет медвежьих ордер-блоков. |
| mitigMode | Режим митигации — Режим митигации зон: по касанию, заполнение на 50% или полное заполнение. |
| showZoneTxt | Показать метку внутри зоны — Отображает текстовую метку внутри зоны (ордер-блок/FVG). |
| zoneTxtDir | Добавить направление к метке — Добавляет направление (OB BUY / FVG SELL) к тексту метки внутри зоны. |
| zoneTxtCol | Цвет текста в зоне — Цвет текста внутри зон. |
| zoneTxtSize | Размер текста в зоне — Размер текста внутри зон: мелкий, малый, нормальный, большой. |
| show_ote | Показать зону OTE — Отображает зоны оптимального входа (OTE). |
| oteShallow | Неглубокий уровень OTE — Неглубинный уровень OTE как доля расстояния. |
| oteMid | Средний уровень OTE (вход) — Средний уровень OTE, используемый как точка входа. |
| oteDeep | Глубокий уровень OTE — Глубина зоны OTE (глубокий уровень) как доля расстояния. |
| snapEntry | Привязка входа к зоне совпадения — Привязка точки входа к ближайшей зоне совпадения факторов. |
| tp2Ext | Расширение Фибоначчи для TP2 — Расширение Фибоначчи для второго тейк-профита. |
| ote_col | Цвет зоны OTE — Цвет зоны OTE. |
| oteConfCol | Цвет границы при совпадении — Цвет границы зоны OTE при наличии совпадения факторов. |
| acc_size | Баланс аккаунта ($) — Баланс аккаунта в долларах для расчёта размера позиции. |
| risk_pct | Риск на сделку (%) — Процент риска на одну сделку от баланса аккаунта. |
| slBuffer | Отступ стоп-лосса (пункты) — Отступ стоп-лосса в пунктах от уровня. |
| autoPV | Автоматическая стоимость пункта — Автоматическое определение стоимости пункта на основе символа. |
| manualPV | Стоимость пункта на лот ($) — Стоимость пункта на лот в долларах (используется при отключённом авто-определении). |
| show_pd | Показать премиум/дисконт — Отображает зоны премиума и дисконта. |
| pdMode | Фильтр премиум/дисконт — Фильтр премиум/дисконт для ордер-блоков и FVG: выключен, исключить, затемнить. |
| pdShowEq | Показать линию равенства (50%) — Отображение линии равенства (50%) между последними свинг-хаем и лоу. |
| pdPremCol | Цвет премиума — Цвет зоны премиума. |
| pdDiscCol | Цвет дисконта — Цвет зоны дисконта. |
| pdEqCol | Цвет линии равенства — Цвет линии равенства (50%). |
| show_sweep | Показать ликвидностные спреды — Отображает ликвидностные спреды (прорисовку ликвидности). |
| swpLeft | Пивот слева (бары) — Количество баров слева для определения пивота ликвидностного спреда. |
| swpRight | Пивот справа (бары) — Количество баров справа для определения пивота ликвидностного спреда. |
| sweepMinPen | Минимальное проникновение (x ATR) — Минимальное проникновение ликвидности в кратных значениях ATR. |
| sweepNeedBack | Требовать возврат внутрь уровня — Требовать закрытие цены обратно внутри уровня после спреда. |
| sweepUpCol | Цвет спреда на максимуме — Цвет спреда на максимуме (покупка). |
| sweepDnCol | Цвет спреда на минимуме — Цвет спреда на минимуме (продажа). |
| show_eq | Показать EQH/EQL — Отображает линии равных максимумов и минимумов (EQH/EQL). |
| eqTol | Допуск равных уровней (x ATR) — Допуск равенства уровней в кратных значениях ATR. |
| eqCol | Цвет линии EQ — Цвет линий равных уровней (EQH/EQL). |
| useScore | Включить оценку совпадения — Включает систему оценки совпадения факторов (Confluence Score). |
| showScoreP | Показать таблицу разбора оценки — Отображает таблицу разбора факторов оценки совпадения. |
| scDecay | Срок жизни сигнала (бары) — Количество баров до обнуления свежести сигнала в оценке. |
| scRrTarget | R:R для полной оценки — Соотношение риск/прибыль, за которое начисляется полная оценка. |
| scAlertLv | Порог оценки для оповещения — Порог оценки совпадения факторов для срабатывания оповещения. |
| scBgTint | Заливка фона выше порога — Заливка фона графика при превышении порога оценки. |
| w_struct | Вес свежей структуры TF1 — Вес свежего прорыва/смены характера на таймфрейме 1 в формуле оценки. |
| w_htf | Вес тренда TF2 — Вес совпадения тренда на таймфрейме 2 в формуле оценки. |
| w_ob | Вес ордер-блока внутри OTE — Вес ордер-блока внутри OTE в формуле оценки. |
| w_fvg | Вес FVG внутри OTE — Вес зоны FVG внутри OTE в формуле оценки. |
| w_pd | Вес стороны равенства — Вес правильной стороны равенства в формуле оценки. |
| w_sweep | Вес подтверждающего спреда — Вес подтверждающего спреда в формуле оценки. |
| w_ote | Вес цены внутри OTE — Вес нахождения цены внутри зоны OTE в формуле оценки. |
| w_rr | Вес качества R:R — Вес качества соотношения риск/прибыль в формуле оценки. |
| w_fresh | Вес свежих зон — Вес свежих (нетронутых) зон в формуле оценки. |
| alertMasterStr | Оповещения — Главный переключатель всех оповещений: включить или отключить. |
| alertOnClose | Срабатывать при закрытии свечи — Оповещение срабатывает только при закрытии свечи (если отключено — внутри свечи, может перерисовываться). |
| alertCooldown | Пауза между оповещениями (бары) — Количество баров между оповещениями одного типа (0 — без ограничений). |
| alertPrefix | Префикс сообщения — Префикс в тексте оповещения. |
| a_bos1 | BOS таймфрейм 1 — Включает оповещение при прорыве структуры (BOS) на таймфрейме 1. |
| a_choch1 | CHoCH таймфрейм 1 — Включает оповещение при смене характера (CHoCH) на таймфрейме 1. |
| a_bos2 | BOS таймфрейм 2 — Включает оповещение при прорыве структуры (BOS) на таймфрейме 2. |
| a_choch2 | CHoCH таймфрейм 2 — Включает оповещение при смене характера (CHoCH) на таймфрейме 2. |
| a_retro | Включить ретро BOS — Включает отслеживание отложенных (ретро) прорывов структуры в оповещениях. |
| a_newOb | Новый ордер-блок — Включает оповещение при появлении нового ордер-блока. |
| a_newFvg | Новый FVG — Включает оповещение при появлении новой зоны справедливой стоимости (FVG). |
| a_touchOb | Цена касается ордер-блока — Включает оповещение при касании цены ордер-блока. |
| a_touchFvg | Цена касается FVG — Включает оповещение при касании цены зоны FVG. |
| a_newOte | Новая зона OTE — Включает оповещение при появлении новой зоны OTE. |
| a_enterOte | Цена входит в OTE — Включает оповещение при входе цены в зону OTE. |
| a_sweep | Ликвидностный спред — Включает оповещение при обнаружении ликвидностного спреда. |
| a_eq | Формирование EQH/EQL — Включает оповещение при формировании равных максимумов/минимумов (EQH/EQL). |
| a_score | Оценка пересекает порог — Включает оповещение при пересечении порога оценки совпадения факторов. |
| show_dash | Показать панель сигналов — Отображает панель сигналов в правом верхнем углу графика. |
| showAlertRow | Показать диагностику оповещений — Показывает строку диагностики оповещений на панели (количество отправленных оповещений). |
| dashSize | Размер шрифта дашборда — Размер шрифта панели сигналов на графике. |
Поиск по коду файла
indicator("SMC Confluence Suite", overlay = true, max_lines_count = 500, max_labels_count = 500, max_boxes_count = 500)
DSP_OFF = display.data_window
DSP_ON = display.status_line + display.data_window
var string GRP_STRUCT = "1 · Market Structure"
var string GRP_MTF = "2 · Multi-Timeframe Swings"
var string GRP_FVG = "3 · Fair Value Gap"
var string GRP_OB = "4 · Order Block"
var string GRP_ZONE = "5 · Zone Display"
var string GRP_RISK = "6 · OTE & Risk Management"
var string GRP_PD = "7 · Premium / Discount"
var string GRP_LIQ = "8 · Liquidity"
var string GRP_SCORE = "9 · Confluence Score"
var string GRP_ALERT = "10 · Alerts"
var string GRP_DASH = "11 · Dashboard"
leftLen = input.int(5, "Swing Left Length", group = GRP_STRUCT, minval = 1, display = DSP_OFF)
rightLen = input.int(5, "Swing Right Length", group = GRP_STRUCT, minval = 1, display = DSP_OFF)
bosUseWick = input.bool(false, "Confirm BOS with wicks", group = GRP_STRUCT, display = DSP_OFF)
allowRetro = input.bool(true, "Allow Retro BOS (late confirmation)", group = GRP_STRUCT, display = DSP_OFF)
maxObjects = input.int(300, "Max lines / labels kept", group = GRP_STRUCT, minval = 50, maxval = 480, display = DSP_OFF)
tf1 = input.timeframe("15", "Timeframe 1", group = GRP_MTF, display = DSP_OFF)
col1 = input.color(color.aqua, "TF1 colour", group = GRP_MTF, inline = "c1", display = DSP_OFF)
tf2 = input.timeframe("60", "Timeframe 2", group = GRP_MTF, display = DSP_OFF)
col2 = input.color(color.orange, "TF2 colour", group = GRP_MTF, inline = "c2", display = DSP_OFF)
show_tag = input.bool(true, "Show High / Low tags", group = GRP_MTF, display = DSP_OFF)
show_fvg = input.bool(true, "Show FVG", group = GRP_FVG, display = DSP_OFF)
fvgFilter = input.string("ATR", "Size filter", options = ["Off", "Points", "ATR", "Both"], group = GRP_FVG, display = DSP_OFF)
fvgMinPts = input.float(50, "Min size (points)", group = GRP_FVG, minval = 0, step = 10, display = DSP_OFF)
fvgMinAtr = input.float(0.25, "Min size (x ATR)", group = GRP_FVG, minval = 0, step = 0.05, display = DSP_OFF)
fvgAtrLen = input.int(14, "ATR length", group = GRP_FVG, minval = 1, display = DSP_OFF)
maxFvgZones = input.int(30, "Max FVG kept", group = GRP_FVG, minval = 1, maxval = 150, display = DSP_OFF)
fvg_col_bull = input.color(color.new(color.green, 80), "Bullish", group = GRP_FVG, inline = "f", display = DSP_OFF)
fvg_col_bear = input.color(color.new(color.red, 80), "Bearish", group = GRP_FVG, inline = "f", display = DSP_OFF)
show_ob = input.bool(true, "Show Order Blocks", group = GRP_OB, display = DSP_OFF)
obMode = input.string("BOS-based (SMC)", "Detection mode", options = ["BOS-based (SMC)", "Displacement (Legacy)"], group = GRP_OB, display = DSP_OFF)
obSource = input.string("Both", "Structure source", options = ["TF1", "TF2", "Both"], group = GRP_OB, display = DSP_OFF)
obLookback = input.int(15, "Displacement lookback (bars)", group = GRP_OB, minval = 2, maxval = 50, display = DSP_OFF)
obFallback = input.bool(true, "Fall back to extreme bar if no opposite candle", group = GRP_OB, display = DSP_OFF)
useExtFilter = input.bool(false, "Enable extreme-OB filter", group = GRP_OB, display = DSP_OFF)
max_ob_show = input.int(2, "Max OB per swing", group = GRP_OB, minval = 1, display = DSP_OFF)
maxObZones = input.int(20, "Max OB kept (per side)", group = GRP_OB, minval = 1, maxval = 100, display = DSP_OFF)
ob_col_bull = input.color(color.new(color.blue, 70), "Bullish", group = GRP_OB, inline = "o", display = DSP_OFF)
ob_col_bear = input.color(color.new(color.orange, 70), "Bearish", group = GRP_OB, inline = "o", display = DSP_OFF)
mitigMode = input.string("50% Fill", "Mitigation mode", options = ["Touch", "50% Fill", "Full Fill"], group = GRP_ZONE, display = DSP_OFF)
showZoneTxt = input.bool(true, "Show label inside zone", group = GRP_ZONE, display = DSP_OFF)
zoneTxtDir = input.bool(false, "Append direction (OB BUY / FVG SELL)", group = GRP_ZONE, display = DSP_OFF)
zoneTxtCol = input.color(color.white, "Text colour", group = GRP_ZONE, inline = "zt", display = DSP_OFF)
zoneTxtSize = input.string("Small", "Size", options = ["Tiny", "Small", "Normal", "Large"], group = GRP_ZONE, inline = "zt", display = DSP_OFF)
show_ote = input.bool(true, "Show OTE zone", group = GRP_RISK, display = DSP_OFF)
oteShallow = input.float(0.62, "OTE shallow", group = GRP_RISK, minval = 0.1, maxval = 1.0, step = 0.005, display = DSP_OFF)
oteMid = input.float(0.705, "OTE mid (entry)", group = GRP_RISK, minval = 0.1, maxval = 1.0, step = 0.005, display = DSP_OFF)
oteDeep = input.float(0.79, "OTE deep", group = GRP_RISK, minval = 0.1, maxval = 1.0, step = 0.005, display = DSP_OFF)
snapEntry = input.bool(true, "Snap entry to confluence zone", group = GRP_RISK, display = DSP_OFF)
tp2Ext = input.float(0.5, "TP2 fib extension", group = GRP_RISK, minval = 0.1, step = 0.1, display = DSP_OFF)
ote_col = input.color(color.new(color.purple, 70), "OTE zone colour", group = GRP_RISK, display = DSP_OFF)
oteConfCol = input.color(color.lime, "Border colour when confluent", group = GRP_RISK, display = DSP_OFF)
acc_size = input.float(1000.0, "Account balance ($)", group = GRP_RISK, minval = 1, display = DSP_OFF)
risk_pct = input.float(1.0, "Risk per trade (%)", group = GRP_RISK, step = 0.1, minval = 0.1, display = DSP_OFF)
slBuffer = input.float(100, "SL buffer (points)", group = GRP_RISK, step = 1, minval = 0, display = DSP_OFF) / 100
autoPV = input.bool(false, "Auto point value", group = GRP_RISK, display = DSP_OFF)
manualPV = input.float(100, "Point value per lot ($)", group = GRP_RISK, minval = 0.0001, display = DSP_OFF)
show_pd = input.bool(true, "Show Premium / Discount zones", group = GRP_PD, display = DSP_OFF)
pdMode = input.string("Dim Only", "P/D filter for OB & FVG", options = ["Off", "Filter Out", "Dim Only"], group = GRP_PD, display = DSP_OFF)
pdShowEq = input.bool(true, "Show equilibrium line (50%)", group = GRP_PD, display = DSP_OFF)
pdPremCol = input.color(color.new(color.red, 92), "Premium", group = GRP_PD, inline = "pd", display = DSP_OFF)
pdDiscCol = input.color(color.new(color.green, 92), "Discount", group = GRP_PD, inline = "pd", display = DSP_OFF)
pdEqCol = input.color(color.new(color.gray, 40), "EQ line", group = GRP_PD, display = DSP_OFF)
show_sweep = input.bool(true, "Show liquidity sweeps", group = GRP_LIQ, display = DSP_OFF)
swpLeft = input.int(5, "Sweep pivot left", group = GRP_LIQ, minval = 1, inline = "sp", display = DSP_OFF)
swpRight = input.int(2, "Right", group = GRP_LIQ, minval = 1, inline = "sp", display = DSP_OFF)
sweepMinPen = input.float(0.05, "Min penetration (x ATR)", group = GRP_LIQ, minval = 0, step = 0.05, display = DSP_OFF)
sweepNeedBack = input.bool(true, "Require close back inside level", group = GRP_LIQ, display = DSP_OFF)
sweepUpCol = input.color(color.red, "Sweep high", group = GRP_LIQ, inline = "sc", display = DSP_OFF)
sweepDnCol = input.color(color.lime, "Sweep low", group = GRP_LIQ, inline = "sc", display = DSP_OFF)
show_eq = input.bool(true, "Show EQH / EQL", group = GRP_LIQ, display = DSP_OFF)
eqTol = input.float(0.10, "Equal-level tolerance (x ATR)", group = GRP_LIQ, minval = 0.01, step = 0.05, display = DSP_OFF)
eqCol = input.color(color.new(color.yellow, 20), "EQ line colour", group = GRP_LIQ, display = DSP_OFF)
useScore = input.bool(true, "Enable Confluence Score", group = GRP_SCORE, display = DSP_OFF)
showScoreP = input.bool(true, "Show score breakdown table", group = GRP_SCORE, display = DSP_OFF)
scDecay = input.int(20, "Signal lifespan before score decays to 0 (bars)", group = GRP_SCORE, minval = 1, maxval = 500, display = DSP_OFF)
scRrTarget = input.float(2.0, "R:R that earns full credit", group = GRP_SCORE, minval = 0.5, step = 0.5, display = DSP_OFF)
scAlertLv = input.int(70, "Alert threshold", group = GRP_SCORE, minval = 0, maxval = 100, display = DSP_OFF)
scBgTint = input.bool(false, "Tint background above threshold", group = GRP_SCORE, display = DSP_OFF)
w_struct = input.float(20, "1 · Fresh BOS/CHoCH (TF1)", group = GRP_SCORE, minval = 0, maxval = 50, step = 5, display = DSP_OFF)
w_htf = input.float(15, "2 · TF2 trend aligned", group = GRP_SCORE, minval = 0, maxval = 50, step = 5, display = DSP_OFF)
w_ob = input.float(15, "3 · OB inside OTE", group = GRP_SCORE, minval = 0, maxval = 50, step = 5, display = DSP_OFF)
w_fvg = input.float(10, "4 · FVG inside OTE", group = GRP_SCORE, minval = 0, maxval = 50, step = 5, display = DSP_OFF)
w_pd = input.float(15, "5 · Correct side of EQ", group = GRP_SCORE, minval = 0, maxval = 50, step = 5, display = DSP_OFF)
w_sweep = input.float(10, "6 · Supporting sweep", group = GRP_SCORE, minval = 0, maxval = 50, step = 5, display = DSP_OFF)
w_ote = input.float(10, "7 · Price inside OTE", group = GRP_SCORE, minval = 0, maxval = 50, step = 5, display = DSP_OFF)
w_rr = input.float(10, "8 · R:R quality", group = GRP_SCORE, minval = 0, maxval = 50, step = 5, display = DSP_OFF)
w_fresh = input.float(5, "9 · Untouched zones left", group = GRP_SCORE, minval = 0, maxval = 50, step = 5, display = DSP_OFF)
alertMasterStr = input.string("ON", "Alerts", options = ["ON", "OFF"], group = GRP_ALERT, display = DSP_ON)
bool alertMaster = alertMasterStr == "ON"
alertOnClose = input.bool(true, "Fire on bar close only", group = GRP_ALERT, tooltip = "OFF = intrabar (may repaint within the bar)", display = DSP_OFF)
alertCooldown = input.int(0, "Cooldown per event type (bars)", group = GRP_ALERT, minval = 0, maxval = 200, tooltip = "0 = no throttling. Raise only if you get spammed.", display = DSP_OFF)
alertPrefix = input.string("SMC", "Message prefix", group = GRP_ALERT, display = DSP_OFF)
a_bos1 = input.bool(true, "BOS TF1", group = GRP_ALERT, inline = "a1", display = DSP_OFF)
a_choch1 = input.bool(true, "CHoCH TF1", group = GRP_ALERT, inline = "a1", display = DSP_OFF)
a_bos2 = input.bool(true, "BOS TF2", group = GRP_ALERT, inline = "a2", display = DSP_OFF)
a_choch2 = input.bool(true, "CHoCH TF2", group = GRP_ALERT, inline = "a2", display = DSP_OFF)
a_retro = input.bool(false, "Include Retro BOS*", group = GRP_ALERT, display = DSP_OFF)
a_newOb = input.bool(true, "New OB", group = GRP_ALERT, inline = "a3", display = DSP_OFF)
a_newFvg = input.bool(false, "New FVG", group = GRP_ALERT, inline = "a3", display = DSP_OFF)
a_touchOb = input.bool(true, "Price taps OB", group = GRP_ALERT, inline = "a4", display = DSP_OFF)
a_touchFvg = input.bool(false, "Price taps FVG", group = GRP_ALERT, inline = "a4", display = DSP_OFF)
a_newOte = input.bool(true, "New OTE zone", group = GRP_ALERT, inline = "a5", display = DSP_OFF)
a_enterOte = input.bool(true, "Price enters OTE", group = GRP_ALERT, inline = "a5", display = DSP_OFF)
a_sweep = input.bool(true, "Liquidity sweep", group = GRP_ALERT, inline = "a6", display = DSP_OFF)
a_eq = input.bool(false, "EQH / EQL formed", group = GRP_ALERT, inline = "a6", display = DSP_OFF)
a_score = input.bool(true, "Score crosses threshold", group = GRP_ALERT, display = DSP_OFF)
show_dash = input.bool(true, "Show signal dashboard", group = GRP_DASH, display = DSP_OFF)
showAlertRow = input.bool(false, "Show alert diagnostics row", group = GRP_DASH, tooltip = "Confirms the alert engine is actually firing", display = DSP_OFF)
dashSize = input.string("Small", "Dashboard font size", options = ["Tiny", "Small", "Normal"], group = GRP_DASH, display = DSP_OFF)
int chartSec = timeframe.in_seconds(timeframe.period)
bool tf1Valid = timeframe.in_seconds(tf1) >= chartSec
bool tf2Valid = timeframe.in_seconds(tf2) >= chartSec
bool tfWarn = not tf1Valid or not tf2Valid
string warnTxt = "Chart TF is higher than " + (not tf1Valid ? "TF1" : "") + (not tf1Valid and not tf2Valid ? " / " : "") + (not tf2Valid ? "TF2" : "") + " - that structure and its alerts are disabled"
string zTxtSize = zoneTxtSize == "Tiny" ? size.tiny : zoneTxtSize == "Small" ? size.small : zoneTxtSize == "Normal" ? size.normal : size.large
string dTxt = dashSize == "Tiny" ? size.tiny : dashSize == "Small" ? size.small : size.normal
float atrVal = ta.atr(fvgAtrLen)
float pointVal = autoPV ? (na(syminfo.pointvalue) or syminfo.pointvalue <= 0 ? manualPV : syminfo.pointvalue) : manualPV
type SwingPoint
int timeLoc
float price
int ptype
bool isBroken
int confirmTime
line ln
label lb
type StructState
SwingPoint lastSwing
SwingPoint lastHigh
SwingPoint lastLow
int trend
int seenH
int seenL
color col
bool enabled
int retroSig
int evt
bool evtChoch
bool evtRetro
float evtPrice
type Zone
box bx
float top
float bottom
int dir
int originTime
int birthTime
bool mitigated
string kind
bool touched // [K3] real state - drives freshness score
bool notified // [K3] alert de-duplication only
bool pdOk
var StructState st1 = StructState.new(na, na, na, 1, 0, 0, col1, false, 0, 0, false, false, na)
var StructState st2 = StructState.new(na, na, na, 1, 0, 0, col2, false, 0, 0, false, false, na)
var array<line> structLines = array.new<line>()
var array<label> structLabels = array.new<label>()
var array<Zone> fvgZones = array.new<Zone>()
var array<Zone> obBull = array.new<Zone>()
var array<Zone> obBear = array.new<Zone>()
var array<Zone> interBull = array.new<Zone>()
var array<Zone> interBear = array.new<Zone>()
int ID_BOS1 = 0
int ID_CHOCH1 = 1
int ID_BOS2 = 2
int ID_CHOCH2 = 3
int ID_NEWOB = 4
int ID_NEWFVG = 5
int ID_TOUCHOB = 6
int ID_TOUCHFVG = 7
int ID_NEWOTE = 8
int ID_ENTEROTE = 9
int ID_SWEEP = 10
int ID_EQ = 11
int ID_SCORE = 12
var array<int> alertClock = array.new<int>(13, -1000000)
var array<int> alertStat = array.new<int>(2, 0)
fire(int id, bool enabled, string msg) =>
bool sent = false
if alertMaster and enabled
int last = array.get(alertClock, id)
if bar_index - last >= alertCooldown
array.set(alertClock, id, bar_index)
array.set(alertStat, 0, array.get(alertStat, 0) + 1)
array.set(alertStat, 1, bar_index)
if alertOnClose
alert(msg, alert.freq_once_per_bar_close)
else
alert(msg, alert.freq_once_per_bar)
sent := true
sent
amsg(string body) =>
alertPrefix + " | " + syminfo.ticker + " " + timeframe.period + " | " + body + " @ " + str.tostring(close, format.mintick)
method destroy(Zone z) =>
box.delete(z.bx)
true
method isMitigated(Zone z) =>
float h = z.top - z.bottom
bool res = false
if h > 0
float pen = z.dir == 1 ? z.top - low : high - z.bottom
float ratio = pen / h
res := mitigMode == "Touch" ? ratio > 0 : mitigMode == "50% Fill" ? ratio >= 0.5 : ratio >= 1.0
res
new_zone(int t, float top, float bottom, int dir, color bg, color border, string kind, bool pdOk) =>
color useBg = pdOk ? bg : color.new(bg, 94)
color useBd = na(border) ? border : (pdOk ? border : color.new(border, 90))
string txt = (not showZoneTxt or not pdOk) ? "" : zoneTxtDir ? kind + (dir == 1 ? " BUY" : " SELL") : kind
box bx = box.new(left = t, top = top, right = t, bottom = bottom, border_color = useBd, border_style = line.style_solid, bgcolor = useBg, xloc = xloc.bar_time, extend = extend.right, text = txt, text_color = zoneTxtCol, text_halign = text.align_right, text_valign = text.align_center, text_size = zTxtSize)
Zone.new(bx, top, bottom, dir, t, time, false, kind, false, false, pdOk)
detach(array<Zone> arr, Zone z) =>
int i = array.indexof(arr, z)
if i >= 0
array.remove(arr, i)
true
has_zone_at(array<Zone> zones, int t) =>
bool found = false
int sz = array.size(zones)
if sz > 0
for i = 0 to sz - 1
if array.get(zones, i).originTime == t
found := true
break
found
scan_touch(array<Zone> zones, bool enabled, int id) =>
bool anyTouch = false
int sz = array.size(zones)
if sz > 0
for i = 0 to sz - 1
Zone z = array.get(zones, i)
if not z.touched and z.pdOk and time > z.birthTime and low <= z.top and high >= z.bottom
z.touched := true
anyTouch := true
if not z.notified
z.notified := true
string side = z.dir == 1 ? "Bullish" : "Bearish"
fire(id, enabled, amsg("Price tapped " + side + " " + z.kind + " [" + str.tostring(z.bottom, format.mintick) + " - " + str.tostring(z.top, format.mintick) + "]"))
anyTouch
count_fresh(array<Zone> zones) =>
int c = 0
int sz = array.size(zones)
if sz > 0
for i = 0 to sz - 1
Zone z = array.get(zones, i)
if z.pdOk and not z.touched
c += 1
c
manage_zones(array<Zone> zones, array<Zone> mirror, bool useMirror) =>
int sz = array.size(zones)
if sz > 0
for i = sz - 1 to 0
Zone z = array.get(zones, i)
if time > z.birthTime and z.isMitigated()
if useMirror
detach(mirror, z)
z.destroy()
array.remove(zones, i)
true
prune_zones(array<Zone> zones, array<Zone> mirror, bool useMirror, int maxN) =>
while array.size(zones) > maxN
Zone z = array.shift(zones)
if useMirror
detach(mirror, z)
z.destroy()
true
get_mtf_pivots(int left, int right) =>
float ph = ta.pivothigh(high, left, right)
float pl = ta.pivotlow(low, left, right)
float last_ph = ta.valuewhen(not na(ph), ph, 0)
int last_time_h = int(ta.valuewhen(not na(ph), time[right], 0))
float last_pl = ta.valuewhen(not na(pl), pl, 0)
int last_time_l = int(ta.valuewhen(not na(pl), time[right], 0))
[last_ph[1], last_pl[1], last_time_h[1], last_time_l[1]]
[ph1, pl1, pTimeH1, pTimeL1] = request.security(syminfo.tickerid, tf1, get_mtf_pivots(leftLen, rightLen), lookahead = barmerge.lookahead_on)
[ph2, pl2, pTimeH2, pTimeL2] = request.security(syminfo.tickerid, tf2, get_mtf_pivots(leftLen, rightLen), lookahead = barmerge.lookahead_on)
method push_swing(StructState st, int t, float p, int typ) =>
bool changed = false
bool sameRun = not na(st.lastSwing) and st.lastSwing.ptype == typ
if sameRun
SwingPoint cur = st.lastSwing
bool moreExtreme = typ == 1 ? p > cur.price : p < cur.price
if moreExtreme
cur.timeLoc := t
cur.price := p
cur.confirmTime := time
cur.isBroken := false
if not na(cur.lb)
label.set_xy(cur.lb, t, p)
if not na(cur.ln)
line.set_x2(cur.ln, t)
line.set_y2(cur.ln, p)
if (typ == 1 and close > p) or (typ == -1 and close < p)
cur.isBroken := true
st.retroSig := typ
changed := true
else
label lb = na
if show_tag
lb := label.new(x = t, y = p, text = typ == 1 ? "H" : "L", style = typ == 1 ? label.style_label_down : label.style_label_up, color = color.new(st.col, 50), textcolor = color.white, xloc = xloc.bar_time)
array.push(structLabels, lb)
line ln = na
if not na(st.lastSwing)
ln := line.new(x1 = st.lastSwing.timeLoc, y1 = st.lastSwing.price, x2 = t, y2 = p, color = st.col, style = line.style_dashed, xloc = xloc.bar_time)
array.push(structLines, ln)
SwingPoint sp = SwingPoint.new(t, p, typ, false, time, ln, lb)
if (typ == 1 and close > p) or (typ == -1 and close < p)
sp.isBroken := true
st.retroSig := typ
st.lastSwing := sp
if typ == 1
st.lastHigh := sp
else
st.lastLow := sp
changed := true
changed
method update_swings(StructState st, float ph, float pl, int pTimeH, int pTimeL) =>
bool touched = false
int tH = int(nz(pTimeH))
int tL = int(nz(pTimeL))
bool gotH = st.enabled and not na(ph) and tH > 0 and tH != st.seenH
bool gotL = st.enabled and not na(pl) and tL > 0 and tL != st.seenL
if gotH and gotL
if tH <= tL
touched := st.push_swing(tH, ph, 1)
touched := st.push_swing(tL, pl, -1) or touched
else
touched := st.push_swing(tL, pl, -1)
touched := st.push_swing(tH, ph, 1) or touched
st.seenH := tH
st.seenL := tL
else if gotH
touched := st.push_swing(tH, ph, 1)
st.seenH := tH
else if gotL
touched := st.push_swing(tL, pl, -1)
st.seenL := tL
touched
st1.enabled := tf1Valid
st2.enabled := tf2Valid
bool newSwing1 = st1.update_swings(ph1, pl1, pTimeH1, pTimeL1)
bool newSwing2 = st2.update_swings(ph2, pl2, pTimeH2, pTimeL2)
draw_break(StructState st, SwingPoint sp, bool isBull, bool retro) =>
sp.isBroken := true
string base = isBull ? (st.trend == -1 ? "CHoCH" : "BOS") : (st.trend == 1 ? "CHoCH" : "BOS")
string txt = retro ? base + "*" : base
ln = line.new(x1 = sp.timeLoc, y1 = sp.price, x2 = time, y2 = sp.price, color = st.col, style = retro ? line.style_dotted : line.style_solid, width = 2, xloc = xloc.bar_time)
array.push(structLines, ln)
lbl = label.new(x = int(math.avg(sp.timeLoc, time)), y = sp.price, text = txt, color = color.new(color.white, 100), textcolor = st.col, style = isBull ? label.style_label_down : label.style_label_up, size = size.small, xloc = xloc.bar_time)
array.push(structLabels, lbl)
st.evt := isBull ? 1 : -1
st.evtChoch := base == "CHoCH"
st.evtRetro := retro
st.evtPrice := sp.price
st.trend := isBull ? 1 : -1
true
check_structure(StructState st) =>
st.evt := 0
float upRef = bosUseWick ? high : close
float dnRef = bosUseWick ? low : close
bool bullBreak = st.enabled and not na(st.lastHigh) and not st.lastHigh.isBroken and time > st.lastHigh.confirmTime and upRef > st.lastHigh.price
bool bearBreak = st.enabled and not na(st.lastLow) and not st.lastLow.isBroken and time > st.lastLow.confirmTime and dnRef < st.lastLow.price
bool retroBull = allowRetro and st.enabled and st.retroSig == 1 and not na(st.lastHigh)
bool retroBear = allowRetro and st.enabled and st.retroSig == -1 and not na(st.lastLow)
st.retroSig := 0
bool bearFirst = close >= open
if bullBreak and bearBreak
if bearFirst
draw_break(st, st.lastLow, false, false)
draw_break(st, st.lastHigh, true, false)
else
draw_break(st, st.lastHigh, true, false)
draw_break(st, st.lastLow, false, false)
else if bullBreak
draw_break(st, st.lastHigh, true, false)
else if bearBreak
draw_break(st, st.lastLow, false, false)
else if retroBull
draw_break(st, st.lastHigh, true, true)
else if retroBear
draw_break(st, st.lastLow, false, true)
[bullBreak or retroBull, bearBreak or retroBear]
[bull1, bear1] = check_structure(st1)
[bull2, bear2] = check_structure(st2)
bool retroPass1 = a_retro or not st1.evtRetro
bool retroPass2 = a_retro or not st2.evtRetro
bool evBos1 = st1.evt != 0 and not st1.evtChoch and retroPass1
bool evChoch1 = st1.evt != 0 and st1.evtChoch and retroPass1
bool evBos2 = st2.evt != 0 and not st2.evtChoch and retroPass2
bool evChoch2 = st2.evt != 0 and st2.evtChoch and retroPass2
struct_alert(StructState st, string tfName, bool okBos, bool okChoch, int idBos, int idChoch) =>
bool sent = false
if st.evt != 0 and (a_retro or not st.evtRetro)
string dir = st.evt == 1 ? "Bullish" : "Bearish"
string kind = (st.evtChoch ? "CHoCH" : "BOS") + (st.evtRetro ? "*" : "")
string body = kind + " " + dir + " [" + tfName + "] broke " + str.tostring(st.evtPrice, format.mintick)
sent := fire(st.evtChoch ? idChoch : idBos, st.evtChoch ? okChoch : okBos, amsg(body))
sent
bool sA1 = struct_alert(st1, tf1, a_bos1, a_choch1, ID_BOS1, ID_CHOCH1)
bool sA2 = struct_alert(st2, tf2, a_bos2, a_choch2, ID_BOS2, ID_CHOCH2)
while array.size(structLines) > maxObjects
line.delete(array.shift(structLines))
while array.size(structLabels) > maxObjects
label.delete(array.shift(structLabels))
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)
float rngHigh = na
float rngLow = na
float rngEq = na
int rngLeft = 0
if not na(st1.lastHigh) and not na(st1.lastLow)
rngHigh := st1.lastHigh.price
rngLow := st1.lastLow.price
rngEq := math.avg(rngHigh, rngLow)
rngLeft := math.min(st1.lastHigh.timeLoc, st1.lastLow.timeLoc)
pd_ok(int dir, float top, float bottom) =>
bool ok = true
if pdMode != "Off" and not na(rngEq)
float mid = math.avg(top, bottom)
ok := dir == 1 ? mid <= rngEq : mid >= rngEq
ok
pd_allow_create(bool ok) =>
pdMode == "Filter Out" ? ok : true
var box pdPremBx = na
var box pdDiscBx = na
var line pdEqLn = na
var float lastRngH = na
var float lastRngL = na
if show_pd and not na(rngEq)
if rngHigh != lastRngH or rngLow != lastRngL
box.delete(pdPremBx)
box.delete(pdDiscBx)
line.delete(pdEqLn)
pdPremBx := box.new(left = rngLeft, top = rngHigh, right = time, bottom = rngEq, border_color = color.new(pdPremCol, 60), bgcolor = pdPremCol, xloc = xloc.bar_time, extend = extend.Показано первые 50% кода (символов: 39504)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.