//@version=6
indicator('Liquidity Lines & Sweeps + FVG [Lucien]', overlay = true, max_lines_count = 500)

// === LIQUIDITY SETTINGS ===
liquidityBool = input.bool(true, 'Show Liquidity Sweeps', group = 'Liquidity Settings')
liquidity_len = input.int(30, 'Liquidity Length', minval = 5, group = 'Liquidity Settings')
upColor = input.color(color.new(color.teal, 15), title = 'Bullish Liquidity Color', group = 'Liquidity Settings')
downColor = input.color(color.new(color.red, 15), title = 'Bearish Liquidity Color', group = 'Liquidity Settings')

// === EMA SETTINGS ===
showEma = input.bool(true, title="Show EMA", group="Moving Average")
emaLength = input.int(50, title="EMA Length", minval=1, group="Moving Average") // Changed EMA1 default to 50
emaSource = input.source(close, title="EMA Source", group="Moving Average")
emaTimeframe = input.timeframe("", title="EMA Timeframe (leave empty for current)", group="Moving Average")
emaColor = input.color(color.new(color.orange, 0), title="EMA Color", group="Moving Average")
emaWidth = input.int(2, title="EMA Line Width", minval=1, maxval=5, group="Moving Average")

// === EMA 2 SETTINGS ===
showEma2 = input.bool(true, title="Show EMA 2", group="Moving Average") // Enabled by default
ema2Length = input.int(100, title="EMA 2 Length", minval=1, group="Moving Average")
ema2Source = input.source(close, title="EMA 2 Source", group="Moving Average")
ema2Timeframe = input.timeframe("", title="EMA 2 Timeframe (leave empty for current)", group="Moving Average")
ema2Color = input.color(color.new(color.blue, 0), title="EMA 2 Color", group="Moving Average")
ema2Width = input.int(2, title="EMA 2 Line Width", minval=1, maxval=5, group="Moving Average")

// === EMA 3 SETTINGS ===
showEma3 = input.bool(true, title="Show EMA 3", group="Moving Average") // Enabled by default
ema3Length = input.int(200, title="EMA 3 Length", minval=1, group="Moving Average")
ema3Source = input.source(close, title="EMA 3 Source", group="Moving Average")
ema3Timeframe = input.timeframe("", title="EMA 3 Timeframe (leave empty for current)", group="Moving Average")
ema3Color = input.color(color.new(color.purple, 0), title="EMA 3 Color", group="Moving Average")
ema3Width = input.int(2, title="EMA 3 Line Width", minval=1, maxval=5, group="Moving Average")

// Calculate EMA 1 with timeframe option
emaValue = request.security(syminfo.tickerid, emaTimeframe != "" ? emaTimeframe : timeframe.period, ta.ema(emaSource, emaLength))
plot(showEma ? emaValue : na, title="EMA", color=emaColor, linewidth=emaWidth)

// Calculate EMA 2 with timeframe option
emaValue2 = request.security(syminfo.tickerid, ema2Timeframe != "" ? ema2Timeframe : timeframe.period, ta.ema(ema2Source, ema2Length))
plot(showEma2 ? emaValue2 : na, title="EMA 2", color=ema2Color, linewidth=ema2Width)

// Calculate EMA 3 with timeframe option
emaValue3 = request.security(syminfo.tickerid, ema3Timeframe != "" ? ema3Timeframe : timeframe.period, ta.ema(ema3Source, ema3Length))
plot(showEma3 ? emaValue3 : na, title="EMA 3", color=ema3Color, linewidth=ema3Width)

// --- True range for label positioning ---
tr = ta.tr(true)

// --- Bias Detection and Label ---
var label biasLabel = na

bullishBias = (emaValue > emaValue2) and (emaValue2 > emaValue3)
bearishBias = (emaValue < emaValue2) and (emaValue2 < emaValue3)

if not na(biasLabel)
label.delete(biasLabel)

