Indicator · Pine Script v6 · Own pane

SMC HTF Confluence

by skipp-dev· code credited to preuss_steffen

SMC HTF Confluence calculates multi-timeframe market structure and setup scores using confirmed higher-timeframe data.

View on GitHub

Repaints

GitHub stars1on the repository
Pine versionv6current
Lines of code182
Settings6inputs
LicenceNone statedfile: MPL-2.0
Last update4 days ago26 Oct 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

182 lines of Pine Script v6 from SMC_HTF_Confluence.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

SMC_HTF_Confluence.pine
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © preuss_steffen

//@version=6

// Product role: companion_operator_only. Pro-only confirmed HTF context.
//
// Every higher-timeframe value is transported from the last closed source bar.
// Equal/lower requested frames and incomplete source history fail closed.

indicator("SMC HTF Confluence", overlay = false, max_labels_count = 20, dynamic_requests = true)

string GROUP_FRAMES = "Confirmed higher timeframes"
string GROUP_VIEW = "View"

string tf_fast = input.timeframe("15", "Fast HTF (15m)", group = GROUP_FRAMES)
string tf_medium = input.timeframe("60", "Medium HTF (1h)", group = GROUP_FRAMES)
string tf_slow = input.timeframe("240", "Slow HTF (4h)", group = GROUP_FRAMES)
bool show_atr = input.bool(true, "Show ATR regime", group = GROUP_VIEW)
bool show_reversal = input.bool(true, "Show reversal scores", group = GROUP_VIEW)
bool show_table = input.bool(true, "Show confirmed-source table", group = GROUP_VIEW)

_strictly_higher(string requested_tf) =>
    float requested_seconds = timeframe.in_seconds(requested_tf)
    float chart_seconds = timeframe.in_seconds(timeframe.period)
    not na(requested_seconds) and not na(chart_seconds) and requested_seconds > chart_seconds

_confirmed_tuple() =>
    float ema_fast = ta.ema(close, 21)
    float ema_slow = ta.ema(close, 55)
    float rsi = ta.rsi(close, 14)
    float atr = ta.atr(14)
    float atr_baseline = ta.sma(atr, 50)
    float atr_ratio = atr_baseline > 0 ? atr / atr_baseline : na
    float bb_basis = ta.sma(close, 20)
    float bb_deviation = ta.stdev(close, 20) * 2.0
    float bb_upper = bb_basis + bb_deviation
    float bb_lower = bb_basis - bb_deviation
    float kc_basis = ta.ema(close, 20)
    float kc_range = ta.atr(20) * 1.5
    float kc_upper = kc_basis + kc_range
    float kc_lower = kc_basis - kc_range
    bool squeeze_on = bb_upper < kc_upper and bb_lower > kc_lower
    bool squeeze_released = not squeeze_on and squeeze_on[1]
    int trend = close > ema_fast and ema_fast > ema_slow ? 1 : close < ema_fast and ema_fast < ema_slow ? -1 : 0
    bool bull_pattern = close > open and close > high[1] and low <= low[1]
    bool bear_pattern = close < open and close < low[1] and high >= high[1]
    bool bull_divergence = low < low[5] and rsi > rsi[5]
    bool bear_divergence = high > high[5] and rsi < rsi[5]
    float source_vwap = ta.vwap(hlc3)
    bool vwap_hold = trend > 0 and close >= source_vwap or trend < 0 and close <= source_vwap
    bool retrace_ok = trend != 0 and math.abs(close - ema_fast) <= atr * 0.75
    bool reversal_active = bull_pattern or bear_pattern or bull_divergence or bear_divergence
    int setup_score = (squeeze_on ? 1 : 0) + (retrace_ok ? 1 : 0) + (reversal_active ? 1 : 0)
    int confirm_score = (trend != 0 ? 1 : 0) + (vwap_hold ? 1 : 0) + (bull_pattern or bear_pattern ? 1 : 0)
    int follow_score = (squeeze_released ? 1 : 0) + (trend > 0 and close > high[1] or trend < 0 and close < low[1] ? 1 : 0)
    [
         time[1],
         time_close[1],
         barstate.isconfirmed[1],
         trend[1],
         atr_ratio[1],
         squeeze_on[1],
         squeeze_released[1],
         reversal_active[1],
         bull_pattern[1],
         bear_pattern[1],
         bull_divergence[1],
         bear_divergence[1],
         vwap_hold[1],
         retrace_ok[1],
         setup_score[1],
         confirm_score[1],
         follow_score[1]]

