Smart Money Concepts (ICT) Trading Strategy: Complete Guide with Code
Learn Smart Money Concepts including Break of Structure, Change of Character, Order Blocks, and Fair Value Gaps. Includes PineScript code for TradingView.
Smart Money Concepts (SMC) trading has rapidly grown in popularity, offering traders a framework to understand how institutional players move markets. This guide covers the core SMC concepts — BOS, CHOCH, Order Blocks, Fair Value Gaps, and liquidity sweeps — with PineScript code for TradingView.
What Are Smart Money Concepts?
Smart Money Concepts is a trading methodology based on the idea that large institutional traders ("smart money") leave footprints in price action that retail traders can identify and follow.
Core Principles:
- Markets are driven by institutional order flow, not retail traders
- Institutions need liquidity to fill large orders
- Price moves from one liquidity pool to another
- Structural shifts in price reveal institutional intent
Key SMC Terminology:
| Term | Abbreviation | Meaning |
|---|---|---|
| Break of Structure | BOS | Price breaks a swing high/low in the direction of the trend |
| Change of Character | CHOCH | Price breaks a swing high/low against the trend (reversal signal) |
| Order Block | OB | The last opposing candle before a strong move (institutional entry zone) |
| Fair Value Gap | FVG | A three-candle imbalance where price moved too fast, leaving a gap |
| Liquidity Sweep | — | Price moves beyond a key level to trigger stop losses before reversing |
Break of Structure (BOS)
BOS confirms the current trend is continuing. In an uptrend, BOS occurs when price breaks above the most recent swing high.
//@version=5
indicator("Break of Structure", overlay=true, max_labels_count=500)
swingLength = input(5, "Swing Length")
// Detect swing highs and lows
swingHigh = ta.pivothigh(high, swingLength, swingLength)
swingLow = ta.pivotlow(low, swingLength, swingLength)
// Track last swing levels
var float lastSwingHigh = na
var float lastSwingLow = na
var int lastSwingHighBar = na
var int lastSwingLowBar = na
if (not na(swingHigh))
lastSwingHigh := swingHigh
lastSwingHighBar := bar_index - swingLength
if (not na(swingLow))
lastSwingLow := swingLow
lastSwingLowBar := bar_index - swingLength
// BOS detection
bosUp = not na(lastSwingHigh) and close > lastSwingHigh and close[1] <= lastSwingHigh
bosDown = not na(lastSwingLow) and close < lastSwingLow and close[1] >= lastSwingLow
// Plot BOS labels
if (bosUp)
label.new(bar_index, low, "BOS ↑", color=color.green, textcolor=color.white, style=label.style_label_up, size=size.small)
if (bosDown)
label.new(bar_index, high, "BOS ↓", color=color.red, textcolor=color.white, style=label.style_label_down, size=size.small)Change of Character (CHOCH)
CHOCH signals a potential trend reversal. It's the first BOS in the opposite direction of the current trend.
The key difference: BOS continues the trend, CHOCH breaks it.
Example:
- Uptrend → price breaks below the last swing low → CHOCH (bearish reversal)
- Downtrend → price breaks above the last swing high → CHOCH (bullish reversal)
//@version=5
indicator("CHOCH Detection", overlay=true, max_labels_count=500)
swingLength = input(5, "Swing Length")
swingHigh = ta.pivothigh(high, swingLength, swingLength)
swingLow = ta.pivotlow(low, swingLength, swingLength)
var float lastSH = na
var float lastSL = na
var int trend = 0 // 1 = up, -1 = down
if (not na(swingHigh))
lastSH := swingHigh
if (not na(swingLow))
lastSL := swingLow
// Detect trend direction changes
chochUp = trend == -1 and not na(lastSH) and close > lastSH and close[1] <= lastSH
chochDown = trend == 1 and not na(lastSL) and close < lastSL and close[1] >= lastSL
if (chochUp)
trend := 1
label.new(bar_index, low, "CHOCH ↑", color=color.teal, textcolor=color.white, style=label.style_label_up, size=size.small)
if (chochDown)
trend := -1
label.new(bar_index, high, "CHOCH ↓", color=color.purple, textcolor=color.white, style=label.style_label_down, size=size.small)
// BOS in direction of trend
bosUp = trend == 1 and not na(lastSH) and close > lastSH and close[1] <= lastSH and not chochUp
bosDown = trend == -1 and not na(lastSL) and close < lastSL and close[1] >= lastSL and not chochDownOrder Blocks
An Order Block is the last bearish candle before a bullish move (bullish OB) or the last bullish candle before a bearish move (bearish OB). These represent zones where institutions placed large orders.
//@version=5
indicator("Order Blocks", overlay=true, max_boxes_count=500)
obLength = input(5, "OB Lookback")
obShowLast = input(5, "Show Last N OBs")
// Bullish Order Block: last bearish candle before a strong bullish move
bullishOB = close[1] < open[1] and close > high[1] and close > high[2]
// Bearish Order Block: last bullish candle before a strong bearish move
bearishOB = close[1] > open[1] and close < low[1] and close < low[2]
// Draw Bullish OB zone
if (bullishOB)
box.new(bar_index - 1, high[1], bar_index + 20, low[1],
border_color=color.green, bgcolor=color.new(color.green, 85))
// Draw Bearish OB zone
if (bearishOB)
box.new(bar_index - 1, high[1], bar_index + 20, low[1],
border_color=color.red, bgcolor=color.new(color.red, 85))Trading Order Blocks:
- Identify the OB zone after a BOS or CHOCH
- Wait for price to retrace into the OB zone
- Enter with a tight stop loss below/above the OB
- Target the next liquidity level or opposing OB
Fair Value Gaps (FVG)
A Fair Value Gap is a three-candle pattern where the wick of candle 1 doesn't overlap with the wick of candle 3, creating an imbalance that price tends to fill.
//@version=5
indicator("Fair Value Gaps", overlay=true, max_boxes_count=500)
// Bullish FVG: gap between candle 1 high and candle 3 low
bullishFVG = low > high[2] // Current low is above the high from 2 bars ago
// Bearish FVG: gap between candle 1 low and candle 3 high
bearishFVG = high < low[2] // Current high is below the low from 2 bars ago
// Draw Bullish FVG
if (bullishFVG)
box.new(bar_index - 1, low, bar_index + 15, high[2],
border_color=color.green, bgcolor=color.new(color.green, 90))
// Draw Bearish FVG
if (bearishFVG)
box.new(bar_index - 1, low[2], bar_index + 15, high,
border_color=color.red, bgcolor=color.new(color.red, 90))FVG Trading Rules:
- Bullish FVG: Expect price to retrace into the gap and bounce higher
- Bearish FVG: Expect price to retrace into the gap and drop lower
- FVGs in the direction of the trend have the highest fill probability
- Unfilled FVGs act as magnets for price
Liquidity Sweeps
Liquidity rests above swing highs (buy stops) and below swing lows (sell stops). Institutions sweep these levels to fill large orders before the real move.
How to trade liquidity sweeps:
- Identify key swing highs/lows where stops are likely clustered
- Wait for price to sweep beyond the level (wick through, body closes back)
- Look for a CHOCH or BOS in the opposite direction
- Enter with a stop loss beyond the sweep wick
Complete SMC Trading Strategy
Combining all concepts into a systematic strategy:
//@version=5
strategy("SMC Strategy", overlay=true)
swingLen = input(5, "Swing Length")
// Swing points
swingHigh = ta.pivothigh(high, swingLen, swingLen)
swingLow = ta.pivotlow(low, swingLen, swingLen)
var float lastSH = na
var float lastSL = na
if (not na(swingHigh))
lastSH := swingHigh
if (not na(swingLow))
lastSL := swingLow
// BOS / CHOCH detection
bosUp = not na(lastSH) and close > lastSH and close[1] <= lastSH
bosDown = not na(lastSL) and close < lastSL and close[1] >= lastSL
// Fair Value Gap
bullishFVG = low > high[2]
bearishFVG = high < low[2]
// Order Block (simplified)
bullishOB = close[1] < open[1] and close > high[1]
bearishOB = close[1] > open[1] and close < low[1]
// Long: BOS up + Bullish OB or FVG
longCondition = bosUp and (bullishOB or bullishFVG)
if (longCondition)
strategy.entry("Long", strategy.long)
strategy.exit("Long SL", "Long", stop=lastSL)
// Short: BOS down + Bearish OB or FVG
shortCondition = bosDown and (bearishOB or bearishFVG)
if (shortCondition)
strategy.entry("Short", strategy.short)
strategy.exit("Short SL", "Short", stop=lastSH)SMC vs Traditional Technical Analysis
| Aspect | Smart Money Concepts | Traditional TA |
|---|---|---|
| Foundation | Institutional order flow | Price patterns and indicators |
| Key tools | BOS, CHOCH, OB, FVG | RSI, MACD, Moving Averages |
| Support/Resistance | Order Blocks, liquidity zones | Horizontal levels, trendlines |
| Trend detection | Structure shifts (BOS/CHOCH) | Moving average crossovers |
| Entries | OB and FVG retracements | Indicator signals |
| Works best on | Higher timeframes (15min+) | All timeframes |
| Learning curve | Steep | Moderate |
Common SMC Mistakes
- Trading every BOS — Not all structural breaks lead to tradeable moves; confirm with OBs or FVGs
- Ignoring higher timeframe context — SMC works best when aligned with the higher timeframe trend
- Drawing Order Blocks everywhere — Only the most recent, unmitigated OBs matter
- Forgetting risk management — SMC doesn't eliminate the need for stop losses
- Over-complicating entries — You don't need every SMC concept on every trade
SpendDock Supports Smart Money Concepts
SpendDock natively supports all SMC indicators:
- BOS (Bullish/Bearish) — Break of Structure detection
- CHOCH (Bullish/Bearish) — Change of Character detection
- Order Blocks (Bullish/Bearish) — Institutional entry zones
- Fair Value Gaps (Bullish/Bearish) — Price imbalance zones
- Swing High/Low — Market structure pivots
Describe your SMC strategy in plain English:
"Enter long when there's a bullish CHOCH and price retraces into a bullish Order Block. Set stop loss below the Order Block. Target the next swing high."
SpendDock generates production-ready PineScript code with all the SMC detection logic built in — no manual coding required.
Conclusion
Smart Money Concepts offer a powerful framework for understanding institutional price action. Key takeaways:
- BOS confirms trend continuation; CHOCH signals reversal
- Order Blocks are high-probability entry zones after structural shifts
- Fair Value Gaps act as magnets that price tends to fill
- Liquidity sweeps reveal where institutions are hunting stops
- Combine SMC with proper risk management for consistent results
Ready to build your own SMC strategy? Try SpendDock and generate production-ready code with built-in Smart Money Concepts support.
Skip the Coding — Generate Your Strategy
Describe your trading strategy in plain English and get production-ready code for TradingView, MetaTrader, NinjaTrader, or Python.
Try SpendDock Free