if bullishBias
biasLabel := label.new(bar_index, low - tr1.5, "Only Buy", xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_up, color=color.new(color.teal, 0), textcolor=color.white, size=size.large)
else if bearishBias
biasLabel := label.new(bar_index, high + tr1.5, "Only Sell", xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_down, color=color.new(color.red, 0), textcolor=color.white, size=size.large)
else
// No label if no clear bias, do nothing
na

// === FVG SETTINGS ===
isFvgToShow = input(true, title='Display FVG', group="Fair Value Gap")
bullishFvgColor = input.color(color.new(color.green, 50), 'Bullish FVG Color', group="Fair Value Gap")
bearishFvgColor = input.color(color.new(color.red, 50), 'Bearish FVG Color', group="Fair Value Gap")
mitigatedFvgColor = input.color(color.new(color.gray, 50), 'Mitigated FVG Color', group="Fair Value Gap")
fvgHistoryNbr = input.int(5, 'Number of FVG to show', minval=1, maxval=50, group="Fair Value Gap")
isMitigatedFvgToReduce = input(false, title='Reduce mitigated FVG', group="Fair Value Gap")

// === DATA STRUCTURES ===
// For Liquidity
type liquidity
float value
int barStart
int barEnd
line liquidityLine
bool broken
label sweep

var array

// For FVG
var array

// === FVG FUNCTIONS ===
FVGDraw(_boxes, _fvgTypes, _isFvgMitigated, _fvgLabels) =>
for [index, value] in _boxes
// Processing bullish FVG
if array.get(_fvgTypes, index)
if low <= box.get_bottom(value)
array.remove(_boxes, index)
array.remove(_fvgTypes, index)
array.remove(_isFvgMitigated, index)
label.delete(array.get(_fvgLabels, index))
array.remove(_fvgLabels, index)
box.delete(value)
else
if low < box.get_top(value)
box.set_bgcolor(value, mitigatedFvgColor)
if not array.get(_isFvgMitigated, index)
alert("FVG has been mitigated", alert.freq_once_per_bar)
array.set(_isFvgMitigated, index, true)
if isMitigatedFvgToReduce
box.set_top(value, low)
box.set_right(value, bar_index)
label.set_x(array.get(_fvgLabels, index), (box.get_left(value) + box.get_right(value)) / 2 )
label.set_y(array.get(_fvgLabels, index), box.get_top(value) - (box.get_top(value) - box.get_bottom(value)) / 2)
// Processing bearish FVG
else
if high >= box.get_top(value)
array.remove(_boxes, index)
array.remove(_fvgTypes, index)
array.remove(_isFvgMitigated, index)
label.delete(array.get(_fvgLabels, index))
array.remove(_fvgLabels, index)
box.delete(value)
else
if high > box.get_bottom(value)
box.set_bgcolor(value, mitigatedFvgColor)
if not array.get(_isFvgMitigated, index)
alert("FVG has been mitigated", alert.freq_once_per_bar)
array.set(_isFvgMitigated, index, true)
if isMitigatedFvgToReduce
box.set_bottom(value, high)
box.set_right(value, bar_index)
label.set_x(array.get(_fvgLabels, index), (box.get_left(value) + box.get_right(value)) / 2 )
label.set_y(array.get(_fvgLabels, index), box.get_top(value) - (box.get_top(value) - box.get_bottom(value)) / 2)

// === LIQUIDITY DETECTION ===
phLiquidity = ta.pivothigh(high, liquidity_len, liquidity_len)
plLiquidity = ta.pivotlow(low, liquidity_len, liquidity_len)

if not na(phLiquidity) and liquidityBool
liquidity newLiquidity = liquidity.new()
newLiquidity.value := high[liquidity_len]
newLiquidity.barStart := time[liquidity_len]
newLiquidity.barEnd := time
newLiquidity.broken := false
newLiquidity.liquidityLine := line.new(x1 = newLiquidity.barStart, y1 = newLiquidity.value, x2 = newLiquidity.barEnd, y2 = newLiquidity.value, xloc = xloc.bar_time, color = downColor, width = 1)
array.push(bearishLiquidity, newLiquidity)
if array.size(bearishLiquidity) > 7
deletedLiquidity = array.shift(bearishLiquidity)
deletedLiquidity.liquidityLine.delete()

if not na(plLiquidity) and liquidityBool
liquidity newLiquidity = liquidity.new()
newLiquidity.value := low[liquidity_len]
newLiquidity.barStart := time[liquidity_len]
newLiquidity.barEnd := time
newLiquidity.broken := false
newLiquidity.liquidityLine := line.new(x1 = newLiquidity.barStart, y1 = newLiquidity.value, x2 = newLiquidity.barEnd, y2 = newLiquidity.value, xloc = xloc.bar_time, color = upColor, width = 1)
array.push(bullishLiquidity, newLiquidity)
if array.size(bullishLiquidity) > 7
deletedLiquidity = array.shift(bullishLiquidity)
deletedLiquidity.liquidityLine.delete()

// === FVG DETECTION ===
isBullishFVG = high[3] < low[1]
isBearishFVG = low[3] > high[1]

if isBullishFVG and isFvgToShow
box _box = box.new(left=bar_index - 2, top=low[1], right=bar_index - 1, bottom=high[3], border_style=line.style_solid, border_width=1, bgcolor=bullishFvgColor, border_color=color.new(color.green, 100))
label _label = label.new(math.ceil((_box.get_left() + _box.get_right()) / 2), _box.get_top() - (_box.get_top() - _box.get_bottom()) / 2, text = "FVG", style = label.style_none, textcolor = color.white)
array.push(fvgBoxes, _box)
array.push(fvgTypes, true)
array.push(isFvgMitigated, false)
array.push(fvgLabels, _label)


if array.size(fvgBoxes) > fvgHistoryNbr + 1
    box.delete(array.get(fvgBoxes, 0))
    label.delete(array.get(fvgLabels, 0))
    array.remove(fvgLabels, 0)
    array.remove(fvgBoxes, 0)
    array.remove(fvgTypes, 0)
    array.remove(isFvgMitigated, 0)
if isBearishFVG and isFvgToShow
box _box = box.new(left=bar_index - 2, top=low[3], right=bar_index - 1, bottom=high[1], border_style=line.style_solid, border_width=1, bgcolor=bearishFvgColor, border_color=color.new(color.red, 100))
label _label = label.new(math.ceil((_box.get_left() + _box.get_right()) / 2), _box.get_top() - (_box.get_top() - _box.get_bottom()) / 2, text = "FVG", style = label.style_none, textcolor = color.white)
array.push(fvgBoxes, _box)
array.push(fvgTypes, false)
array.push(isFvgMitigated, false)
array.push(fvgLabels, _label)


if array.size(fvgBoxes) > fvgHistoryNbr + 1
    box.delete(array.get(fvgBoxes, 0))
    label.delete(array.get(fvgLabels, 0))
    array.remove(fvgLabels, 0)
    array.remove(fvgBoxes, 0)
    array.remove(fvgTypes, 0)
    array.remove(isFvgMitigated, 0)
// === UPDATE VISUALS ===
// Update Liquidity Lines and Sweeps
var bool sweepAlert = false

if array.size(bearishLiquidity) > 0
liquidity testLiquidity = na
for i = array.size(bearishLiquidity) - 1 to 0 by 1
testLiquidity := array.get(bearishLiquidity, i)
if high > testLiquidity.value
testLiquidity.liquidityLine.set_x2(time)
testLiquidity.liquidityLine.set_style(line.style_dashed)
array.remove(bearishLiquidity, i)
if close < testLiquidity.value
testLiquidity.sweep := label.new(x = time, y = high, text = 'x', xloc = xloc.bar_time, style = label.style_label_down, size = size.normal, textcolor = color.new(color.purple, 0), color = color.new(color.white, 100))
sweepAlert := true
else
testLiquidity.liquidityLine.set_x2(time)

