Indicator · Pine Script v6 · On the chart

ICT Displacement Candles Indicator

by ArunKBhaskar

The indicator plots ICT displacement candles on the price chart and can switch to retracement scanning.

View on GitHub

GitHub stars575on the repository
Pine versionv6current
Lines of code325
Settings25inputs
LicenceMPL-2.0
Last update1 year ago30 Mar 2025

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

325 lines of Pine Script v6 from ICT Displacement Candles/[Indicator] ICT Displacement Candles.txt, published under MPL-2.0. Keep the author's credit and licence lines when you reuse it.

[Indicator] ICT Displacement Candles.txt
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Arun_K_Bhaskar

//@version=6
indicator(title = 'ICT Displacement Candles Indicator', shorttitle = 'ICTDC', overlay = true, max_lines_count = 500, max_labels_count = 500, behind_chart = false)

//___________________________ Menu Start

string g_scn_tb = '█████████████████ Scanner █████████████████'

string tt_ch = 
 "Displacement:" + 
 "\n• Strong, sudden price move (up/down) with long candles, minimal wicks." + 

 "\n\n Retracement:" + 
 "\n• Price retraces to a Fibonacci level of the displacement." +
 "\n• Potential entry point for trend continuation."

string tt_is = 
 "• Reads only the first 40 symbols." + 
 "\n• Max 4096 characters." + 
 "\n• Format: EXCHANGE:SYMBOL_A,EXCHANGE:SYMBOL_B"

string i_scn_choose = input.string(
 defval = 'Displacement', 
 title = 'Scanning Method', 
 options = ['Displacement', 'Retracement'], tooltip = tt_ch, group = g_scn_tb)

bool i_scn_show_long = input.bool(defval = true, title = 'Long Signals', inline = 'tb_2', group = g_scn_tb)
bool i_scn_show_short = input.bool(defval = true, title = 'Short Signals', inline = 'tb_2', group = g_scn_tb)

string g_dc = '████████████ Displacement Candles ████████████'

string tt_mb = "Shows if bars exceed the set value."
string tt_dev = "Specifies the minimal size of displament, as a percentage of the average high-low range for the last 14 bars."
string tt_ret_fib = 
 "• 0: Top of bullish & bottom of bearish displacement." + 
 "\n• 1: Bottom of bullish & top of bearish displacement." + 
 "\n• 0.5: 50% of the displacement."

int i_dc_min_bars = input.int(defval = 3, title = 'Minimum Bars', minval = 1, tooltip = tt_mb, group = g_dc)
float i_dc_dev_percent = nz(input.float(60.0, "Minimal Deviation (%)", minval=1, step = 10, tooltip = tt_dev, group = g_dc) / 100 * ta.sma(high-low, 14))
bool i_dc_close_filter = input.bool(defval = true, title = 'Apply Close Above/Below Prev Close', group = g_dc)
bool i_dc_hl_filter = input.bool(defval = false, title = 'Apply Close Above/Below Prev High/Low', group = g_dc)
float i_dc_fib_val = input.float(defval = 0.5, title = 'Fibonacci Value', step = 0.1, tooltip = tt_ret_fib, group = g_dc)

string g_af = '██████████████ Additional Fiters ██████████████'

string tt_atr = "• Filters out longer or more volatile displacement candles."
string tt_atr_mul = "• Higher values filter longer or more volatile candles."
string tt_bf = "• 80 means the body covers 80%+ of the displacement candle."
string tt_tf = "• Filter signals within a given time."
string tt_df = "• Filter signals on specified dates (for Retracement Candles only)."

bool i_atr_filter = input.bool(defval = false, title = 'Apply ATR Filter', tooltip = tt_atr, group = g_af)
int i_atr_length = input.int(defval = 14, minval = 1, title = 'ATR Length', group = g_af)
float i_atr_multi = input.float(defval = 1, title = 'ATR Multiplier', minval = 1, group = g_af)

bool i_body_filter = input.bool(defval = false, title = 'Apply Body % Filter', tooltip = tt_bf, group = g_af)
float i_body_percent = input.float(defval = 70, title = 'Body % Above', minval = 0, maxval = 100, group = g_af) / 100

bool i_time_filter = input.bool(defval = false, title = 'Apply Time Filter', tooltip = tt_tf, group = g_af)
int i_hour_1 = input.int(defval = 9, minval = 0, title = 'Time From', inline = 't_1', group = g_af)
int i_minute_1 = input.int(defval = 15, minval = 0, title = ':', inline = 't_1', group = g_af)
int i_hour_2 = input.int(defval = 10, minval = 0, title = 'Time To ', inline = 't_2', group = g_af)
int i_minute_2 = input.int(defval = 15, minval = 0, title = ':', inline = 't_2', group = g_af)