[fast_source_time, fast_source_close, fast_source_confirmed, fast_trend_raw, fast_atr_ratio_raw, fast_squeeze_on_raw, fast_squeeze_released_raw, fast_reversal_active_raw, fast_bull_pattern_raw, fast_bear_pattern_raw, fast_bull_divergence_raw, fast_bear_divergence_raw, fast_vwap_hold_raw, fast_retrace_ok_raw, fast_setup_raw, fast_confirm_raw, fast_follow_raw] = request.security(
     syminfo.tickerid,
     tf_fast,
     _confirmed_tuple(),
     gaps = barmerge.gaps_off,
     lookahead = barmerge.lookahead_on,
     calc_bars_count = 500)

[medium_source_time, medium_source_close, medium_source_confirmed, medium_trend_raw, medium_atr_ratio_raw, medium_squeeze_on_raw, medium_squeeze_released_raw, medium_reversal_active_raw, medium_bull_pattern_raw, medium_bear_pattern_raw, medium_bull_divergence_raw, medium_bear_divergence_raw, medium_vwap_hold_raw, medium_retrace_ok_raw, medium_setup_raw, medium_confirm_raw, medium_follow_raw] = request.security(
     syminfo.tickerid,
     tf_medium,
     _confirmed_tuple(),
     gaps = barmerge.gaps_off,
     lookahead = barmerge.lookahead_on,
     calc_bars_count = 500)

[slow_source_time, slow_source_close, slow_source_confirmed, slow_trend_raw, slow_atr_ratio_raw, slow_squeeze_on_raw, slow_squeeze_released_raw, slow_reversal_active_raw, slow_bull_pattern_raw, slow_bear_pattern_raw, slow_bull_divergence_raw, slow_bear_divergence_raw, slow_vwap_hold_raw, slow_retrace_ok_raw, slow_setup_raw, slow_confirm_raw, slow_follow_raw] = request.security(
     syminfo.tickerid,
     tf_slow,
     _confirmed_tuple(),
     gaps = barmerge.gaps_off,
     lookahead = barmerge.lookahead_on,
     calc_bars_count = 500)

bool fast_available = _strictly_higher(tf_fast) and fast_source_confirmed and not na(fast_source_time) and not na(fast_source_close) and not na(fast_atr_ratio_raw)
bool medium_available = _strictly_higher(tf_medium) and medium_source_confirmed and not na(medium_source_time) and not na(medium_source_close) and not na(medium_atr_ratio_raw)
bool slow_available = _strictly_higher(tf_slow) and slow_source_confirmed and not na(slow_source_time) and not na(slow_source_close) and not na(slow_atr_ratio_raw)
bool frames_ordered = timeframe.in_seconds(tf_fast) < timeframe.in_seconds(tf_medium) and timeframe.in_seconds(tf_medium) < timeframe.in_seconds(tf_slow)
fast_available := frames_ordered and fast_available
medium_available := frames_ordered and medium_available
slow_available := frames_ordered and slow_available

int fast_trend = fast_available ? fast_trend_raw : 0
int medium_trend = medium_available ? medium_trend_raw : 0
int slow_trend = slow_available ? slow_trend_raw : 0
float fast_atr_ratio = fast_available ? fast_atr_ratio_raw : na
float medium_atr_ratio = medium_available ? medium_atr_ratio_raw : na
float slow_atr_ratio = slow_available ? slow_atr_ratio_raw : na

bool squeeze_on = fast_available and fast_squeeze_on_raw or medium_available and medium_squeeze_on_raw or slow_available and slow_squeeze_on_raw
bool squeeze_released = fast_available and fast_squeeze_released_raw or medium_available and medium_squeeze_released_raw or slow_available and slow_squeeze_released_raw
bool reversal_active = fast_available and fast_reversal_active_raw or medium_available and medium_reversal_active_raw or slow_available and slow_reversal_active_raw
bool bull_pattern = fast_available and fast_bull_pattern_raw or medium_available and medium_bull_pattern_raw or slow_available and slow_bull_pattern_raw
bool bear_pattern = fast_available and fast_bear_pattern_raw or medium_available and medium_bear_pattern_raw or slow_available and slow_bear_pattern_raw
bool bull_divergence = fast_available and fast_bull_divergence_raw or medium_available and medium_bull_divergence_raw or slow_available and slow_bull_divergence_raw
bool bear_divergence = fast_available and fast_bear_divergence_raw or medium_available and medium_bear_divergence_raw or slow_available and slow_bear_divergence_raw
bool vwap_hold = fast_available and fast_vwap_hold_raw or medium_available and medium_vwap_hold_raw or slow_available and slow_vwap_hold_raw
bool retrace_ok = fast_available and fast_retrace_ok_raw or medium_available and medium_retrace_ok_raw or slow_available and slow_retrace_ok_raw

