Indicator · Pine Script v6 · On the chart

SMC Toolkit [btankutt]

by btankutt

SMC Toolkit detects core Smart Money Concepts on the price chart, including market structure breaks (BoS and CHoCH), Order Blocks, Fair Value Gaps (FVGs), and liquidity levels such as equal highs and lows.

View on GitHub

GitHub stars2on the repository
Pine versionv6current
Lines of code475
Settings18inputs
LicenceMPL-2.0
Last update3 months ago6 Jul 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

475 lines of Pine Script v6 from indicators/01-smc-toolkit/smc-toolkit.pine, published under MPL-2.0. Keep the author's credit and licence lines when you reuse it.

smc-toolkit.pine
// =============================================================================
// SMC Toolkit
// =============================================================================
// Author:      Baris Tankut (@btankutt)
// Repository:  https://github.com/btankutt/smc-pine-suite
// License:     MPL 2.0 (see LICENSE-FREE)
// Created:     2026-05-15
// Version:     1.1.0
// -----------------------------------------------------------------------------
// Smart Money Concepts toolkit for TradingView:
//   - Market structure detection (BoS / CHoCH)
//   - Order Block identification with mitigation tracking
//   - Fair Value Gap (FVG) detection
//   - Liquidity level detection and sweep alerts
//
// Standard implementations of public-domain SMC concepts. Open source under
// MPL 2.0 - fork, study, adapt to your strategy.
//
// v1.1.0 changelog:
//   - FIX: FVGs were marked filled on their creation bar (fill loop saw the
//     just-created gap whose edge equals the creation bar's own low/high).
//     Objects now store their creation bar and are never evaluated on it.
//   - FIX: Order Blocks were mitigated on their own creation bar in gapless
//     markets. Same creation-bar guard applies.
//   - FIX: "Equal highs/lows lookback" input was never used; it now bounds
//     how far back (in bars) a pivot may match a prior pivot.
//   - FIX: all state updates, drawings and alert flags are gated on
//     barstate.isconfirmed - no intrabar phantom signals; realtime output
//     now always matches a historical recalculation.
//   - NEW: dedicated "Max liquidity levels" input (was silently coupled to
//     the OB + FVG display caps).
//   - NEW: liquidity levels are invalidated when price CLOSES through them
//     (a broken level is not resting liquidity anymore); swept/broken lines
//     are grayed out and frozen, matching the OB/FVG convention.
//   - NEW: mitigated OBs / filled FVGs stop extending right - only active
//     zones project to the right edge.
//   - REMOVED: dead "Show internal structure" input (was a no-op).
//
// Disclaimer: Educational tool, not financial advice. Past performance does
// not guarantee future results. Always backtest and use proper risk management.
// =============================================================================

//@version=6
indicator("SMC Toolkit [btankutt]", overlay=true, max_boxes_count=500, max_lines_count=500, max_labels_count=500)

// =============================================================================
// CONSTANTS
// =============================================================================
int ATR_LENGTH        = 14
int VOLUME_SMA_LENGTH = 20
int OB_LOOKBACK_BARS  = 30
int PIVOT_BUFFER_SIZE = 10

// Input group names
GRP_STRUCT = "Structure"
GRP_OB     = "Order Blocks"
GRP_FVG    = "Fair Value Gaps"
GRP_LIQ    = "Liquidity"
GRP_DISP   = "Display"

// =============================================================================
// USER INPUTS
// =============================================================================
// Group 1 - Structure
int  swing_length            = input.int(5, "Swing detection length", minval=2, maxval=50, group=GRP_STRUCT)
bool show_external_structure = input.bool(true, "Show structure labels", group=GRP_STRUCT)

// Group 2 - Order Blocks
bool  ob_enabled        = input.bool(true,  "Enable Order Blocks", group=GRP_OB)
int   ob_max_count      = input.int(5, "Max OBs to display (total)", minval=1, maxval=50, group=GRP_OB)
bool  ob_volume_filter  = input.bool(true, "Filter by volume", group=GRP_OB)
color ob_bullish_color  = input.color(color.new(color.green, 70), "Bullish OB color", group=GRP_OB)
color ob_bearish_color  = input.color(color.new(color.red,   70), "Bearish OB color", group=GRP_OB)