bool i_date_filter = input.bool(defval = false, title = 'Apply Date Filter', tooltip = tt_df, group = g_af)
int i_day = input.int(defval = 30, minval = 1, maxval = 31, title = 'Day', group = g_af)
int i_month = input.int(defval = 3, minval = 1, maxval = 12, title = 'Month', group = g_af)
int i_year = input.int(defval = 2025, minval = 0, title = 'Year', group = g_af)

string g_cum = '█████████████ Performance Table █████████████'

bool i_cum_tbl_disp = input.bool(defval = true, title = 'Display', group = g_cum)
string i_cum_tbl_pos = input.string(defval = position.bottom_right, title = 'Position', options = [position.top_left, position.top_center, position.top_right, position.middle_left, position.middle_center, position.middle_right, position.bottom_left, position.bottom_center, position.bottom_right], group = g_cum)
string i_cum_tbl_size = input.string(defval = size.normal, title = 'Size', options = [size.auto, size.tiny, size.small, size.normal, size.large, size.huge], group = g_cum)

//string g_ch = '█████████████████ Colors █████████████████'
color i_pos_color = #089981 //input.color(defval = #089981, title = 'Positive', group = g_ch)
color i_pos_light_color = #70CCBD //input.color(defval = #70CCBD, title = 'Positive Light', group = g_ch)
color i_neg_light_color = #FAA1A4 //input.color(defval = #FAA1A4, title = 'Negative Light', group = g_ch)
color i_neg_color = #F23645 //input.color(defval = #F23645, title = 'Negative', group = g_ch)
color i_neu_dark_color = #0F0F0F //input.color(defval = #0F0F0F, title = 'Neutral', group = g_ch)

//___________________________ Menu End

//___________________________ Performance Start

is_new_day = ta.change(time('D')) != 0

// Cumulative Percentage Change
var float cum_pchg = na
day_pchg = na(close[1]) ? 0 : (close - close[1]) / close[1] * 100
cum_pchg := is_new_day ? day_pchg : na(cum_pchg) ? day_pchg : cum_pchg + day_pchg

// Cumulative Volume and Volume Percentage Change
var float curr_cum_vol = na
var float prev_cum_vol = na
if is_new_day
    prev_cum_vol := curr_cum_vol
    curr_cum_vol := volume
    curr_cum_vol
else
    curr_cum_vol := na(curr_cum_vol) ? volume : curr_cum_vol + volume
    curr_cum_vol
prev_vol_safe = nz(prev_cum_vol, curr_cum_vol)
cum_vol_pchg = (curr_cum_vol - prev_vol_safe) / prev_vol_safe * 100

var table tbl_cum = table.new(position=i_cum_tbl_pos, columns=2, rows=4, border_width=1, force_overlay=true)

cell_perform(col, row, txt, txt_color, aligh) =>
    table.cell(tbl_cum, col, row, txt, text_color=txt_color, text_halign=aligh, bgcolor=i_neu_dark_color, text_size=i_cum_tbl_size)

if barstate.islast and i_cum_tbl_disp
    pchg_col = cum_pchg > 0 ? i_pos_color : i_neg_color
    vol_pchg_col = cum_vol_pchg > 0 ? i_pos_color : i_neg_color
    prev_vol_pchg_col = prev_vol_safe < curr_cum_vol ? i_neg_color : i_pos_color
    
    cell_perform(0, 0, '%Chg', chart.fg_color, text.align_left)
    cell_perform(1, 0, str.tostring(cum_pchg, '#.##') + ' %', pchg_col, text.align_right)
    cell_perform(0, 1, 'Vol %Chg', chart.fg_color, text.align_left)
    cell_perform(1, 1, str.tostring(cum_vol_pchg, '#.##') + ' %', vol_pchg_col, text.align_right)
    cell_perform(0, 2, 'Vol', chart.fg_color, text.align_left)
    cell_perform(1, 2, str.tostring(curr_cum_vol / 100000, '#.##') + ' L', vol_pchg_col, text.align_right)
    cell_perform(0, 3, 'PD Vol', chart.fg_color, text.align_left)
    cell_perform(1, 3, str.tostring(prev_vol_safe / 100000, '#.##') + ' L', prev_vol_pchg_col, text.align_right)

//___________________________ Performance End

//___________________________ Additional Filters Start

// Pre-calculate common values
candle_range = high - low
body_size = math.abs(close - open)

// ATR Filter
atr_filter = not i_atr_filter or candle_range > ta.atr(i_atr_length) * i_atr_multi

// Body Filters
body_filter = not i_body_filter or candle_range > 0 and body_size / candle_range >= i_body_percent

// Time Filter
time_filter = 
 not i_time_filter or 
 (hour > i_hour_1 or hour == i_hour_1 and minute >= i_minute_1) and 
 (hour < i_hour_2 or hour == i_hour_2 and minute < i_minute_2)

// Date Filter
date_filter = not i_date_filter or year == i_year and month == i_month and dayofmonth == i_day

//___________________________ Additional Filters End

//___________________________ Displacement Candles Start

// Combined tracking variables
var int bullCnt = 0
var int bearCnt = 0
var float bullHi = na
var float bullLo = na
var float bearHi = na
var float bearLo = na
var float bullFib = na
var float bearFib = na
var bullHighs = array.new_float()
var bullLows = array.new_float()
var bearHighs = array.new_float()
var bearLows = array.new_float()

// Conditions and filters combined
float priceChg = (high - low)
bool bullish = priceChg >= i_dc_dev_percent and close > open and (not i_dc_close_filter or close > close[1]) and (not i_dc_hl_filter or close > high[1]) and atr_filter
bool bearish = priceChg >= i_dc_dev_percent and close < open and (not i_dc_close_filter or close < close[1]) and (not i_dc_hl_filter or close < low[1]) and atr_filter

// Optimized counting and array management
if bullish
    bullCnt := bullCnt + 1
    bearCnt := 0
    array.push(bullHighs, high)
    array.push(bullLows, low)
    if bullCnt == 1
        array.clear(bearHighs)
        array.clear(bearLows)
else if bearish
    bearCnt := bearCnt + 1
    bullCnt := 0
    array.push(bearHighs, high)
    array.push(bearLows, low)
    if bearCnt == 1
        array.clear(bullHighs)
        array.clear(bullLows)
else
    bullCnt := 0
    bearCnt := 0
    array.clear(bullHighs)
    array.clear(bullLows)
    array.clear(bearHighs)
    array.clear(bearLows)

// Calculate high-low range and percentage
float bullRange = na
float bearRange = na
float bullRangePercent = na
float bearRangePercent = na

if bullCnt >= i_dc_min_bars
    bullHi := array.max(bullHighs)
    bullLo := array.min(bullLows)
    bullRange := bullHi - bullLo
    bullRangePercent := (bullRange / bullLo) * 100
    bullFib := bullHi - (bullHi - bullLo) * i_dc_fib_val
if bearCnt >= i_dc_min_bars
    bearHi := array.max(bearHighs)
    bearLo := array.min(bearLows)
    bearRange := bearHi - bearLo
    bearRangePercent := (bearRange / bearLo) * 100
    bearFib := bearLo + (bearHi - bearLo) * i_dc_fib_val

bearMaxCnt = bearCnt[1] >= i_dc_min_bars and bearCnt == 0
bullMaxCnt = bullCnt[1] >= i_dc_min_bars and bullCnt == 0

// Plot
if bearMaxCnt and i_scn_show_short
    label.new(x = bar_index[1], y = low[1], text = str.tostring(bearCnt[1]), color = na, textcolor = i_neg_light_color, size = size.small, style = label.style_label_up, yloc = yloc.belowbar)
//    label.new(x = bar_index[1], y = low[1], text = str.format("{0,number,#.##}%", bearRangePercent[1]), color = na, textcolor = i_neg_light_color, size = size.small, style = label.style_label_up, yloc = yloc.belowbar)

if bullMaxCnt and i_scn_show_long
    label.new(x = bar_index[1], y = high[1], text = str.tostring(bullCnt[1]), color = na, textcolor = i_pos_light_color, size = size.small, style = label.style_label_down, yloc = yloc.abovebar)
//    label.new(x = bar_index[1], y = high[1], text = str.format("{0,number,#.##}%", bullRangePercent[1]), color = na, textcolor = i_pos_light_color, size = size.small, style = label.style_label_down, yloc = yloc.abovebar)

// Plot counts
//if bearCnt >= i_dc_min_bars and i_scn_show_short
//    label.new(x = bar_index, y = low, text = str.tostring(bearCnt), color = na, textcolor = i_neg_light_color, size = size.small, style = label.style_label_up, yloc = yloc.belowbar)
//if bullCnt >= i_dc_min_barst and i_scn_show_long
//    label.new(x = bar_index, y = high, text = str.tostring(bullCnt), color = na, textcolor = i_pos_light_color, size = size.small, style = label.style_label_down, yloc = yloc.abovebar)

plot(series = bearFib, title = 'Bearish Fib Line', color = i_neg_color, style = plot.style_stepline, display = display.none)
plot(series = bullFib, title = 'Bullish Fib Line', color = i_pos_color, style = plot.style_stepline, display = display.none)

// Track the final count before reset
var int lastBullCnt = 0
var int lastBearCnt = 0

// Update when sequence ends
if bullMaxCnt
    lastBullCnt := bullCnt[1]
if bearMaxCnt
    lastBearCnt := bearCnt[1]

// Retracement tracking combined
var bool bullActive = false
var bool bearActive = false
var bool bullDone = false
var bool bearDone = false
var int bullBar = na
var int bearBar = na
var int bullStart = na
var int bearStart = na
var float bullLow = na
var float bearHigh = na
var line bullLine = na
var line bearLine = na

// Activate sequences
if bullCnt >= i_dc_min_bars and bullCnt[1] < i_dc_min_bars
    bullActive := true
    bearActive := false
    bullDone := false
    bearDone := false
    bullStart := bar_index - bullCnt + 1
if bearCnt >= i_dc_min_bars and bearCnt[1] < i_dc_min_bars
    bearActive := true
    bullActive := false
    bearDone := false
    bullDone := false
    bearStart := bar_index - bearCnt + 1

// Detect and mark retracements
bool bearRet = bearActive and not bearDone and ta.crossover(high, bearFib) and high[1] < bearFib and time_filter and date_filter
bool bullRet = bullActive and not bullDone and ta.crossunder(low, bullFib) and low[1] > bullFib and time_filter and date_filter
if bearRet and i_scn_choose == 'Retracement' and i_scn_show_short
    bearDone := true
    bearBar := bar_index
    bearHigh := high
    bearLine := line.new(x1 = bearStart, y1 = bearFib, x2 = bearBar, y2 = bearFib, color = i_neg_light_color, style = line.style_dotted)
if bullRet and i_scn_choose == 'Retracement' and i_scn_show_long
    bullDone := true
    bullBar := bar_index
    bullLow := low
    bullLine := line.new(x1 = bullStart, y1 = bullFib, x2 = bullBar, y2 = bullFib, color = i_pos_light_color, style = line.style_dotted)

// Plot signals
plotshape(i_scn_show_short and i_scn_choose == 'Retracement' ? bearRet : false, title = 'Bearish Retracement', style = shape.triangledown, location = location.abovebar, color = i_neg_light_color, size = size.tiny)
plotshape(i_scn_show_long and i_scn_choose == 'Retracement' ? bullRet : false, title = 'Bullish Retracement', style = shape.triangleup, location = location.belowbar, color = i_pos_light_color, size = size.tiny)
barcolor(i_scn_show_short and i_scn_choose == 'Retracement' and bearRet ? i_neg_light_color : i_scn_show_long and i_scn_choose == 'Retracement' and bullRet ? i_pos_light_color : na, title = 'Retracement Candle')

//___________________________ Displacement Candles End

//___________________________ Code End

// Readme
// 
// Indicator Title: "ICT Displacement Candles Scanner"
// 
// Overview
// - A price action trading method based on strong price moves (displacement).
// - Helps identify trend direction and potential trade entries.
//
// Features
// - Scanning Methods:
//   - Displacement: Strong, sudden price move (up/down) with long candles, minimal wicks.
//   - Retracement: Price retraces to a Fibonacci level of the displacement.
//
// How to Use?
// 1. Identify Displacement: Look for strong price movement after liquidity is taken.
// 2. Wait for Retracement: Use Fibonacci to find entry levels (e.g., 61.8%).
// 3. Confirm with Order Blocks or Fair Value Gap(FVG): Ensure price reacts at an institutional level.
// 4. Enter Trade: Buy or sell based on trend continuation signals.
// 5. Set Targets: Aim for the next liquidity zone.
//
// Note: Read tooltips for more clarity.
// 
// Questions?: Message the author on TradingView: https://www.tradingview.com/u/Arun_K_Bhaskar/
// 
// More Indicators: Free TradingView indicators and source code on GitHub: https://github.com/ArunKBhaskar/PineScript