int available_count = (fast_available ? 1 : 0) + (medium_available ? 1 : 0) + (slow_available ? 1 : 0)
int trend_sum = fast_trend + medium_trend + slow_trend
int confluence_bias = available_count == 3 ? (trend_sum >= 2 ? 1 : trend_sum <= -2 ? -1 : 0) : 0
float confluence_score = available_count == 3 ? trend_sum / 3.0 * 100.0 : na
int setup_score = (fast_available ? fast_setup_raw : 0) + (medium_available ? medium_setup_raw : 0) + (slow_available ? slow_setup_raw : 0)
int confirm_score = (fast_available ? fast_confirm_raw : 0) + (medium_available ? medium_confirm_raw : 0) + (slow_available ? slow_confirm_raw : 0)
int follow_score = (fast_available ? fast_follow_raw : 0) + (medium_available ? medium_follow_raw : 0) + (slow_available ? slow_follow_raw : 0)

color bias_color = confluence_bias > 0 ? color.new(color.green, 20) : confluence_bias < 0 ? color.new(color.red, 20) : color.new(color.gray, 55)
float atr_display = not show_atr ? na : fast_available ? fast_atr_ratio : medium_available ? medium_atr_ratio : slow_atr_ratio
plot(atr_display, "Confirmed ATR Ratio", bias_color, 2, plot.style_columns)
hline(1.0, "ATR Baseline", color.new(color.gray, 70), hline.style_dotted)
plot(show_reversal and reversal_active ? setup_score : na, "Setup Score", color.new(color.blue, 30), 1, plot.style_stepline)
plot(show_reversal and reversal_active ? confirm_score : na, "Confirm Score", color.new(color.green, 30), 1, plot.style_stepline)
plot(show_reversal and reversal_active ? follow_score : na, "Follow Score", color.new(color.orange, 30), 1, plot.style_stepline)
plotshape(squeeze_on, "Squeeze On", shape.diamond, location.bottom, color.new(color.blue, 20), size = size.tiny)
plotshape(squeeze_released, "Squeeze Released", shape.circle, location.bottom, color.new(color.orange, 20), size = size.tiny)
plotshape(bull_divergence, "HTF Bull Divergence", shape.triangleup, location.bottom, color.new(color.green, 20), size = size.tiny)
plotshape(bear_divergence, "HTF Bear Divergence", shape.triangledown, location.top, color.new(color.red, 20), size = size.tiny)
bgcolor(bull_pattern ? color.new(color.green, 92) : bear_pattern ? color.new(color.red, 92) : na, title = "Confirmed HTF pattern")

plot(fast_available ? 1 : 0, "HTF 15m Available", display = display.data_window)
plot(medium_available ? 1 : 0, "HTF 1h Available", display = display.data_window)
plot(slow_available ? 1 : 0, "HTF 4h Available", display = display.data_window)
plot(fast_available ? fast_source_close : na, "HTF 15m Source Close", display = display.data_window)
plot(medium_available ? medium_source_close : na, "HTF 1h Source Close", display = display.data_window)
plot(slow_available ? slow_source_close : na, "HTF 4h Source Close", display = display.data_window)
plot(fast_available ? fast_trend : na, "HTF 15m Trend", display = display.data_window)
plot(medium_available ? medium_trend : na, "HTF 1h Trend", display = display.data_window)
plot(slow_available ? slow_trend : na, "HTF 4h Trend", display = display.data_window)
plot(fast_atr_ratio, "HTF 15m ATR Ratio", display = display.data_window)
plot(medium_atr_ratio, "HTF 1h ATR Ratio", display = display.data_window)
plot(slow_atr_ratio, "HTF 4h ATR Ratio", display = display.data_window)
plot(confluence_bias, "HTF Confluence Bias", display = display.data_window)
plot(confluence_score, "HTF Confluence Score", display = display.data_window)
plot(vwap_hold ? 1 : 0, "HTF VWAP Hold", display = display.data_window)
plot(retrace_ok ? 1 : 0, "HTF Retrace OK", display = display.data_window)

_available_text(bool available, int source_close) =>
    available ? "closed " + str.format_time(source_close, "yyyy-MM-dd HH:mm", "Etc/UTC") + " UTC" : "unavailable"