// Group 3 - Fair Value Gaps
bool  fvg_enabled       = input.bool(true, "Enable FVG", group=GRP_FVG)
int   fvg_max_count     = input.int(5, "Max FVGs to display", minval=1, maxval=50, group=GRP_FVG)
float fvg_min_size_atr  = input.float(0.5, "Min FVG size (ATR multiplier)", minval=0.1, maxval=5.0, step=0.1, group=GRP_FVG)
color fvg_bullish_color = input.color(color.new(color.aqua,   80), "Bullish FVG color", group=GRP_FVG)
color fvg_bearish_color = input.color(color.new(color.orange, 80), "Bearish FVG color", group=GRP_FVG)

// Group 4 - Liquidity
bool  liq_enabled       = input.bool(true, "Enable Liquidity", group=GRP_LIQ)
int   liq_max_count     = input.int(10, "Max liquidity levels", minval=1, maxval=50, group=GRP_LIQ)
int   liq_lookback      = input.int(50, "Equal highs/lows lookback (bars)", minval=10, maxval=200, group=GRP_LIQ, tooltip="A new pivot only forms a liquidity level with prior pivots that are at most this many bars old.")
float liq_tolerance_atr = input.float(0.2, "Tolerance (ATR multiplier)", minval=0.05, maxval=1.0, step=0.05, group=GRP_LIQ)

// Group 5 - Display
bool show_labels      = input.bool(true, "Show event labels", group=GRP_DISP)
int  box_transparency = input.int(70, "Box transparency", minval=0, maxval=100, group=GRP_DISP)

// =============================================================================
// USER-DEFINED TYPES
// =============================================================================
// created_bar guards maintenance loops: an object is never evaluated on the
// bar it was created (its edges are that bar's own high/low - a same-bar
// check would trivially "touch" it).
type OrderBlock
    float top
    float bottom
    int   created_bar
    bool  mitigated
    bool  bullish

type FVG
    float top
    float bottom
    int   created_bar
    bool  filled
    bool  bullish

type LiquidityLevel
    float price
    int   created_bar
    bool  swept
    bool  is_bsl

// =============================================================================
// STATE
// =============================================================================
// Tracked SMC objects (logical state)
var array<OrderBlock>     obs  = array.new<OrderBlock>()
var array<FVG>            fvgs = array.new<FVG>()
var array<LiquidityLevel> liqs = array.new<LiquidityLevel>()

// Parallel arrays for visual handles (kept in lockstep with the logical arrays).
// This avoids polluting the UDT spec with rendering concerns.
var array<box>  ob_boxes  = array.new<box>()
var array<box>  fvg_boxes = array.new<box>()
var array<line> liq_lines = array.new<line>()

// Most recent confirmed swing levels
var float last_swing_high = na
var float last_swing_low  = na

// "Has the last confirmed swing been broken?" - prevents re-firing BoS/CHoCH
// every bar while close remains beyond the swing.
var bool broke_last_high = false
var bool broke_last_low  = false

// Current structural trend
// trend_initialized = false until the FIRST break (BoS/CHoCH detection only valid after)
// is_bullish        = direction of the current trend (only meaningful when trend_initialized)
var bool trend_initialized = false
var bool is_bullish        = false

// Recent pivot prices + the bar each formed on, used for equal-highs/lows
// liquidity detection. liq_lookback evicts entries older than N bars;
// PIVOT_BUFFER_SIZE caps the buffer length.
var array<float> recent_ph_prices = array.new<float>()
var array<int>   recent_ph_bars   = array.new<int>()
var array<float> recent_pl_prices = array.new<float>()
var array<int>   recent_pl_bars   = array.new<int>()

// Alert flags, reset each bar. Set only on confirmed bars, so any TradingView
// alert frequency is safe (recommended: "Once Per Bar Close").
bool bos_bullish   = false
bool bos_bearish   = false
bool choch_bullish = false
bool choch_bearish = false
bool bsl_swept     = false
bool ssl_swept     = false

// Volatility + volume context
float atr_value     = ta.atr(ATR_LENGTH)
float vol_sma_value = ta.sma(volume, VOLUME_SMA_LENGTH)