if array.size(bullishLiquidity) > 0
liquidity testLiquidity = na
for i = array.size(bullishLiquidity) - 1 to 0 by 1
testLiquidity := array.get(bullishLiquidity, i)
if low < testLiquidity.value
testLiquidity.liquidityLine.set_x2(time)
testLiquidity.liquidityLine.set_style(line.style_dashed)
array.remove(bullishLiquidity, i)
if close > testLiquidity.value
testLiquidity.sweep := label.new(x = time, y = low, text = 'x', xloc = xloc.bar_time, style = label.style_label_up, size = size.normal, textcolor = color.new(color.teal, 0), color = color.new(color.white, 100))
sweepAlert := true
else
testLiquidity.liquidityLine.set_x2(time)

// Update FVGs
FVGDraw(fvgBoxes, fvgTypes, isFvgMitigated, fvgLabels)

// === ALERTS ===
alertcondition(sweepAlert, title = "Liquidity Sweep", message = "A liquidity zone has been swept.")
sweepAlert := false

// === PREVIOUS DAY HIGH/LOW SETTINGS ===
showPrevDayRange = input.bool(true, 'Show Previous Day High/Low', group='Previous Day Range')
prevDayColorHigh = input.color(color.new(color.blue, 0), 'Previous Day High Color', group='Previous Day Range')
prevDayColorLow = input.color(color.new(color.orange, 0), 'Previous Day Low Color', group='Previous Day Range')
prevDayLineWidth = input.int(2, 'Previous Day Line Width', minval=1, maxval=5, group='Previous Day Range')
prevDayLineStyle = input.string('Dashed', 'Previous Day Line Style', options=['Dashed', 'Dotted'], group='Previous Day Range')

// Convert line style string to line.style constant
lineStyle = prevDayLineStyle == 'Dotted' ? line.style_dotted : line.style_dashed

// Get previous day timeframe string or use 'D'
dailyTF = "D" // fixed daily timeframe

// Request previous daily data (high/low) and previous day start timestamp (session start)
prevDayHigh = request.security(syminfo.tickerid, dailyTF, high[1], lookahead=barmerge.lookahead_on)
prevDayLow = request.security(syminfo.tickerid, dailyTF, low[1], lookahead=barmerge.lookahead_on)
prevDayTime = request.security(syminfo.tickerid, dailyTF, time[1], lookahead=barmerge.lookahead_on) // Timestamp of previous daily bar start

// Variables to hold lines just once (persistent)
var line prevHighLine = na
var line prevLowLine = na

// Calculate approximate timeframe minutes and future time offset
tf_minutes = timeframe.multiplier * (timeframe.isintraday ? 1 : 1440)
futureBarsCount = 500
futureDeltaMs = tf_minutes * 60000 * futureBarsCount
lineEndTime = time + futureDeltaMs

if showPrevDayRange
if na(prevHighLine)
prevHighLine := line.new(x1=prevDayTime, y1=prevDayHigh, x2=lineEndTime, y2=prevDayHigh, xloc=xloc.bar_time, color=prevDayColorHigh, width=prevDayLineWidth, style=lineStyle)
else
line.set_xy1(prevHighLine, prevDayTime, prevDayHigh)
line.set_xy2(prevHighLine, lineEndTime, prevDayHigh)


if na(prevLowLine)
    prevLowLine := line.new(x1=prevDayTime, y1=prevDayLow, x2=lineEndTime, y2=prevDayLow, xloc=xloc.bar_time, color=prevDayColorLow, width=prevDayLineWidth, style=lineStyle)
else
    line.set_xy1(prevLowLine, prevDayTime, prevDayLow)
    line.set_xy2(prevLowLine, lineEndTime, prevDayLow)
else
if not na(prevHighLine)
line.delete(prevHighLine)
prevHighLine := na
if not na(prevLowLine)
line.delete(prevLowLine)
prevLowLine := na


in this script i don't want to see "FVG" text on chart, and bias label over/under a liquidity line