var table status = table.new(position.top_right, 3, 5, border_width = 1)
if barstate.islast and show_table
    table.cell(status, 0, 0, "Frame", bgcolor = color.new(color.gray, 75))
    table.cell(status, 1, 0, "Freshness", bgcolor = color.new(color.gray, 75))
    table.cell(status, 2, 0, "Trend", bgcolor = color.new(color.gray, 75))
    table.cell(status, 0, 1, tf_fast)
    table.cell(status, 1, 1, _available_text(fast_available, fast_source_close))
    table.cell(status, 2, 1, fast_available ? str.tostring(fast_trend) : "—")
    table.cell(status, 0, 2, tf_medium)
    table.cell(status, 1, 2, _available_text(medium_available, medium_source_close))
    table.cell(status, 2, 2, medium_available ? str.tostring(medium_trend) : "—")
    table.cell(status, 0, 3, tf_slow)
    table.cell(status, 1, 3, _available_text(slow_available, slow_source_close))
    table.cell(status, 2, 3, slow_available ? str.tostring(slow_trend) : "—")
    table.cell(status, 0, 4, "Aggregate")
    table.cell(status, 1, 4, not frames_ordered ? "invalid frame order" : available_count == 3 ? "all confirmed" : "fail closed")
    table.cell(status, 2, 4, available_count == 3 ? str.tostring(confluence_score, "#") + "%" : "—", text_color = bias_color)

Overview

SMC HTF Confluence evaluates exponential moving averages for trend alignment, RSI for divergences, ATR for volatility regimes, and Bollinger Band Squeezes relative to Keltner Channels. The indicator compiles these metrics into setup, confirmation, and follow-through scores across three user-defined higher timeframes, rendering a summary table and secondary indicators in a separate pane.

Details

Published by

skipp-dev on GitHub

Code credit

preuss_steffen, as written in the script's header

Draws

Separate pane below the chart

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

  • Reads higher-timeframe data with lookahead on, so the history can show signals that were not there in real time

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Fast HTF (15m)timeframe15tf_fast
Medium HTF (1h)timeframe60tf_medium
Slow HTF (4h)timeframe240tf_slow
Show ATR regimebooltrueshow_atr
Show reversal scoresbooltrueshow_reversal
Show confirmed-source tablebooltrueshow_table
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

This indicator scans a pasted list of symbols and shows matching long and short setups in a table in a separate pane. It uses a Supertrend crossover, then applies an ATR or fixed-point volatility range so quiet, sideways conditions can be skipped. Optional fil

Indicator v5 TrendVolatility & bands
Updated 1 year ago · MPL-2.0 GitHub repository of Trend Following Setup - Sideways Market Skipper Scanner

Strategy-Picker

by hintheman
13 stars

Strategy-Picker evaluates market trend, momentum, and volatility across multiple timeframes (5m, 15m, and 60m) to recommend suitable options trading structures. It combines MACD, an 8-period EMA, and ADX readings with external VIX levels to suggest Put Credit

Indicator v6 TrendVolatility & bands
Updated 2 months ago · Custom licence GitHub repository of Strategy-Picker

The Adaptive Cycle Detector estimates the dominant market cycle from WaveTrend oscillator zero-crossing frequency and applies smoothing to recommend adaptive indicator lengths. Fast markets with frequent crossings receive shorter lengths while slow swing marke

Indicator v6 Oscillators & momentumVolatility & bands
Updated 3 days ago · MIT GitHub repository of Adaptive Cycle Detector [WavesUnchained]

Manias, Panics and Crashes

by MeridianAlgo
9 stars

Manias, Panics and Crashes is a separate-pane market regime indicator that quantifies market sentiment and systemic risk. It processes technical metrics including RSI, moving averages, and volume alongside optional intermarket data such as VIX volatility and c

Indicator v6 Oscillators & momentumVolatility & bands
Updated 4 months ago · MIT GitHub repository of Manias, Panics and Crashes

Elton's Screener

by eltonaguiar
4 stars

Elton's Screener is an indicator that runs in a separate pane and scores one of twenty selectable strategies, or auto-selects a route from the symbol type. It filters signals by a minimum confidence level and a higher-timeframe EMA trend alignment. ATR multipl

Indicator v6 Screeners & dashboardsOscillators & momentum Repaints
Updated 2 days ago · None stated GitHub repository of Elton's Screener
4 stars

Meridian - Futures Context is an intraday analysis indicator designed for US index futures. It measures volume participation using relative volume, calculates rolling realized volatility, and evaluates trend context through VWAP slope and EMA structures. Displ

Indicator v6 VolumeVolatility & bands
Updated 7 weeks ago · MPL-2.0 GitHub repository of Meridian - Futures Context

More Trend scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers