Indicator · Pine Script v5 · On the chart

ICT Turtle Soup | Flux Charts

by middlechild0· code credited to fluxchart

ICT Turtle Soup by Flux Charts is an overlay indicator that detects Smart Money Concepts (SMC) Turtle Soup liquidity sweeps and market structure shifts (MSS).

View on GitHub

GitHub stars2on the repository
Pine versionv5runs as is
Lines of code432
Settings26inputs
LicenceNone statedfile: MPL-2.0
Last update5 months ago13 May 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

432 lines of Pine Script v5 from mt5/indicators/pine/ict_ts.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

ict_ts.pine
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © fluxchart

//@version=5

const bool DEBUG = false
const int maxDistanceToLastBar = 4900 // Affects Running Time
const int atrLen = 5
const bool maxTPLastHour = false

var initRun = true

indicator("ICT Turtle Soup | Flux Charts", shorttitle = "Turtle Soup | Flux Charts", overlay = true, max_boxes_count = 500, max_labels_count = 500, max_lines_count = 500, max_bars_back = maxDistanceToLastBar + 100)

//pivotLenLiq = input.int(4, "Pivot Length", group = "General Configuration", display = display.none)
mssOffset = input.int(10, "MSS Swing Length", group = "General Configuration")
higherTimeframe = input.timeframe("60", "Higher Timeframe", group = "General Configuration")
breakoutMethod = input.string("Wick", "Breakout Method", options = ["Close", "Wick"], group = "General Configuration")
entryMethod = input.string("Classic", "Entry Method", options = ["Classic", "Adaptive"], group = "General Configuration", tooltip = "The entry method for the indicator to use. Try changing this setting if you are getting poor results.")
dbgTPSLVersion = input.string("Default", "TP / SL Layout", options = ["Default", "Alternative"], group = "General Configuration")
dbgLabelSize = DEBUG ? input.string("Small", "[DBG] Label Size", ["Normal", "Small", "Tiny"], group = "General Configuration") : "Normal"
lblSize = (dbgLabelSize == "Small" ? size.small : dbgLabelSize == "Normal" ? size.normal : size.tiny)

showHL = input.bool(false, "Show Liquidity Zones", inline = "3", group = "General Configuration")
showLiqGrabs = input.bool(true, "Liq Grabs", inline = "3", group = "General Configuration")
showTPSL = input.bool(true, "TP / SL", inline = "3", group = "General Configuration")

tpslMethod = input.string("Dynamic", "TP / SL Method", options = ["Dynamic", "Fixed"], group = "TP / SL")
riskAmount = input.string("Low", "Risk", options = ["Highest", "High", "Normal", "Low", "Lowest"], group = "TP / SL", tooltip = "The risk amount when Dynamic TP / SL method is selected.\n\nDifferent assets may have different volatility so changing this setting may result in change of performance of the indicator.")
customSLATRMult = DEBUG ? input.float(6.5, "Custom Risk Mult", group = "TP / SL") : 6.5
tpPercent = input.float(0.3, "Take Profit %", group = "TP / SL")
slPercent = input.float(0.4, "Stop Loss %", group = "TP / SL")

RR = DEBUG ? input.float(0.9, "Risk:Reward Ratio", group = "Debug") : 0.9

slATRMult = riskAmount == "Highest" ? 10 : riskAmount == "High" ? 6.5 : riskAmount == "Normal" ? 5.5 : riskAmount == "Low" ? 3.5 : riskAmount == "Lowest" ? 1.15 : customSLATRMult