Overview

Displacement requires a move larger than a set share of the 14-bar average high-low range, lasting at least a chosen number of bars, with optional close, previous high-low, ATR, and candle-body filters. Retracement mode marks when price returns to a chosen Fibonacci level of that displacement. Users can show long or short signals and apply a time window or a date filter. A cumulative table can appear in a chosen corner. It is not a strategy and has no exits.

Details

Published by

ArunKBhaskar on GitHub

Type

Indicator, Pine Script v6

Draws

On the price chart

Category

SMC / ICT / price action, Candlestick patterns, Screeners & dashboards

Markets

Any symbol

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.

Topics

pinescripttradingview

Settings

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

SettingTypeDefaultVariable
Scanning MethodstringDisplacementi_scn_choose
Long Signalsbooltruei_scn_show_long
Short Signalsbooltruei_scn_show_short
Minimum Barsint3i_dc_min_bars
Minimal Deviation (%)float60.0Minimal Deviation (%)
Apply Close Above/Below Prev Closebooltruei_dc_close_filter
Apply Close Above/Below Prev High/Lowboolfalsei_dc_hl_filter
Fibonacci Valuefloat0.5i_dc_fib_val
Apply ATR Filterboolfalsei_atr_filter
ATR Lengthint14i_atr_length
ATR Multiplierfloat1i_atr_multi
Apply Body % Filterboolfalsei_body_filter
Show all 25 settings
SettingTypeDefaultVariable
Body % Abovefloat70i_body_percent
Apply Time Filterboolfalsei_time_filter
Time Fromint9i_hour_1
:int15i_minute_1
Time To int10i_hour_2
:int15i_minute_2
Apply Date Filterboolfalsei_date_filter
Dayint30i_day
Monthint3i_month
Yearint2025i_year
Displaybooltruei_cum_tbl_disp
Positionstringposition.bottom_righti_cum_tbl_pos
Sizestringsize.normali_cum_tbl_size
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

Confluence Suite

by TamaraKGreen
46 stars

The Confluence Suite indicator draws multiple trading signals and tools directly on the price chart. It generates entry and exit signals based on selected modes and filters, with an AI signal classifier rating quality from 1-4. Additional features include smar

Indicator v5 TrendSMC / ICT / price action
Updated 7 weeks ago · None stated GitHub repository of Confluence Suite

Fractal Reclaim Strength

by selimgrsoy0-commits
12 stars

The indicator tracks four-bar fractal sweep and reclaim setups on chart timeframes of 15 minutes and above. It calculates Reclaim Strength based on where C2 closes relative to C1's range and plots level lines for the swept C1 extreme and C2 extreme. An on-scre

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 7 weeks ago · None stated GitHub repository of Fractal Reclaim Strength
12 stars

This overlay indicator assigns a next-candle bias from the prior candle: previous-candle high, previous-candle low, an inside-bar version of that bias, or none. Outside bars clear the bias. After each confirmed bar it records whether price tags the prior high

Indicator v5 SMC / ICT / price actionCandlestick patterns
Updated 1 year ago · None stated GitHub repository of Simplified Next Day Bias Model

Golden Bullet Strategy

by TradersPost
218 stars

The Golden Bullet Strategy is an overlay signal indicator based on Smart Money Concepts and time-based liquidity models. It identifies liquidity sweeps of a designated reference session range during a specified hunt window. It then confirms Market Structure Sh

Indicator v6 SMC / ICT / price actionSessions & time
Updated 3 months ago · None stated GitHub repository of Golden Bullet Strategy
56 stars

This indicator identifies fractal-based pivot highs and lows to map out market structure directly on the price chart. It detects bullish and bearish structure breaks, automatically labeling Break of Structure (BOS) and Change of Character (ChoCH) events when p

Indicator v5 SMC / ICT / price actionSupport & resistance
Updated 2 months ago · None stated GitHub repository of Market Structure (Fractal)
53 stars

Apex Trend & Liquidity Master calculates a trend cloud using customizable moving averages expanded by a volatility multiplier directly on the main price chart. It identifies dynamic support and resistance liquidity zones from swing high and low pivots, extendi

Indicator v6 TrendSupport & resistance
Updated 2 months ago · MPL-2.0 GitHub repository of Apex Trend & Liquidity Master

More indicators

Trade Your Charts With a Regulated Broker

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

Compare brokers