// =============================================================================
// SECTION 1 - Swing detection
// =============================================================================
// Note: ta.pivothigh/pivotlow returns the pivot value `swing_length` bars
// AFTER it actually formed. This `swing_length` bar confirmation delay is
// required to avoid lookahead bias - adjust swing_length to balance
// responsiveness vs stability.
// ta.* calls stay unconditional at global scope; only STATE updates are
// gated on barstate.isconfirmed (true on every historical bar, and only on
// the final execution of the realtime bar - history is unchanged, live
// output can no longer flicker intrabar).
float ph = ta.pivothigh(swing_length, swing_length)
float pl = ta.pivotlow(swing_length, swing_length)

if barstate.isconfirmed
    if not na(ph)
        last_swing_high := ph
        broke_last_high := false
    if not na(pl)
        last_swing_low := pl
        broke_last_low := false

// =============================================================================
// SECTION 2 - Structure (BoS / CHoCH)
// =============================================================================
// A break only fires the FIRST time close exceeds the last swing. The
// per-swing "broke_last_*" flag is reset whenever a new pivot is confirmed.
// Note: on a single wide bar that closes beyond BOTH swings (rare), the
// upside break is processed first, then the downside - the bar emits both
// events and the trend ends bearish.
bool break_up   = false
bool break_down = false

if barstate.isconfirmed
    if not na(last_swing_high) and close > last_swing_high and not broke_last_high
        break_up        := true
        broke_last_high := true
    if not na(last_swing_low) and close < last_swing_low and not broke_last_low
        break_down     := true
        broke_last_low := true

    // First break establishes the initial trend direction.
    if not trend_initialized and (break_up or break_down)
        is_bullish        := break_up
        trend_initialized := true

    if trend_initialized
        if break_up
            if is_bullish
                bos_bullish := true
            else
                choch_bullish := true
                is_bullish    := true
            if show_external_structure and show_labels
                label.new(bar_index, high, choch_bullish ? "CHoCH" : "BoS",
                     yloc=yloc.abovebar, style=label.style_label_down,
                     color=color.new(color.green, 50), textcolor=color.white,
                     size=size.tiny)
        if break_down
            if is_bullish
                choch_bearish := true
                is_bullish    := false
            else
                bos_bearish := true
            if show_external_structure and show_labels
                label.new(bar_index, low, choch_bearish ? "CHoCH" : "BoS",
                     yloc=yloc.belowbar, style=label.style_label_up,
                     color=color.new(color.red, 50), textcolor=color.white,
                     size=size.tiny)

// =============================================================================
// SECTION 3 - Order Block Detection
// =============================================================================
// When a break of structure occurs, the LAST opposite-color candle before
// the break is the order block. Optional volume filter excludes low-volume
// candles that historically produce weaker zones.
// Mitigation runs BEFORE creation and skips each OB's creation bar, so a
// fresh OB can only be mitigated by a later return into the zone - never by
// the breakout bar that defined it.

if barstate.isconfirmed and obs.size() > 0
    for i = 0 to obs.size() - 1
        OrderBlock ob = obs.get(i)
        if not ob.mitigated and bar_index > ob.created_bar
            bool hit = ob.bullish ? (low <= ob.top) : (high >= ob.bottom)
            if hit
                ob.mitigated := true
                box ref = ob_boxes.get(i)
                if not na(ref)
                    ref.set_bgcolor(color.new(color.gray, 90))
                    ref.set_border_color(color.gray)
                    ref.set_extend(extend.none)
                    ref.set_right(bar_index)

if barstate.isconfirmed and ob_enabled and break_up
    int found_bar = -1
    for i = 1 to OB_LOOKBACK_BARS
        if close[i] < open[i]
            found_bar := i
            break
    if found_bar > 0
        if not ob_volume_filter or volume[found_bar] > vol_sma_value[found_bar]
            color bg = color.new(ob_bullish_color, box_transparency)
            box new_box = box.new(left=bar_index - found_bar, top=high[found_bar],
                 right=bar_index, bottom=low[found_bar],
                 border_color=ob_bullish_color, bgcolor=bg, extend=extend.right)
            obs.push(OrderBlock.new(high[found_bar], low[found_bar], bar_index, false, true))
            ob_boxes.push(new_box)
            while obs.size() > ob_max_count
                obs.shift()
                box dropped = ob_boxes.shift()
                if not na(dropped)
                    dropped.delete()

if barstate.isconfirmed and ob_enabled and break_down
    int found_bar = -1
    for i = 1 to OB_LOOKBACK_BARS
        if close[i] > open[i]
            found_bar := i
            break
    if found_bar > 0
        if not ob_volume_filter or volume[found_bar] > vol_sma_value[found_bar]
            color bg = color.new(ob_bearish_color, box_transparency)
            box new_box = box.new(left=bar_index - found_bar, top=high[found_bar],
                 right=bar_index, bottom=low[found_bar],
                 border_color=ob_bearish_color, bgcolor=bg, extend=extend.right)
            obs.push(OrderBlock.new(high[found_bar], low[found_bar], bar_index, false, false))
            ob_boxes.push(new_box)
            while obs.size() > ob_max_count
                obs.shift()
                box dropped = ob_boxes.shift()
                if not na(dropped)
                    dropped.delete()

// =============================================================================
// SECTION 4 - Fair Value Gap
// =============================================================================
// A 3-candle gap pattern. Filter by ATR multiplier to skip noise-sized gaps.
// Fill check runs BEFORE creation and skips each FVG's creation bar: a
// bullish FVG's top IS the creation bar's low, so a same-bar check would
// mark every gap filled at birth (the v1.0.0 bug).

if barstate.isconfirmed and fvgs.size() > 0
    for i = 0 to fvgs.size() - 1
        FVG g = fvgs.get(i)
        if not g.filled and bar_index > g.created_bar
            bool hit = g.bullish ? (low <= g.top) : (high >= g.bottom)
            if hit
                g.filled := true
                box ref = fvg_boxes.get(i)
                if not na(ref)
                    ref.set_bgcolor(color.new(color.gray, 90))
                    ref.set_border_color(color.gray)
                    ref.set_extend(extend.none)
                    ref.set_right(bar_index)

if barstate.isconfirmed and fvg_enabled and bar_index > 2
    float min_size = atr_value * fvg_min_size_atr

    // Bullish FVG: current low is above the high two bars back.
    if low > high[2] and (low - high[2]) >= min_size
        color bg = color.new(fvg_bullish_color, box_transparency)
        box bnew = box.new(left=bar_index - 1, top=low, right=bar_index, bottom=high[2],
             border_color=fvg_bullish_color, bgcolor=bg, extend=extend.right)
        fvgs.push(FVG.new(low, high[2], bar_index, false, true))
        fvg_boxes.push(bnew)
        while fvgs.size() > fvg_max_count
            fvgs.shift()
            box dropped = fvg_boxes.shift()
            if not na(dropped)
                dropped.delete()

    // Bearish FVG: current high is below the low two bars back.
    if high < low[2] and (low[2] - high) >= min_size
        color bg = color.new(fvg_bearish_color, box_transparency)
        box bnew = box.new(left=bar_index - 1, top=low[2], right=bar_index, bottom=high,
             border_color=fvg_bearish_color, bgcolor=bg, extend=extend.right)
        fvgs.push(FVG.new(low[2], high, bar_index, false, false))
        fvg_boxes.push(bnew)
        while fvgs.size() > fvg_max_count
            fvgs.shift()
            box dropped = fvg_boxes.shift()
            if not na(dropped)
                dropped.delete()

// =============================================================================
// SECTION 5 - Liquidity
// =============================================================================
// Equal-highs / equal-lows form liquidity pools.
// Buy-side liquidity (BSL): equal highs, where stop-losses from short
// positions cluster above price.
// Sell-side liquidity (SSL): equal lows, where stop-losses from long
// positions cluster below price.
// A new pivot within ATR-scaled tolerance of any prior pivot in the buffer
// counts as a liquidity level. The buffer holds at most PIVOT_BUFFER_SIZE
// pivots AND evicts pivots older than liq_lookback bars, so equality is
// only ever measured against recent history.

// Freeze a liquidity line once its level is consumed (swept or broken).
freezeLiqLine(line ln) =>
    if not na(ln)
        ln.set_color(color.new(color.gray, 60))
        ln.set_extend(extend.none)
        ln.set_x2(bar_index)

// Sweep / invalidation pass. Runs before creation; skips creation bars.
//   Sweep  = wick beyond the level, close back inside  -> alert + label.
//   Broken = close beyond the level (no sweep pattern) -> silent invalidation:
//            a level price has closed through is no longer resting liquidity,
//            and keeping it armed would fire bogus "swept" alerts on a later
//            routine pullback.
if barstate.isconfirmed and liqs.size() > 0
    for i = 0 to liqs.size() - 1
        LiquidityLevel lvl = liqs.get(i)
        if not lvl.swept and bar_index > lvl.created_bar
            if lvl.is_bsl
                if high > lvl.price and close < lvl.price
                    lvl.swept := true
                    bsl_swept := true
                    freezeLiqLine(liq_lines.get(i))
                    if show_labels
                        label.new(bar_index, high, "BSL Swept",
                             yloc=yloc.abovebar, style=label.style_label_down,
                             color=color.new(color.red, 30), textcolor=color.white,
                             size=size.tiny)
                else if close > lvl.price
                    lvl.swept := true
                    freezeLiqLine(liq_lines.get(i))
            else
                if low < lvl.price and close > lvl.price
                    lvl.swept := true
                    ssl_swept := true
                    freezeLiqLine(liq_lines.get(i))
                    if show_labels
                        label.new(bar_index, low, "SSL Swept",
                             yloc=yloc.belowbar, style=label.style_label_up,
                             color=color.new(color.green, 30), textcolor=color.white,
                             size=size.tiny)
                else if close < lvl.price
                    lvl.swept := true
                    freezeLiqLine(liq_lines.get(i))

if barstate.isconfirmed and liq_enabled and not na(ph)
    int piv_bar = bar_index - swing_length
    // Evict pivots older than the lookback window (buffer is chronological).
    while recent_ph_bars.size() > 0 and piv_bar - recent_ph_bars.get(0) > liq_lookback
        recent_ph_bars.shift()
        recent_ph_prices.shift()
    bool equal = false
    if recent_ph_prices.size() > 0
        for i = 0 to recent_ph_prices.size() - 1
            if math.abs(ph - recent_ph_prices.get(i)) <= atr_value * liq_tolerance_atr
                equal := true
                break
    if equal
        line new_line = line.new(piv_bar, ph, bar_index, ph, extend=extend.right,
             color=color.new(color.aqua, 30), style=line.style_dashed, width=1)
        liqs.push(LiquidityLevel.new(ph, bar_index, false, true))
        liq_lines.push(new_line)
        while liqs.size() > liq_max_count
            liqs.shift()
            line dropped = liq_lines.shift()
            if not na(dropped)
                dropped.delete()
    recent_ph_prices.push(ph)
    recent_ph_bars.push(piv_bar)
    if recent_ph_prices.size() > PIVOT_BUFFER_SIZE
        recent_ph_prices.shift()
        recent_ph_bars.shift()

if barstate.isconfirmed and liq_enabled and not na(pl)
    int piv_bar = bar_index - swing_length
    while recent_pl_bars.size() > 0 and piv_bar - recent_pl_bars.get(0) > liq_lookback
        recent_pl_bars.shift()
        recent_pl_prices.shift()
    bool equal = false
    if recent_pl_prices.size() > 0
        for i = 0 to recent_pl_prices.size() - 1
            if math.abs(pl - recent_pl_prices.get(i)) <= atr_value * liq_tolerance_atr
                equal := true
                break
    if equal
        line new_line = line.new(piv_bar, pl, bar_index, pl, extend=extend.right,
             color=color.new(color.orange, 30), style=line.style_dashed, width=1)
        liqs.push(LiquidityLevel.new(pl, bar_index, false, false))
        liq_lines.push(new_line)
        while liqs.size() > liq_max_count
            liqs.shift()
            line dropped = liq_lines.shift()
            if not na(dropped)
                dropped.delete()
    recent_pl_prices.push(pl)
    recent_pl_bars.push(piv_bar)
    if recent_pl_prices.size() > PIVOT_BUFFER_SIZE
        recent_pl_prices.shift()
        recent_pl_bars.shift()

