// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at
https://mozilla.org/MPL/2.0/
// © AlgoAlpha
//@version=6
indicator("Change in State of Delivery CISD [AlgoAlpha]", "AlgoAlpha - CISD", true, max_lines_count = 500, behind_chart = false)
tolerence = input.float(0.7, "Noise Filter", group = "Calculations", tooltip = "Determines which levels to use as CSID triggers, a larger setting results in less noise", maxval = 1, minval = 0, step = 0.1)
len = input.int(12, "Swing Period", group = "Calculations", tooltip = "The period to detect swing points, a larger setting will detect longer term swings")
expiry_bars = input.int(100, "Expiry Bars", group = "Calculations", tooltip = "Number of bars after which old liquidity lines stop updating")
liquidity_lookback = input.int(10, "Liquidity Lookback", group = "Calculations", tooltip = "Lookback period to check if opposing liquidity was wicked before a CISD")
green = input.color(#00ffbb, title = "Bullish Colour", group = "Appearance", tooltip = "Color used for bullish visuals and positive sentiment texts.")
red = input.color(#ff1100, title = "Bearish Colour", group = "Appearance", tooltip = "Color used for bearish visuals and negative sentiment texts.")
t1 = input.int(90, "Candle Body Transperency", maxval = 100, minval = 0, group = "Appearance")
t2 = input.int(40, "Candle Wick/Border Transperency", maxval = 100, minval = 0, group = "Appearance")
hide_expired_levels = input.bool(true, "Hide Expired Levels", group = "Appearance", tooltip = "Delete liquidity levels once they exceed the expiry bar threshold.")
hide_mitigated_levels = input.bool(false, "Hide Mitigated Levels", group = "Appearance", tooltip = "Delete liquidity levels from the chart as soon as price mitigates them.")
pivlow = ta.pivotlow(len, len)
pivhigh = ta.pivothigh(len, len)
var swinghighs = array.new_line()
var swinglows = array.new_line()
if not na(pivhigh)
swinghighs.unshift(line.new(bar_index-len, high[len], bar_index, high[len], color = color.new(chart.fg_color, 50)))
if not na(pivlow)
swinglows.unshift(line.new(bar_index-len, low[len], bar_index, low[len], color = color.new(chart.fg_color, 50)))
var float last_wicked_high_level = na
var float last_wicked_low_level = na
wicked_high = false
wicked_low = false
if swinghighs.size() > 0
for i = swinghighs.size() - 1 to 0
if i < swinghighs.size()
l = swinghighs.get(i)
if bar_index - line.get_x1(l) < expiry_bars
lvl = line.get_y1(l)
line.set_x2(l, bar_index)
if high >= lvl and barstate.isconfirmed
if hide_mitigated_levels
line.delete(l)
swinghighs.remove(i)
wicked_high := true
last_wicked_high_level := lvl
else
if hide_expired_levels
line.delete(l)
swinghighs.remove(i)
if swinglows.size() > 0
for i = swinglows.size() - 1 to 0
if i < swinglows.size()
l = swinglows.get(i)
if bar_index - line.get_x1(l) < expiry_bars
lvl = line.get_y1(l)
line.set_x2(l, bar_index)
if low <= lvl and barstate.isconfirmed
if hide_mitigated_levels
line.delete(l)
swinglows.remove(i)
wicked_low := true
last_wicked_low_level := lvl
else
if hide_expired_levels
line.delete(l)
swinglows.remove(i)
while swinghighs.size() > 100
line.delete(swinghighs.pop())
while swinglows.size() > 100
line.delete(swinglows.pop())
bars_since_high = ta.barssince(wicked_high)
bars_since_low = ta.barssince(wicked_low)
var potential_bull_cisd_level = 0.0
var potential_bear_cisd_level = 0.0
var o = 0.0
var c = 0.0
var bear_potential = array.new_float()
var bull_potential = array.new_float()
if close[1] < open[1] and close > open
bear_potential.unshift(bar_index)
bear_potential.unshift(open)
if close[1] > open[1] and close < open
bull_potential.unshift(bar_index)
bull_potential.unshift(open)
cisd = 0
origin_lvl = 0.0
origin_idx = 0.0
if bear_potential.size() > 0
inloop = true
while inloop
if close < bear_potential.first()
highest = 0.0
for i = 0 to bar_index-bear_potential.get(1)
if close
> highest
highest := close
running = true
init = bar_index-bear_potential.get(1)+1
top = 0.0
while running
if close[init] < open[init]
top := open[init]
init+=1
else
running:=false
if (highest-bear_potential.first())/(top-bear_potential.first()) > tolerence
origin_lvl := bear_potential.first()
origin_idx := bear_potential.get(1)
bear_potential.clear()
cisd := 1
inloop := false
else
bear_potential.shift()
bear_potential.shift()
if bear_potential.size() == 0
inloop := false
else
inloop := false
if bull_potential.size() > 0
inloop = true
while inloop
if close > bull_potential.first()
lowest = close
for i = 0 to bar_index-bull_potential.get(1)
if close < lowest
lowest := close
running = true
init = bar_index-bull_potential.get(1)+1
bottom = 0.0
while running
if close[init] > open[init]
bottom := open[init]
init+=1
else
running:=false
if (bull_potential.first() - lowest)/(bull_potential.first() - bottom) > tolerence
origin_lvl := bull_potential.first()
origin_idx := bull_potential.get(1)
bull_potential.clear()
cisd := 2
inloop := false
else
bull_potential.shift()
bull_potential.shift()
if bull_potential.size() == 0
inloop := false
else
inloop := false
var trend = 0
bearish_sweep = false
bullish_sweep = false
if cisd == 1
trend := -1
line.new(int(origin_idx),origin_lvl,bar_index,origin_lvl, color = red, width = 3)
if bars_since_high <= liquidity_lookback and close < last_wicked_high_level
bearish_sweep := true
if cisd == 2
trend := 1
line.new(int(origin_idx),origin_lvl,bar_index,origin_lvl, color = green, width = 3)
if bars_since_low <= liquidity_lookback and close > last_wicked_low_level
bullish_sweep := true
plotshape(bearish_sweep ? high : na, "Bearish CISD with Liquidity Sweep", shape.labeldown, location.abovebar, red, size = size.small, text = "▼", textcolor = chart.fg_color)
plotshape(bullish_sweep ? low : na, "Bullish CISD with Liquidity Sweep", shape.labelup, location.belowbar, green, size = size.small, text = "▲", textcolor = chart.fg_color)
plotchar(not na(pivhigh) ? high[len] : na, "Swing High", "●", location.absolute, red, size = size.tiny, offset = -len)
plotchar(not na(pivlow) ? low[len] : na, "Swing Low", "●", location.absolute, green, size = size.tiny, offset = -len)
candle_col = color.from_gradient(t1, 0, 100, trend > 0 ? green : red, chart.bg_color)
candle_col_ = color.from_gradient(t2, 0, 100, trend > 0 ? green : red, chart.bg_color)
plotcandle(open, high, low, close, "Price Candles", candle_col, candle_col_, bordercolor = candle_col_)
// Alerts
alertcondition(wicked_high, "Swing High Mitigation", "Swing High Mitigated")
alertcondition(wicked_low, "Swing Low Mitigation", "Swing Low Mitigated")
alertcondition(cisd == 1, "Bearish Normal CISD", "Bearish Normal CISD Detected")
alertcondition(cisd == 2, "Bullish Normal CISD", "Bullish Normal CISD Detected")
alertcondition(bearish_sweep, "Strong Bearish CISD", "Strong Bearish CISD Detected")
alertcondition(bullish_sweep, "Strong Bullish CISD", "Strong Bullish CISD Detected")