backtestDisplayEnabled = input.bool(true, "Enabled", group = "Backtesting Dashboard", display = display.none)
backtestingLocation = input.string("Top Center", "Position", options = ["Top Right", "Right Center", "Top Center"], group = "Backtesting Dashboard", display = display.none)
fillBackgrounds = input.bool(true, "Fill Backgrounds", group = "Backtesting Dashboard", display = display.none)
screenerColor = input.color(#1B1F2B, 'Background', inline = "1", group = 'Backtesting Dashboard', display = display.none)

highColor = input.color(color.green, "Buy", inline = "colors", group = "Visuals")
lowColor = input.color(color.red, "Sell", inline = "colors", group = "Visuals")
textColor = input.color(color.white, "Text", inline = "colors", group = "Visuals")

buyAlertEnabled = input.bool(true, "Buy Signal", inline = "BS", group = "Alerts")
sellAlertEnabled = input.bool(true, "Sell Signal", inline = "BS", group = "Alerts")
tpAlertEnabled = input.bool(true, "Take-Profit Signal", inline = "TS", group = "Alerts")
slAlertEnabled = input.bool(true, "Stop-Loss Signal ", inline = "TS", group = "Alerts")

buyAlertTick = false
sellAlertTick = false
tpAlertTick = false
slAlertTick = false


type Sweep
    int startTime
    int endTime
    string side
    float price

type TurtleSoup
    string state
    int startTime

    int lastHour = na
    float lastHourHigh = na
    float lastHourLow = na
    Sweep brokenSweep = na
    float slTarget
    float tpTarget
    string entryType
    int entryTime
    int exitTime
    float entryPrice
    float exitPrice
    int dayEndedBeforeExit


var lineX = array.new<line>()
var boxX = array.new<box>()
var labelX = array.new<label>()

var TurtleSoup[] tsList = array.new<TurtleSoup>(0)
var TurtleSoup lastTS = na

atr = ta.atr(atrLen)

diffPercent (float val1, float val2) =>
    (math.abs(val1 - val2) / val2) * 100.0

getPosition (positionText) =>
    if positionText == "Top Right"
        position.top_right
    else if positionText == "Top Center"
        position.top_center
    else if positionText == "Right Center"
        position.middle_right
    else if positionText == "Left Center"
        position.middle_left
    else if positionText == "Bottom Center"
        position.bottom_center
    else if positionText == "Middle Center"
        position.middle_center

tfInMin = timeframe.in_seconds() / 60

//#region Liqs
if timeframe.in_seconds(higherTimeframe) <= timeframe.in_seconds()
    runtime.error("Higher timeframe must be higher than current timeframe.")
int htfMins = timeframe.in_seconds(higherTimeframe) / 60
int barLength = htfMins / tfInMin
float high12 = ta.highest(barLength)
float low12 = ta.lowest(barLength)
float highMSS = ta.highest(mssOffset)
float lowMSS = ta.lowest(mssOffset)
int lastHourTime = time[barLength]
//#endregion

//#region Turtle Soup
var highBreaks = 0
var lowBreaks = 0

if bar_index > last_bar_index - maxDistanceToLastBar
    if true
        // Find Session Start
        createNewTS = true
        if not na(lastTS)
            if na(lastTS.exitPrice)
                createNewTS := false // Don't enter if a trade is already entered
                
        if createNewTS
            newTS = TurtleSoup.new("Waiting For Liquidity Break", time)
            newTS.lastHourHigh := high12
            newTS.lastHourLow := low12
            newTS.lastHour := lastHourTime
            tsList.unshift(newTS)
            lastTS := newTS
            log.info("New Turtle Soup")

        if not na(lastTS)
            // Find Liquidity Breaks
            if lastTS.state == "Waiting For Liquidity Break"
                log.info("Wait For Liq Grab")
                if time > lastTS.startTime
                    if (breakoutMethod == "Close" ? close : low) < lastTS.lastHourLow
                        log.info("Sellside Liq Grab")
                        if entryMethod == "Classic" or highBreaks > lowBreaks
                            lastTS.brokenSweep := Sweep.new(lastTS.lastHour, time, "Sellside", lastTS.lastHourLow)
                            lastTS.entryType := "Long"
                        else if highBreaks <= lowBreaks
                            //lastTS.brokenSweep := Sweep.new(lastTS.lastHour, time, "Buyside", lastTS.lastHourHigh)
                            lastTS.brokenSweep := Sweep.new(lastTS.lastHour, time, "Sellside", lastTS.lastHourLow)
                            lastTS.entryType := "Short"

                        lastTS.state := "Waiting For Execution"
                    
                    else if (breakoutMethod == "Close" ? close : high) > lastTS.lastHourHigh
                        log.info("Buyside Liq Grab")
                        if entryMethod == "Classic" or highBreaks <= lowBreaks
                            lastTS.brokenSweep := Sweep.new(lastTS.lastHour, time, "Buyside", lastTS.lastHourHigh)
                            lastTS.entryType := "Short"
                        else if highBreaks > lowBreaks
                            //lastTS.brokenSweep := Sweep.new(lastTS.lastHour, time, "Sellside", lastTS.lastHourLow)
                            lastTS.brokenSweep := Sweep.new(lastTS.lastHour, time, "Buyside", lastTS.lastHourHigh)
                            lastTS.entryType := "Long"
                        lastTS.state := "Waiting For Execution"
            // Execute
            if lastTS.state == "Waiting For Execution"
                if time > lastTS.brokenSweep.endTime
                    log.info("MSS Execution")
                    if lastTS.entryType == "Short"
                        if (breakoutMethod == "Close" ? close : low) < lowMSS[1]
                            sellAlertTick := true
                            lastTS.state := "Entry Taken"
                            lastTS.entryTime := time
                            lastTS.entryPrice := (breakoutMethod == "Close" ? close : lowMSS[1])
                            if tpslMethod == "Fixed"
                                lastTS.slTarget := lastTS.entryPrice * (1 + slPercent / 100.0)
                                lastTS.tpTarget := lastTS.entryPrice * (1 - tpPercent / 100.0)
                            else
                                lastTS.slTarget := highMSS + atr * slATRMult
                                lastTS.tpTarget := lastTS.entryPrice - (math.abs(lastTS.entryPrice - lastTS.slTarget) * RR)
                    else // Long
                        if (breakoutMethod == "Close" ? close : high) > highMSS[1]
                            buyAlertTick := true
                            lastTS.state := "Entry Taken"
                            lastTS.entryTime := time
                            lastTS.entryPrice := (breakoutMethod == "Close" ? close : highMSS[1])
                            if tpslMethod == "Fixed"
                                lastTS.slTarget := lastTS.entryPrice * (1 - slPercent / 100.0)
                                lastTS.tpTarget := lastTS.entryPrice * (1 + tpPercent / 100.0)
                            else
                                lastTS.slTarget := lowMSS - atr * slATRMult
                                lastTS.tpTarget := lastTS.entryPrice + (math.abs(lastTS.entryPrice - lastTS.slTarget) * RR)
    
    // Entry Taken
    if not na(lastTS)
        if lastTS.state == "Entry Taken"
            log.info("Entry Taken")
            if tpslMethod == "Fixed"
                // Take Profit
                if lastTS.entryType == "Long" and ((high / lastTS.entryPrice) - 1) * 100 >= tpPercent
                    tpAlertTick := true
                    lastTS.exitPrice := lastTS.entryPrice * (1 + tpPercent / 100.0)
                    lastTS.exitTime := time
                    lastTS.state := "Take Profit"
                    highBreaks += 1
                if lastTS.entryType == "Short" and ((low / lastTS.entryPrice) - 1) * 100 <= -tpPercent
                    tpAlertTick := true
                    lastTS.exitPrice := lastTS.entryPrice * (1 - tpPercent / 100.0)
                    lastTS.exitTime := time
                    lastTS.state := "Take Profit"
                    lowBreaks += 1
                
                // Stop Loss
                if lastTS.entryType == "Long" and ((low / lastTS.entryPrice) - 1) * 100 <= -slPercent
                    slAlertTick := true
                    lastTS.exitPrice := lastTS.entryPrice * (1 - slPercent / 100.0)
                    lastTS.exitTime := time
                    lastTS.state := "Stop Loss"
                    highBreaks -= 1
                if lastTS.entryType == "Short" and ((high / lastTS.entryPrice) - 1) * 100 >= slPercent
                    slAlertTick := true
                    lastTS.exitPrice := lastTS.entryPrice * (1 + slPercent / 100.0)
                    lastTS.exitTime := time
                    lastTS.state := "Stop Loss"
                    lowBreaks -= 1
            else
                // Take Profit
                if lastTS.entryType == "Long" and ((maxTPLastHour and high >= lastTS.lastHourHigh) or high >= lastTS.tpTarget)
                    tpAlertTick := true
                    lastTS.exitPrice := (high >= math.max(lastTS.lastHourHigh, lastTS.tpTarget) ? math.max(lastTS.lastHourHigh, lastTS.tpTarget) : math.min(lastTS.lastHourHigh, lastTS.tpTarget))
                    lastTS.exitTime := time
                    lastTS.state := "Take Profit"
                    highBreaks += 1
                if lastTS.entryType == "Short" and ((maxTPLastHour and low <= lastTS.lastHourLow) or low <= lastTS.tpTarget)
                    tpAlertTick := true
                    lastTS.exitPrice := (low <= math.min(lastTS.lastHourLow, lastTS.tpTarget) ? math.min(lastTS.lastHourLow, lastTS.tpTarget) : math.max(lastTS.lastHourLow, lastTS.tpTarget))
                    lastTS.exitTime := time
                    lastTS.state := "Take Profit"
                    lowBreaks += 1
                
                // Stop Loss
                if lastTS.entryType == "Long" and low <= lastTS.slTarget
                    slAlertTick := true
                    lastTS.exitPrice := lastTS.slTarget
                    lastTS.exitTime := time
                    lastTS.state := "Stop Loss"
                    highBreaks -= 1
                if lastTS.entryType == "Short" and high >= lastTS.slTarget
                    slAlertTick := true
                    lastTS.exitPrice := lastTS.slTarget
                    lastTS.exitTime := time
                    lastTS.state := "Stop Loss"
                    lowBreaks -= 1
//#endregion

//#region Render Turtle Soups

renderTopSL = false
renderBottomSL = false
renderTopTP = false
renderBottomTP = false

if not na(lastTS)
    if lastTS.state == "Stop Loss" and time >= lastTS.exitTime
        if lastTS.entryType == "Long"
            renderBottomSL := true
        else
            renderTopSL := true
        lastTS.state := "Done"
    if lastTS.state == "Take Profit"
        if lastTS.entryType == "Long"
            renderTopTP := true
        else
            renderBottomTP := true
        lastTS.state := "Done"

plotshape(renderTopSL, "", shape.circle, location.abovebar, color.red, textcolor = textColor, text = "SL", size = size.tiny)
plotshape(renderBottomSL, "", shape.circle, location.belowbar, color.red, textcolor = textColor, text = "SL", size = size.tiny)
plotshape(renderTopTP, "", shape.xcross, location.abovebar, color.blue, textcolor = textColor, text = "TP", size = size.tiny)
plotshape(renderBottomTP, "", shape.xcross, location.belowbar, color.blue, textcolor = textColor, text = "TP", size = size.tiny)

//#endregion

//#region Alerts
if barstate.islastconfirmedhistory
    initRun := false

alertcondition(buyAlertTick and not initRun, "Buy Signal", "")
alertcondition(sellAlertTick and not initRun, "Sell Signal", "")
alertcondition(tpAlertTick and not initRun, "Take-Profit Signal", "")
alertcondition(slAlertTick and not initRun, "Stop-Loss Signal", "")

if not initRun
    if buyAlertTick and buyAlertEnabled
        alert("Buy Signal")
    if sellAlertTick and sellAlertEnabled
        alert("Sell Signal")
    
    if tpAlertTick and tpAlertEnabled
        alert("Take-Profit Signal")
    if slAlertTick and slAlertEnabled
        alert("Stop-Loss Signal")

//#endregion

if barstate.isconfirmed
    if lineX.size() > 0
        for i = 0 to lineX.size() - 1
            line.delete(lineX.get(i))

    if boxX.size() > 0
        for i = 0 to boxX.size() - 1
            box.delete(boxX.get(i))
    
    if labelX.size() > 0
        for i = 0 to labelX.size() - 1
            label.delete(labelX.get(i))

    lineX.clear()
    boxX.clear()
    labelX.clear()
    
    if tsList.size() > 0
        for i = 0 to math.min(125, tsList.size() - 1)
            curTS = tsList.get(i)

            // Target Liquidity
            if not na(curTS.brokenSweep) and showHL
                offset = atr / 3.0
                if curTS.brokenSweep.price == curTS.lastHourHigh
                    boxX.push(box.new(curTS.brokenSweep.startTime, curTS.lastHourHigh + offset, curTS.brokenSweep.endTime, curTS.lastHourHigh - offset, text = "TARGET LIQUIDITY (" + str.tostring(higherTimeframe) + ")", text_color = textColor, xloc = xloc.bar_time, border_width = 0, bgcolor = color.new(highColor, 50), text_size = size.small))
                    //lineX.push(line.new(curTS.brokenSweep.startTime, curTS.lastHourHigh, curTS.brokenSweep.endTime, curTS.lastHourHigh, xloc = xloc.bar_time, color = lowColor, style = line.style_dashed))
                else
                    boxX.push(box.new(curTS.brokenSweep.startTime, curTS.lastHourLow + offset, curTS.brokenSweep.endTime, curTS.lastHourLow - offset, text = "TARGET LIQUIDITY (" + str.tostring(higherTimeframe) + ")", text_color = textColor, xloc = xloc.bar_time, border_width = 0, bgcolor = color.new(lowColor, 50), text_size = size.small))
                    //lineX.push(line.new(curTS.brokenSweep.startTime, curTS.lastHourLow, curTS.brokenSweep.endTime, curTS.lastHourLow, xloc = xloc.bar_time, color = highColor, style = line.style_dashed))

            // Liq Grab
            if not na(curTS.brokenSweep) and showLiqGrabs
                if curTS.brokenSweep.price == curTS.lastHourHigh
                    labelX.push(label.new(curTS.brokenSweep.endTime, high, yloc = yloc.abovebar, xloc = xloc.bar_time, style = label.style_circle, size = size.tiny, color = color.new(lowColor, 50)))
                else
                    labelX.push(label.new(curTS.brokenSweep.endTime, low, yloc = yloc.belowbar, xloc = xloc.bar_time, style = label.style_circle, size = size.tiny, color = color.new(highColor, 50)))

            if not na(curTS.entryTime)
                // Entry Label
                if curTS.entryType == "Long"
                    labelX.push(label.new(curTS.entryTime, close, "Buy", xloc = xloc.bar_time, yloc = yloc.belowbar, textcolor = textColor, color = highColor, style = label.style_label_up, size = lblSize))
                else
                    labelX.push(label.new(curTS.entryTime, close, "Sell", xloc = xloc.bar_time, yloc = yloc.abovebar, textcolor = textColor, color = lowColor, style = label.style_label_down, size = lblSize))
            
            // TP / SL
            if not na(curTS.entryTime)
                if showTPSL
                    if dbgTPSLVersion == "Alternative"
                        offset = atr / 3.0
                        endTime = nz(curTS.exitTime, time("", -15))
                        boxX.push(box.new(curTS.entryTime, curTS.tpTarget + offset, endTime, curTS.tpTarget - offset, text = "TAKE PROFIT (" + str.tostring(curTS.tpTarget, format.mintick) + ")", text_color = textColor, xloc = xloc.bar_time, border_width = 0, bgcolor = color.new(highColor, 50), text_size = size.small))
                        boxX.push(box.new(curTS.entryTime, curTS.slTarget + offset, endTime, curTS.slTarget - offset, text = "STOP LOSS (" + str.tostring(curTS.slTarget, format.mintick) + ")", text_color = textColor, xloc = xloc.bar_time, border_width = 0, bgcolor = color.new(lowColor, 50) , text_size = size.small))
                    else if dbgTPSLVersion == "Default"
                        endTime = nz(curTS.exitTime, time("", -15))
                        lineX.push(line.new(curTS.entryTime, curTS.entryPrice, curTS.entryTime, curTS.tpTarget, xloc = xloc.bar_time, color = highColor, style = line.style_dashed))
                        lineX.push(line.new(curTS.entryTime, curTS.tpTarget, endTime, curTS.tpTarget, xloc = xloc.bar_time, color = highColor, style = line.style_dashed))
                        labelX.push(label.new(endTime, curTS.tpTarget, "TP", xloc = xloc.bar_time, yloc = yloc.price, textcolor = textColor, color = color.new(highColor, 50), style = label.style_label_left, size = lblSize))
                        //
                        lineX.push(line.new(curTS.entryTime, curTS.entryPrice, curTS.entryTime, curTS.slTarget, xloc = xloc.bar_time, color = lowColor, style = line.style_dashed))
                        lineX.push(line.new(curTS.entryTime, curTS.slTarget, endTime, curTS.slTarget, xloc = xloc.bar_time, color = lowColor, style = line.style_dashed))
                        labelX.push(label.new(endTime, curTS.slTarget, "SL", xloc = xloc.bar_time, yloc = yloc.price, textcolor = textColor, color = color.new(lowColor, 50), style = label.style_label_left, size = lblSize))

            if not na(curTS.dayEndedBeforeExit)
                labelX.push(label.new(curTS.dayEndedBeforeExit, close, "Exit", xloc = xloc.bar_time, yloc = yloc.belowbar, textcolor = textColor, color = color.yellow, style = label.style_circle, size = size.tiny))

//#region Backtesting Dashboard

if barstate.islast and backtestDisplayEnabled
    var table backtestDisplay = table.new(getPosition(backtestingLocation), 2, 10, bgcolor = screenerColor, frame_width = 2, frame_color = color.black, border_width = 1, border_color = color.black)
    
    float totalTSProfitPercent = 0
    int successfulTrades = 0
    int unsuccessfulTrades = 0

    if tsList.size() > 0
        for i = 0 to tsList.size() - 1
            curTS = tsList.get(i)
            if not na(curTS.entryPrice)
                isSuccess = false
                if not na(curTS.exitPrice)
                    if (curTS.entryType == "Long" and curTS.exitPrice > curTS.entryPrice) or (curTS.entryType == "Short" and curTS.exitPrice < curTS.entryPrice)
                        totalTSProfitPercent += math.abs(diffPercent(curTS.entryPrice, curTS.exitPrice))
                        isSuccess := true
                    else
                        totalTSProfitPercent -= math.abs(diffPercent(curTS.entryPrice, curTS.exitPrice))
                        isSuccess := false

                if isSuccess
                    successfulTrades += 1
                else
                    unsuccessfulTrades += 1
    
    // Header
    table.merge_cells(backtestDisplay, 0, 0, 1, 0)
    table.cell(backtestDisplay, 0, 0, "TS Backtesting", text_color = color.white, bgcolor = screenerColor)

    // Total ORBs
    table.cell(backtestDisplay, 0, 1, "Total Entries", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 1, str.tostring(successfulTrades + unsuccessfulTrades), text_color = color.white, bgcolor = screenerColor)

    // Wins
    table.cell(backtestDisplay, 0, 2, "Wins", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 2, str.tostring(successfulTrades), text_color = color.white, bgcolor = screenerColor)

    // Losses
    table.cell(backtestDisplay, 0, 3, "Losses", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 3, str.tostring(unsuccessfulTrades), text_color = color.white, bgcolor = screenerColor)

    // Winrate
    table.cell(backtestDisplay, 0, 4, "Winrate", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 4, str.tostring(100.0 * (successfulTrades / (successfulTrades + unsuccessfulTrades)), "#.##") + "%", text_color = color.white, bgcolor = screenerColor)

    // Average Profit %
    table.cell(backtestDisplay, 0, 5, "Average Profit", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 5, str.tostring(totalTSProfitPercent / (successfulTrades + unsuccessfulTrades), "#.##") + "%", text_color = color.white, bgcolor = screenerColor)

    // Total Profit %
    table.cell(backtestDisplay, 0, 6, "Total Profit", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 6, str.tostring(totalTSProfitPercent, "#.##") + "%", text_color = color.white, bgcolor = screenerColor)

//#endregion

Overview

ICT Turtle Soup | Flux Charts identifies liquidity grabs across standard or higher timeframe periods and projects take-profit and stop-loss levels using dynamic ATR multipliers or fixed percentage thresholds. Users can configure swing length, breakout methods, entry styles, and visual liquidity zones, alongside an optional backtesting status dashboard and customizable alert triggers directly on the main chart.

Details

Published by

middlechild0 on GitHub

Code credit

fluxchart, as written in the script's header

Type

Indicator, Pine Script v5

Draws

On the price chart

Category

SMC / ICT / price action, Support & resistance

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.

Settings

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

SettingTypeDefaultVariable
MSS Swing Lengthint10mssOffset
Higher Timeframetimeframe60higherTimeframe
Breakout MethodstringWickbreakoutMethod
Entry MethodstringClassicentryMethod
TP / SL LayoutstringDefaultdbgTPSLVersion
[DBG] Label SizestringSmall[DBG] Label Size
Show Liquidity ZonesboolfalseshowHL
Liq GrabsbooltrueshowLiqGrabs
TP / SLbooltrueshowTPSL
TP / SL MethodstringDynamictpslMethod
RiskstringLowriskAmount
Custom Risk Multfloat6.5Custom Risk Mult
Show all 26 settings
SettingTypeDefaultVariable
Take Profit %float0.3tpPercent
Stop Loss %float0.4slPercent
Risk:Reward Ratiofloat0.9Risk:Reward Ratio
EnabledbooltruebacktestDisplayEnabled
PositionstringTop CenterbacktestingLocation
Fill BackgroundsbooltruefillBackgrounds
Backgroundcolor#1B1F2BscreenerColor
Buycolorcolor.greenhighColor
Sellcolorcolor.redlowColor
Textcolorcolor.whitetextColor
Buy SignalbooltruebuyAlertEnabled
Sell SignalbooltruesellAlertEnabled
Take-Profit SignalbooltruetpAlertEnabled
Stop-Loss Signal booltrueslAlertEnabled
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

ICT Equal Highs and Lows

by ArunKBhaskar
575 stars

This overlay indicator finds pivot highs and lows on the price chart and compares the last two highs and the last two lows. When the percentage difference between a pair is below the Equal HL threshold, it treats them as equal levels and draws a box. Left and

Indicator v5 SMC / ICT / price actionSupport & resistance
Updated 1 year ago · MPL-2.0 GitHub repository of ICT Equal Highs and Lows

DE-tracker

by Allen1212
303 stars

This indicator plots labels on the TradingView price chart to mark ARK Invest's buy and sell trades for the DE stock. Buy transactions appear in green with X1 or X2 multipliers showing the number of ARK ETFs involved on the same day; sells appear in red. The m

Indicator v4 Support & resistanceSMC / ICT / price action
Updated 2 years ago · None stated GitHub repository of DE-tracker

This Pine Script indicator plots a ZigZag on the price chart. It identifies reversal points when price moves more than a set percentage from the last pivot. The script calculates forecasts using zigzag data and labels detected geometric patterns including harm

Indicator v4 TrendSupport & resistance

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

Open Source Fractal

by cantolab
183 stars

This indicator implements the Fractal Model concept to plot market structure shifts, liquidity sweeps, and Change in State of Delivery (CISD) levels. It overlays custom higher-timeframe candle previews, open prices, and time markers directly on the price chart

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 2 months ago · MIT GitHub repository of Open Source Fractal

Swing Failure Signals

by Ganador1
154 stars

This indicator calculates pivot highs and pivot lows to detect liquidity sweeps and Swing Failure Patterns. It identifies when price breaks past recent key swing highs or lows within a configurable historical window, then looks for a quick reversal or change i

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 2 months ago · Apache-2.0 GitHub repository of Swing Failure Signals

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