// =============================================================================
// ALERTS
// =============================================================================
// All flags are set on confirmed bars only. Recommended alert frequency:
// "Once Per Bar Close".
alertcondition(bos_bullish,   "BoS Bullish",   "Bullish break of structure detected")
alertcondition(bos_bearish,   "BoS Bearish",   "Bearish break of structure detected")
alertcondition(choch_bullish, "CHoCH Bullish", "Bullish change of character detected")
alertcondition(choch_bearish, "CHoCH Bearish", "Bearish change of character detected")
alertcondition(bsl_swept,     "BSL Swept",     "Buy-side liquidity swept")
alertcondition(ssl_swept,     "SSL Swept",     "Sell-side liquidity swept")

Overview

Active zones project forward and freeze or stop extending once mitigated or filled. Users can configure swing detection lengths, display limits, volume filters for order blocks, and minimum ATR thresholds for FVGs and liquidity tolerance. All state logic executes on confirmed bars to prevent real-time repainting, serving as an analytical charting tool without execution logic.

Details

Published by

btankutt on GitHub

Draws

On the price chart

Markets

Forex, Crypto, Gold

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

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

SettingTypeDefaultVariable
Swing detection lengthint5swing_length
Show structure labelsbooltrueshow_external_structure
Enable Order Blocksbooltrueob_enabled
Max OBs to display (total)int5ob_max_count
Filter by volumebooltrueob_volume_filter
Bullish OB colorcolorcolor.new(color.green, 70)ob_bullish_color
Bearish OB colorcolorcolor.new(color.red, 70)ob_bearish_color
Enable FVGbooltruefvg_enabled
Max FVGs to displayint5fvg_max_count
Min FVG size (ATR multiplier)float0.5fvg_min_size_atr
Bullish FVG colorcolorcolor.new(color.aqua, 80)fvg_bullish_color
Bearish FVG colorcolorcolor.new(color.orange, 80)fvg_bearish_color
Show all 18 settings
SettingTypeDefaultVariable
Enable Liquiditybooltrueliq_enabled
Max liquidity levelsint10liq_max_count
Equal highs/lows lookback (bars)int50liq_lookback
Tolerance (ATR multiplier)float0.2liq_tolerance_atr
Show event labelsbooltrueshow_labels
Box transparencyint70box_transparency
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 tracks smart money market structure directly on the price chart. It calculates dual-period swing highs and swing lows to detect Changes of Character (CHoCH), Breaks of Structure (BOS), inducements, and liquidity sweeps. When structural levels ar

Indicator v5 SMC / ICT / price actionSupport & resistance
Updated 1 year ago · Apache-2.0 GitHub repository of Market Structure with Inducements & Sweeps [LuxAlgo]
24 stars

This indicator maps Smart Money Concepts (SMC) market structure directly onto the price chart. It detects internal and swing structure breaks (BOS and CHoCH), tracks bullish and bearish order blocks, identifies fair value gaps (FVG), highlights equal highs and

Indicator v5 SMC / ICT / price actionSupport & resistance Repaints
Updated 12 days ago · Custom licence GitHub repository of Smart Money Concepts [LuxAlgo] Test B
13 stars

This script identifies and visualizes bullish and bearish order blocks on the price chart. It detects low-volatility consolidation ranges followed by breakout moves accompanied by high trading volume. Users can select between Simple, Relative, or Weighted volu

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 6 months ago · MIT GitHub repository of Advanced Order Blocks with Volume

This indicator implements a Wyckoff method state machine that tracks accumulation, distribution, markup, and markdown regimes across phases A through E. It identifies structural events including springs, UTADs, SOS, SOW, LPS, LPSY, and climactic bars using ATR

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 3 days ago · MIT GitHub repository of Modern Wyckoff State Machine Lite [WavesUnchained]
9 stars

This multi-timeframe indicator detects and visualizes Smart Money Concepts (SMC) and ICT market structures on the price chart. It maps higher-timeframe dealing ranges, premium and discount zones, break of structure (BOS), change of character (CHoCH), order blo

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 8 months ago · None stated GitHub repository of SMC/ICT Zones Pro Generalized

More SMC / ICT 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