Indicator · Pine Script v6 · On the chart

Orderflow Break Tape

by Blendoxius

An overlay that tracks swing highs and lows and marks change of character, break of structure and liquidity events with lines and labels.

View on GitHub

GitHub stars1on the repository
Pine versionv6current
Lines of code1,168
Settings40inputs
LicenceNone statedfile: MPL-2.0
Last update10 months ago9 Dec 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

1,168 lines of Pine Script v6 from Pine Script OrderFlowTapeV23.txt, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

Pine Script OrderFlowTapeV23.txt
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Blendoxius

//@version=6
indicator("ORDERFLOW BREAK TAPE v24", overlay=true, max_lines_count=500, max_labels_count=500)

// ════════════════════════════════════════════════════════════════════════════════
// SECTION 1: MAIN SETTINGS
// ════════════════════════════════════════════════════════════════════════════════

swingLookback = input. int(5, "Swing Lookback", minval=1, maxval=50, group="1. Main Settings")
maxSwings = input.int(50, "Max Swings", minval=10, maxval=500, group="1. Main Settings")
avgLookback = input.int(100, "Average Lookback", minval=1, maxval=5000, group="1. Main Settings")

enableChoch = input.bool(true, "Enable CHoCH", group="1. Main Settings")
enableBos = input.bool(true, "Enable BOS", group="1. Main Settings")
enableLiq = input.bool(true, "Enable LIQ", group="1. Main Settings")

// ════════════════════════════════════════════════════════════════════════════════
// SECTION 2: VOLUME STRENGTH FILTER
// ════════════════════════════════════════════════════════════════════════════════

enableVolumeFilter = input.bool(true, "Enable Volume Filter", group="2.  Volume Filter")
volumeCompareMode = input.string("Custom Bars", "Compare Mode", options=["Custom Bars", "Tape Average"], group="2. Volume Filter")
volumeCompareBars = input.int(3, "Compare to Last X Bars", minval=1, maxval=50, group="2. Volume Filter")
volumeStrengthThreshold = input.float(1.0, "Strength Threshold", minval=0.5, maxval=5.0, step=0.1, group="2. Volume Filter")
applyFilterToChoch = input.bool(true, "Apply to CHoCH", group="2. Volume Filter")
applyFilterToBos = input.bool(true, "Apply to BOS", group="2. Volume Filter")
showWeakChoch = input.bool(true, "Show Weak CHoCH", group="2. Volume Filter")
showWeakBos = input.bool(true, "Show Weak BOS", group="2. Volume Filter")

// ════════════════════════════════════════════════════════════════════════════════
// SECTION 3-10: SWING LINE SETTINGS (unchanged)
// ════════════════════════════════════════════════════════════════════════════════

swingHighActiveColor = input.color(color.rgb(244,67,54), "Active Color", group="3. Swing High Active", inline="sha")
swingHighActiveWidth = input.int(1, "Width", minval=1, maxval=10, group="3.  Swing High Active", inline="sha")
swingHighActiveStyle = input.string("solid", "Style", options=["solid", "dashed", "dotted"], group="3. Swing High Active", inline="sha")

swingHighBrokenStrongColor = input.color(color. rgb(0,255,0), "Strong Color", group="4. Swing High Broken Strong", inline="shbs")
swingHighBrokenStrongWidth = input.int(2, "Width", minval=1, maxval=10, group="4. Swing High Broken Strong", inline="shbs")
swingHighBrokenStrongStyle = input.string("solid", "Style", options=["solid", "dashed", "dotted"], group="4. Swing High Broken Strong", inline="shbs")

swingHighBrokenWeakColor = input.color(color. rgb(100,100,100), "Weak Color", group="5. Swing High Broken Weak", inline="shbw")
swingHighBrokenWeakWidth = input.int(1, "Width", minval=1, maxval=10, group="5. Swing High Broken Weak", inline="shbw")
swingHighBrokenWeakStyle = input.string("dotted", "Style", options=["solid", "dashed", "dotted"], group="5. Swing High Broken Weak", inline="shbw")

swingHighTouchedColor = input.color(color.rgb(255,193,7), "Touched Color", group="6. Swing High Touched", inline="sht")
swingHighTouchedWidth = input.int(1, "Width", minval=1, maxval=10, group="6. Swing High Touched", inline="sht")
swingHighTouchedStyle = input. string("dashed", "Style", options=["solid", "dashed", "dotted"], group="6. Swing High Touched", inline="sht")

swingLowActiveColor = input.color(color.rgb(76,175,80), "Active Color", group="7. Swing Low Active", inline="sla")
swingLowActiveWidth = input.int(1, "Width", minval=1, maxval=10, group="7. Swing Low Active", inline="sla")
swingLowActiveStyle = input.string("solid", "Style", options=["solid", "dashed", "dotted"], group="7. Swing Low Active", inline="sla")

swingLowBrokenStrongColor = input.color(color.rgb(255,0,0), "Strong Color", group="8. Swing Low Broken Strong", inline="slbs")
swingLowBrokenStrongWidth = input. int(2, "Width", minval=1, maxval=10, group="8. Swing Low Broken Strong", inline="slbs")
swingLowBrokenStrongStyle = input.string("solid", "Style", options=["solid", "dashed", "dotted"], group="8.  Swing Low Broken Strong", inline="slbs")

swingLowBrokenWeakColor = input.color(color.rgb(100,100,100), "Weak Color", group="9. Swing Low Broken Weak", inline="slbw")
swingLowBrokenWeakWidth = input. int(1, "Width", minval=1, maxval=10, group="9. Swing Low Broken Weak", inline="slbw")
swingLowBrokenWeakStyle = input.string("dotted", "Style", options=["solid", "dashed", "dotted"], group="9. Swing Low Broken Weak", inline="slbw")

swingLowTouchedColor = input.color(color. rgb(255,193,7), "Touched Color", group="10. Swing Low Touched", inline="slt")
swingLowTouchedWidth = input.int(1, "Width", minval=1, maxval=10, group="10.  Swing Low Touched", inline="slt")
swingLowTouchedStyle = input.string("dashed", "Style", options=["solid", "dashed", "dotted"], group="10.  Swing Low Touched", inline="slt")

// ════════════════════════════════════════════════════════════════════════════════
// SECTION 11-13: LABEL SETTINGS (unchanged)
// ════════════════════════════════════════════════════════════════════════════════

showChochLabels = input.bool(true, "Show CHoCH Labels", group="11. CHoCH Labels")
chochUpStrongColor = input.color(color.rgb(0,255,255), "Up Strong", group="11. CHoCH Labels", inline="chu")
chochUpWeakColor = input.color(color.rgb(0,120,120), "Up Weak", group="11. CHoCH Labels", inline="chu")
chochDownStrongColor = input.color(color.rgb(255,165,0), "Down Strong", group="11. CHoCH Labels", inline="chd")
chochDownWeakColor = input.color(color.rgb(150,100,0), "Down Weak", group="11. CHoCH Labels", inline="chd")
chochLabelSizeStr = input.string("small", "Label Size", options=["tiny", "small", "normal", "large"], group="11.  CHoCH Labels")
chochLabelPosition = input.string("Break Point", "Label Position", options=["Break Point", "Center of Line"], group="11. CHoCH Labels")

showBosLabels = input.bool(true, "Show BOS Labels", group="12. BOS Labels")
bosUpStrongColor = input.color(color.rgb(0,255,0), "Up Strong", group="12. BOS Labels", inline="bosu")
bosUpWeakColor = input.color(color.rgb(0,120,0), "Up Weak", group="12.  BOS Labels", inline="bosu")
bosDownStrongColor = input.color(color.rgb(255,0,0), "Down Strong", group="12. BOS Labels", inline="bosd")
bosDownWeakColor = input.color(color.rgb(120,0,0), "Down Weak", group="12. BOS Labels", inline="bosd")
bosLabelSizeStr = input.string("tiny", "Label Size", options=["tiny", "small", "normal", "large"], group="12. BOS Labels")
bosLabelPosition = input.string("Break Point", "Label Position", options=["Break Point", "Center of Line"], group="12. BOS Labels")

showLiqLabels = input. bool(true, "Show LIQ Labels", group="13. LIQ Labels")
liqUpColor = input.color(color.rgb(255,235,59), "Up Color", group="13. LIQ Labels", inline="liq")
liqDownColor = input.color(color.rgb(255,235,59), "Down Color", group="13. LIQ Labels", inline="liq")
liqLabelSizeStr = input.string("tiny", "Label Size", options=["tiny", "small", "normal", "large"], group="13. LIQ Labels")

// ════════════════════════════════════════════════════════════════════════════════
// SECTION 14: TABLE AND SCROLL SETTINGS
// ════════════════════════════════════════════════════════════════════════════════

showTable = input.bool(true, "Show Table", group="14. Table & Scroll")
tablePosition = input.string("Top Right", "Table Position", options=["Top Left", "Top Center", "Top Right", "Middle Left", "Middle Center", "Middle Right", "Bottom Left", "Bottom Center", "Bottom Right"], group="14. Table & Scroll")
tableTextSize = input.string("small", "Text Size", options=["tiny", "small", "normal", "large"], group="14. Table & Scroll")
visibleRows = input.int(15, "Visible Rows", minval=5, maxval=50, group="14. Table & Scroll")
scrollOffset = input.int(0, "Scroll Offset", minval=0, maxval=500, group="14. Table & Scroll", tooltip="0 = newest first, increase to scroll back")
tableFilterMode = input.string("All Candles", "Filter Mode", options=["All Candles", "Events Only", "CHoCH Only", "BOS Only", "LIQ Only"], group="14. Table & Scroll")

// ════════════════════════════════════════════════════════════════════════════════
// SECTION 15: TABLE COLORS
// ════════════════════════════════════════════════════════════════════════════════

tableBgColor = input.color(color.rgb(18,18,18), "Background", group="15. Table Colors")
headerBgColor = input.color(color.rgb(38,38,38), "Header Background", group="15. Table Colors")
groupHeaderBgColor = input.color(color.rgb(28,28,38), "Group Header Background", group="15. Table Colors")
footerBgColor = input.color(color.rgb(28,28,28), "Footer Background", group="15. Table Colors")
textColor = input.color(color. rgb(220,220,220), "Text Color", group="15. Table Colors")

// ════════════════════════════════════════════════════════════════════════════════
// SECTION 16: RANKING BORDER SETTINGS (NEU)
// ════════════════════════════════════════════════════════════════════════════════

rankHighColor1 = input.color(color. rgb(255,215,0), "Rank 1 (Highest) Color", group="16. Ranking Borders", inline="r1")
rankHighColor2 = input.color(color.rgb(255,185,0), "Rank 2 Color", group="16. Ranking Borders", inline="r1")
rankLowColor = input.color(color.rgb(65,105,225), "Rank 3 (Lowest) Color", group="16. Ranking Borders", inline="r2")
rankBorderWidth = input.int(2, "Border Width", minval=1, maxval=5, group="16. Ranking Borders", inline="r2")

// ════════════════════════════════════════════════════════════════════════════════
// SECTION 17: SPREAD WINDOW SETTINGS
// ════════════════════════════════════════════════════════════════════════════════

showSpreadWindow = input.bool(true, "Show Spread Window", group="17. Spread Window")
spreadWindowPosition = input.string("Bottom Right", "Position", options=["Top Left", "Top Center", "Top Right", "Middle Left", "Middle Center", "Middle Right", "Bottom Left", "Bottom Center", "Bottom Right"], group="17. Spread Window")
spreadWindowSize = input.string("small", "Size", options=["tiny", "small", "normal", "large"], group="17. Spread Window")
showSpreadAsPercent = input.bool(true, "Show as Percent", group="17. Spread Window")
spreadColorNormal = input.color(color.rgb(76,175,80), "Normal Color", group="17. Spread Window")
spreadColorHigh = input.color(color.rgb(255,82,82), "High Volatility Color", group="17.  Spread Window")
spreadColorCompression = input.color(color.rgb(33,150,243), "Compression Color", group="17. Spread Window")
spreadHighThreshold = input.float(1.5, "High Threshold", minval=1.0, maxval=5.0, step=0.1, group="17. Spread Window")
spreadLowThreshold = input. float(0.5, "Compression Threshold", minval=0.1, maxval=1.0, step=0.1, group="17. Spread Window")

// ════════════════════════════════════════════════════════════════════════════════
// SECTION 18: ROLLING WINDOWS
// ════════════════════════════════════════════════════════════════════════════════

showRollingWindows = input.bool(true, "Show Rolling Windows", group="18. Rolling Windows")
window1 = input.int(5, "Window 1", minval=0, maxval=500, group="18. Rolling Windows", inline="w1")
window2 = input.int(10, "Window 2", minval=0, maxval=500, group="18. Rolling Windows", inline="w1")
window3 = input. int(20, "Window 3", minval=0, maxval=500, group="18. Rolling Windows", inline="w2")
window4 = input. int(50, "Window 4", minval=0, maxval=500, group="18. Rolling Windows", inline="w2")
window5 = input.int(0, "Window 5", minval=0, maxval=500, group="18. Rolling Windows", inline="w3")
window6 = input.int(0, "Window 6", minval=0, maxval=500, group="18. Rolling Windows", inline="w3")

// ════════════════════════════════════════════════════════════════════════════════
// SECTION 19: LEVEL THRESHOLDS
// ════════════════════════════════════════════════════════════════════════════════

sprdLvl1 = input.float(0.5, "Spread Level 1 (Empty)", minval=0.1, maxval=2.0, step=0.1, group="19. Level Thresholds")
sprdLvl2 = input.float(1.0, "Spread Level 2 (Normal)", minval=0.5, maxval=3.0, step=0.1, group="19. Level Thresholds")
sprdLvl3 = input.float(1.5, "Spread Level 3 (Move)", minval=1.0, maxval=4.0, step=0.1, group="19. Level Thresholds")
sprdLvl4 = input.float(2.0, "Spread Level 4 (Power)", minval=1.5, maxval=5.0, step=0.1, group="19. Level Thresholds")

volLvl1 = input. float(0.5, "Volume Level 1 (Empty)", minval=0.1, maxval=2.0, step=0.1, group="19. Level Thresholds")
volLvl2 = input.float(1.0, "Volume Level 2 (Normal)", minval=0.5, maxval=3.0, step=0.1, group="19. Level Thresholds")
volLvl3 = input.float(1.5, "Volume Level 3 (Move)", minval=1.0, maxval=4.0, step=0.1, group="19. Level Thresholds")
volLvl4 = input.float(2.0, "Volume Level 4 (Power)", minval=1.5, maxval=5.0, step=0.1, group="19. Level Thresholds")

// ════════════════════════════════════════════════════════════════════════════════
// SECTION 20: CONTROL THRESHOLDS
// ════════════════════════════════════════════════════════════════════════════════

ctrlWeakAbove = input.float(60.0, "Control Weak: Above %", minval=50.0, maxval=75.0, step=5.0, group="20. Control Thresholds")
ctrlStrongAbove = input.float(80.0, "Control Strong: Above %", minval=70.0, maxval=90.0, step=5.0, group="20. Control Thresholds")
ctrlMaxAbove = input.float(80.0, "Control Max (Maru): Above %", minval=75.0, maxval=95.0, step=5.0, group="20. Control Thresholds")

// ════════════════════════════════════════════════════════════════════════════════
// SECTION 21: FLOW/TYPE COLORS
// ════════════════════════════════════════════════════════════════════════════════

colorAbsorb = input.color(color.rgb(33,150,243), "Absorb Color", group="21. Flow Colors")
colorManip = input.color(color.rgb(255,235,59), "Manipulation Color", group="21. Flow Colors")
colorBull = input.color(color.rgb(76,175,80), "Bull Color", group="21. Flow Colors")
colorBear = input.color(color.rgb(255,82,82), "Bear Color", group="21. Flow Colors")
colorHigh = input.color(color. rgb(255,82,82), "High Color", group="21. Flow Colors")
colorMid = input.color(color.rgb(255,167,38), "Mid Color", group="21. Flow Colors")
colorNorm = input.color(color.rgb(76,175,80), "Normal Color", group="21. Flow Colors")
colorNeut = input.color(color.rgb(158,158,158), "Neutral Color", group="21. Flow Colors")

// ════════════════════════════════════════════════════════════════════════════════
// HELPER FUNCTIONS
// ════════════════════════════════════════════════════════════════════════════════

getLineStyle(string s) =>
    s == "solid" ? line.style_solid : s == "dashed" ? line. style_dashed : line.style_dotted

getLabelSize(string s) =>
    s == "tiny" ? size.tiny : s == "small" ? size.small : s == "large" ? size.large : size. normal

getTextSize() =>
    tableTextSize == "tiny" ? size.tiny : tableTextSize == "small" ?  size.small : tableTextSize == "large" ? size.large : size. normal

getTablePosition() =>
    tablePosition == "Top Left" ? position.top_left : tablePosition == "Top Center" ? position.top_center : tablePosition == "Top Right" ? position.top_right : tablePosition == "Middle Left" ? position.middle_left : tablePosition == "Middle Center" ? position.middle_center : tablePosition == "Middle Right" ? position.middle_right : tablePosition == "Bottom Left" ? position.bottom_left : tablePosition == "Bottom Center" ? position.bottom_center : position.bottom_right

getSpreadWindowPosition() =>
    spreadWindowPosition == "Top Left" ? position.top_left : spreadWindowPosition == "Top Center" ? position.top_center : spreadWindowPosition == "Top Right" ? position.top_right : spreadWindowPosition == "Middle Left" ?  position.middle_left : spreadWindowPosition == "Middle Center" ? position.middle_center : spreadWindowPosition == "Middle Right" ? position. middle_right : spreadWindowPosition == "Bottom Left" ? position.bottom_left : spreadWindowPosition == "Bottom Center" ? position.bottom_center : position.bottom_right

getSpreadWindowSize() =>
    spreadWindowSize == "tiny" ? size. tiny : spreadWindowSize == "small" ? size.small : spreadWindowSize == "large" ? size.large : size.normal

formatTime(t) =>
    str.tostring(hour(t, "Europe/Berlin"), "00") + ":" + str.tostring(minute(t, "Europe/Berlin"), "00")

formatPct(p) =>
    str.tostring(p, "#.#") + "%"

shouldShowRow(chB, chS, bosB, bosS, liqB, liqS) =>
    if tableFilterMode == "All Candles"
        true
    else if tableFilterMode == "Events Only"
        chB > 0 or chS > 0 or bosB > 0 or bosS > 0 or liqB > 0 or liqS > 0
    else if tableFilterMode == "CHoCH Only"
        chB > 0 or chS > 0
    else if tableFilterMode == "BOS Only"
        bosB > 0 or bosS > 0
    else if tableFilterMode == "LIQ Only"
        liqB > 0 or liqS > 0
    else
        true

// ════════════════════════════════════════════════════════════════════════════════
// LEVEL FUNCTIONS - SPRD/VOL jetzt in PROZENT
// ════════════════════════════════════════════════════════════════════════════════

getSprdLevel(mult) =>
    if mult < sprdLvl1
        0
    else if mult < sprdLvl2
        1
    else if mult < sprdLvl3
        2
    else if mult < sprdLvl4
        3
    else
        4

getVolLevel(mult) =>
    if mult < volLvl1
        0
    else if mult < volLvl2
        1
    else if mult < volLvl3
        2
    else if mult < volLvl4
        3
    else
        4

// NEU: SPRD als Prozent (Multiplikator * 100)
getSprdPctLabel(mult) =>
    str.tostring(mult * 100, "#.#") + "%"

// NEU: VOL als Prozent (Multiplikator * 100)
getVolPctLabel(mult) =>
    str.tostring(mult * 100, "#.#") + "%"

getSprdColor(mult) =>
    int lvl = getSprdLevel(mult)
    lvl == 0 ? colorNeut : lvl == 1 ? colorNorm : lvl == 2 ? colorMid : lvl == 3 ? colorHigh : colorHigh

getVolColor(mult) =>
    int lvl = getVolLevel(mult)
    lvl == 0 ? colorNeut : lvl == 1 ? colorNorm : lvl == 2 ? colorMid : lvl == 3 ? colorHigh : colorHigh

// ════════════════════════════════════════════════════════════════════════════════
// CANDLE ANATOMY FUNCTIONS
// ════════════════════════════════════════════════════════════════════════════════

calcCandleAnatomy() =>
    float candleRange = high - low
    float bodySize = math.abs(close - open)
    float upperWick = high - math.max(close, open)
    float lowerWick = math.min(close, open) - low
    float upperWickPct = candleRange > 0 ? (upperWick / candleRange) * 100 : 0
    float bodyPct = candleRange > 0 ? (bodySize / candleRange) * 100 : 0
    float lowerWickPct = candleRange > 0 ?  (lowerWick / candleRange) * 100 : 0
    bool isBull = close >= open
    [upperWickPct, bodyPct, lowerWickPct, isBull]

// NEU: Ranking für H/WK, BODY, L/WK - returns [rank1_idx, rank2_idx, rank3_idx]
getRanking(upperWickPct, bodyPct, lowerWickPct) =>
    array<float> vals = array.from(upperWickPct, bodyPct, lowerWickPct)
    array<int> ranks = array.from(0, 1, 2)
    // Simple bubble sort
    for i = 0 to 1
        for j = 0 to 1 - i
            if array.get(vals, j) < array.get(vals, j + 1)
                float tempVal = array.get(vals, j)
                array.set(vals, j, array.get(vals, j + 1))
                array. set(vals, j + 1, tempVal)
                int tempRank = array.get(ranks, j)
                array.set(ranks, j, array.get(ranks, j + 1))
                array. set(ranks, j + 1, tempRank)
    [array.get(ranks, 0), array.get(ranks, 1), array.get(ranks, 2)]

// Gibt Border-Farbe basierend auf Ranking zurück (0=H/WK, 1=BODY, 2=L/WK)
getRankBorderColor(idx, rank1, rank2, rank3) =>
    idx == rank1 ? rankHighColor1 : idx == rank2 ? rankHighColor2 : idx == rank3 ? rankLowColor : na

getWickColor(pct) =>
    pct >= 50 ? colorHigh : pct >= 30 ? colorMid : pct >= 15 ? colorNorm : colorNeut

getBodyColor(pct, isBull) =>
    if pct >= 80
        isBull ? colorBull : colorBear
    else if pct >= 60
        isBull ? colorBull : colorBear
    else if pct >= 40
        colorMid
    else
        colorNeut

// ════════════════════════════════════════════════════════════════════════════════
// DIFF FUNCTIONS - FLOW Farben integriert in DIFF
// ════════════════════════════════════════════════════════════════════════════════

getDiffValue(sprdMult, volMult) =>
    float diff = volMult - sprdMult
    float diffPct = (diff / math.max(sprdMult, 0.01)) * 100
    diffPct

getDiffPctLabel(sprdMult, volMult) =>
    float diffPct = getDiffValue(sprdMult, volMult)
    string prefix = diffPct >= 0 ? "+" : ""
    prefix + str.tostring(diffPct, "#.#") + "%"

// FLOW-Logik jetzt in DIFF-Farbe integriert
getDiffColorWithFlow(sprdMult, volMult) =>
    int sprdLevel = getSprdLevel(sprdMult)
    int volLevel = getVolLevel(volMult)
    int diff = volLevel - sprdLevel
    if diff >= 2
        colorAbsorb  // ABSORB++
    else if diff == 1
        color.new(colorAbsorb, 40)  // ABSORB+
    else if diff == 0
        colorNorm  // NORMAL
    else if diff == -1
        color. new(colorManip, 40)  // MANIP+
    else
        colorManip  // MANIP++

// ════════════════════════════════════════════════════════════════════════════════
// CANDLE TYPE FUNCTIONS - ALLE TYPEN FARBIG (kein Grau)
// ════════════════════════════════════════════════════════════════════════════════

getCandleType(upperWickPct, bodyPct, lowerWickPct, isBull) =>
    string candleType = ""
    float bullControl = bodyPct + lowerWickPct
    float bearControl = bodyPct + upperWickPct
    bool isUpperRejection = upperWickPct > bodyPct and upperWickPct > lowerWickPct
    bool isLowerRejection = lowerWickPct > bodyPct and lowerWickPct > upperWickPct
    
    if isUpperRejection
        if bearControl >= ctrlMaxAbove
            candleType := "BIG REJ DN"
        else if bearControl >= ctrlWeakAbove
            candleType := "REJ DN"
        else
            candleType := "WEAK REJ"
    else if isLowerRejection
        if bullControl >= ctrlMaxAbove
            candleType := "BIG REJ UP"
        else if bullControl >= ctrlWeakAbove
            candleType := "REJ UP"
        else
            candleType := "WEAK REJ"
    else
        if isBull
            if bodyPct >= ctrlMaxAbove
                candleType := "MARU BULL"
            else if bullControl >= ctrlStrongAbove
                candleType := "STRONG"
            else if bullControl >= ctrlWeakAbove
                candleType := "STD BULL"
            else
                candleType := "WEAK BULL"
        else
            if bodyPct >= ctrlMaxAbove
                candleType := "MARU BEAR"
            else if bearControl >= ctrlStrongAbove
                candleType := "STRONG"
            else if bearControl >= ctrlWeakAbove
                candleType := "STD BEAR"
            else
                candleType := "WEAK BEAR"
    candleType

// NEU: Alle Types in Farbe - kein Grau mehr
getCandleTypeColor(candleType, isBull) =>
    if str.contains(candleType, "MARU") or str.contains(candleType, "BIG REJ")
        colorHigh
    else if candleType == "STRONG"
        colorMid
    else if str.contains(candleType, "STD") or str.contains(candleType, "REJ UP") or str.contains(candleType, "REJ DN")
        colorNorm
    else if str.contains(candleType, "WEAK")
        isBull ? color.new(colorBull, 50) : color.new(colorBear, 50)
    else
        colorNeut

// ════════════════════════════════════════════════════════════════════════════════
// CONTROL FUNCTIONS - Umbenannt zu BULL/BEAR/NEUT (ohne ++)
// ════════════════════════════════════════════════════════════════════════════════

getControlLabel(upperWickPct, bodyPct, lowerWickPct, isBull) =>
    float bullControl = bodyPct + lowerWickPct
    float bearControl = bodyPct + upperWickPct
    bool isUpperRejection = upperWickPct > bodyPct and upperWickPct > lowerWickPct
    bool isLowerRejection = lowerWickPct > bodyPct and lowerWickPct > upperWickPct
    
    string ctrl = "NEUT"
    
    if isUpperRejection
        if bearControl >= ctrlWeakAbove
            ctrl := "BEAR"
        else
            ctrl := "NEUT"
    else if isLowerRejection
        if bullControl >= ctrlWeakAbove
            ctrl := "BULL"
        else
            ctrl := "NEUT"
    else if isBull
        if bullControl >= ctrlWeakAbove
            ctrl := "BULL"
        else
            ctrl := "NEUT"
    else
        if bearControl >= ctrlWeakAbove
            ctrl := "BEAR"
        else
            ctrl := "NEUT"
    ctrl

getControlColor(ctrl) =>
    if ctrl == "BULL"
        colorBull
    else if ctrl == "BEAR"
        colorBear
    else
        colorNeut

getControlBuyScore(ctrl) =>
    ctrl == "BULL" ? 1 : 0

getControlSellScore(ctrl) =>
    ctrl == "BEAR" ? 1 : 0

// ════════════════════════════════════════════════════════════════════════════════
// VOLUME STRENGTH FUNCTION
// ════════════════════════════════════════════════════════════════════════════════

calculateVolumeStrength(startBar, endBar) =>
    float moveVolume = 0.0
    float compareVolume = 0.0
    int barsInMove = endBar - startBar
    
    if barsInMove > 0
        for i = 0 to barsInMove - 1
            moveVolume += volume[i]
        moveVolume := moveVolume / barsInMove
    
    if volumeCompareMode == "Custom Bars"
        for i = 0 to volumeCompareBars - 1
            compareVolume += volume[barsInMove + i]
        compareVolume := compareVolume / volumeCompareBars
    else
        compareVolume := ta.sma(volume, avgLookback)
    
    bool isStrong = compareVolume > 0 ?  (moveVolume / compareVolume) >= volumeStrengthThreshold : true
    [moveVolume, compareVolume, isStrong]

// ════════════════════════════════════════════════════════════════════════════════
// AVERAGE CALCULATIONS
// ════════════════════════════════════════════════════════════════════════════════

float avgSpread = ta.sma(high - low, avgLookback)
float avgVolume = ta.sma(volume, avgLookback)
float currentSpread = high - low
float currentSpreadPct = close > 0 ? (currentSpread / close) * 100 : 0
float avgSpreadPct = ta.sma(currentSpreadPct, avgLookback)
float curSprdMult = avgSpread > 0 ? currentSpread / avgSpread : 1
float curVolMult = avgVolume > 0 ? volume / avgVolume : 1

[curUpperWickPct, curBodyPct, curLowerWickPct, curIsBull] = calcCandleAnatomy()
string curCandleType = getCandleType(curUpperWickPct, curBodyPct, curLowerWickPct, curIsBull)
string curControl = getControlLabel(curUpperWickPct, curBodyPct, curLowerWickPct, curIsBull)

// ════════════════════════════════════════════════════════════════════════════════
// SPREAD WINDOW CALCULATIONS
// ════════════════════════════════════════════════════════════════════════════════

float currentSpreadVal = showSpreadAsPercent ? currentSpreadPct : currentSpread
float avgSpreadWindow = showSpreadAsPercent ? avgSpreadPct : avgSpread
float spreadRatio = avgSpreadWindow > 0 ? currentSpreadVal / avgSpreadWindow : 1
string volatilityRegime = spreadRatio >= spreadHighThreshold ? "HIGH VOLA" : spreadRatio <= spreadLowThreshold ? "LOW VOLA" : "NORMAL"
color spreadThresholdColor = spreadRatio >= spreadHighThreshold ? spreadColorHigh : spreadRatio <= spreadLowThreshold ? spreadColorCompression : spreadColorNormal

// ════════════════════════════════════════════════════════════════════════════════
// END OF PART 1
// ════════════════════════════════════════════════════════════════════════════════
// ════════════════════════════════════════════════════════════════════════════════
// SWING TRACKING ARRAYS
// ════════════════════════════════════════════════════════════════════════════════

var array<float> swingHighVals = array.new_float(0)
var array<int> swingHighBars = array.new_int(0)
var array<bool> swingHighActive = array.new_bool(0)
var array<bool> swingHighTouched = array.new_bool(0)
var array<line> swingHighLines = array.new_line(0)

var array<float> swingLowVals = array. new_float(0)
var array<int> swingLowBars = array.new_int(0)
var array<bool> swingLowActive = array.new_bool(0)
var array<bool> swingLowTouched = array.new_bool(0)
var array<line> swingLowLines = array.new_line(0)

var int currentTrend = 0

// ════════════════════════════════════════════════════════════════════════════════
// SWING DETECTION
// ════════════════════════════════════════════════════════════════════════════════

bool enoughBars = bar_index >= swingLookback * 2
float highestInWindow = ta.highest(high, swingLookback * 2 + 1)
float lowestInWindow = ta.lowest(low, swingLookback * 2 + 1)
bool isSwingHigh = enoughBars and high[swingLookback] == highestInWindow
bool isSwingLow = enoughBars and low[swingLookback] == lowestInWindow

if isSwingHigh
    float val = high[swingLookback]
    int bar = bar_index - swingLookback
    line l = line.new(bar, val, bar_index, val, color=swingHighActiveColor, width=swingHighActiveWidth, style=getLineStyle(swingHighActiveStyle))
    array.push(swingHighVals, val)
    array.push(swingHighBars, bar)
    array.push(swingHighActive, true)
    array.push(swingHighTouched, false)
    array.push(swingHighLines, l)
    if array.size(swingHighVals) > maxSwings
        line. delete(array.shift(swingHighLines))
        array.shift(swingHighVals)
        array.shift(swingHighBars)
        array.shift(swingHighActive)
        array.shift(swingHighTouched)

if isSwingLow
    float val = low[swingLookback]
    int bar = bar_index - swingLookback
    line l = line. new(bar, val, bar_index, val, color=swingLowActiveColor, width=swingLowActiveWidth, style=getLineStyle(swingLowActiveStyle))
    array.push(swingLowVals, val)
    array.push(swingLowBars, bar)
    array.push(swingLowActive, true)
    array.push(swingLowTouched, false)
    array.push(swingLowLines, l)
    if array.size(swingLowVals) > maxSwings
        line.delete(array.shift(swingLowLines))
        array.shift(swingLowVals)
        array. shift(swingLowBars)
        array.shift(swingLowActive)
        array.shift(swingLowTouched)

// ════════════════════════════════════════════════════════════════════════════════
// EVENT DETECTION
// ════════════════════════════════════════════════════════════════════════════════

int curChochBull = 0
int curChochBear = 0
int curBosBull = 0
int curBosBear = 0
int curLiqBull = 0
int curLiqBear = 0
bool hasAnyEvent = false
bool curChochBullStrong = false
bool curChochBearStrong = false
bool curBosBullStrong = false
bool curBosBearStrong = false

// Check Swing High Breaks
if array.size(swingHighVals) > 0
    for i = 0 to array.size(swingHighVals) - 1
        if array.get(swingHighActive, i)
            float y = array.get(swingHighVals, i)
            int x1 = array.get(swingHighBars, i)
            line l = array.get(swingHighLines, i)
            bool closeAbove = close > y
            bool highAbove = high > y
            bool broken = closeAbove and highAbove
            
            if broken
                array.set(swingHighActive, i, false)
                
                bool isStrong = true
                if enableVolumeFilter
                    [moveVol, compareVol, volStrong] = calculateVolumeStrength(x1, bar_index)
                    isStrong := volStrong
                
                bool isChoch = currentTrend == -1
                
                if isChoch and enableChoch
                    curChochBull += 1
                    curChochBullStrong := isStrong
                    hasAnyEvent := true
                    
                    if not na(l)
                        if isStrong
                            line.set_color(l, swingHighBrokenStrongColor)
                            line.set_width(l, swingHighBrokenStrongWidth)
                            line.set_style(l, getLineStyle(swingHighBrokenStrongStyle))
                        else
                            line.set_color(l, swingHighBrokenWeakColor)
                            line. set_width(l, swingHighBrokenWeakWidth)
                            line.set_style(l, getLineStyle(swingHighBrokenWeakStyle))
                        line.set_x2(l, bar_index)
                    
                    if showChochLabels and (isStrong or showWeakChoch)
                        color labelColor = isStrong ? chochUpStrongColor : chochUpWeakColor
                        string labelText = isStrong ? "CHoCH" : "choch"
                        int labelBar = chochLabelPosition == "Center of Line" ? int((x1 + bar_index) / 2) : bar_index
                        label.new(labelBar, y, labelText, color=color.new(color. white, 100), textcolor=labelColor, style=label.style_none, yloc=yloc.price, size=getLabelSize(chochLabelSizeStr))
                    
                    currentTrend := 1
                
                else if enableBos
                    curBosBull += 1
                    curBosBullStrong := isStrong
                    hasAnyEvent := true
                    
                    if not na(l)
                        if isStrong
                            line.set_color(l, swingHighBrokenStrongColor)
                            line.set_width(l, swingHighBrokenStrongWidth)
                            line.set_style(l, getLineStyle(swingHighBrokenStrongStyle))
                        else
                            line.set_color(l, swingHighBrokenWeakColor)
                            line.set_width(l, swingHighBrokenWeakWidth)
                            line. set_style(l, getLineStyle(swingHighBrokenWeakStyle))
                        line.set_x2(l, bar_index)
                    
                    if showBosLabels and (isStrong or showWeakBos)
                        color labelColor = isStrong ? bosUpStrongColor : bosUpWeakColor
                        string labelText = isStrong ?  "BOS" : "bos"
                        int labelBar = bosLabelPosition == "Center of Line" ?  int((x1 + bar_index) / 2) : bar_index
                        label.new(labelBar, y, labelText, color=color.new(color.white, 100), textcolor=labelColor, style=label. style_none, yloc=yloc.price, size=getLabelSize(bosLabelSizeStr))
                    
                    currentTrend := 1
            
            else if highAbove and not closeAbove and enableLiq
                if not array.get(swingHighTouched, i)
                    array.set(swingHighTouched, i, true)
                    curLiqBull += 1
                    hasAnyEvent := true
                    
                    if showLiqLabels
                        label.new(bar_index, y, "LIQ", color=color.new(color.white, 100), textcolor=liqUpColor, style=label. style_none, yloc=yloc.price, size=getLabelSize(liqLabelSizeStr))
                    
                    if not na(l)
                        line.set_color(l, swingHighTouchedColor)
                        line.set_width(l, swingHighTouchedWidth)
                        line.set_style(l, getLineStyle(swingHighTouchedStyle))
                
                if not na(l)
                    line.set_x2(l, bar_index)
            
            else
                if not na(l)
                    line. set_x2(l, bar_index)

// Check Swing Low Breaks
if array.size(swingLowVals) > 0
    for i = 0 to array.size(swingLowVals) - 1
        if array.get(swingLowActive, i)
            float y = array.get(swingLowVals, i)
            int x1 = array. get(swingLowBars, i)
            line l = array.get(swingLowLines, i)
            bool closeBelow = close < y
            bool lowBelow = low < y
            bool broken = closeBelow and lowBelow
            
            if broken
                array.set(swingLowActive, i, false)
                
                bool isStrong = true
                if enableVolumeFilter
                    [moveVol, compareVol, volStrong] = calculateVolumeStrength(x1, bar_index)
                    isStrong := volStrong
                
                bool isChoch = currentTrend == 1
                
                if isChoch and enableChoch
                    curChochBear += 1
                    curChochBearStrong := isStrong
                    hasAnyEvent := true
                    
                    if not na(l)
                        if isStrong
                            line.set_color(l, swingLowBrokenStrongColor)
                            line.set_width(l, swingLowBrokenStrongWidth)
                            line.set_style(l, getLineStyle(swingLowBrokenStrongStyle))
                        else
                            line.set_color(l, swingLowBrokenWeakColor)
                            line.set_width(l, swingLowBrokenWeakWidth)
                            line.set_style(l, getLineStyle(swingLowBrokenWeakStyle))
                        line.set_x2(l, bar_index)
                    
                    if showChochLabels and (isStrong or showWeakChoch)
                        color labelColor = isStrong ? chochDownStrongColor : chochDownWeakColor
                        string labelText = isStrong ? "CHoCH" : "choch"
                        int labelBar = chochLabelPosition == "Center of Line" ? int((x1 + bar_index) / 2) : bar_index
                        label.new(labelBar, y, labelText, color=color.new(color.white, 100), textcolor=labelColor, style=label.style_none, yloc=yloc.price, size=getLabelSize(chochLabelSizeStr))
                    
                    currentTrend := -1
                
                else if enableBos
                    curBosBear += 1
                    curBosBearStrong := isStrong
                    hasAnyEvent := true
                    
                    if not na(l)
                        if isStrong
                            line.set_color(l, swingLowBrokenStrongColor)
                            line. set_width(l, swingLowBrokenStrongWidth)
                            line.set_style(l, getLineStyle(swingLowBrokenStrongStyle))
                        else
                            line.set_color(l, swingLowBrokenWeakColor)
                            line.set_width(l, swingLowBrokenWeakWidth)
                            line. set_style(l, getLineStyle(swingLowBrokenWeakStyle))
                        line.set_x2(l, bar_index)
                    
                    if showBosLabels and (isStrong or showWeakBos)
                        color labelColor = isStrong ?  bosDownStrongColor : bosDownWeakColor
                        string labelText = isStrong ? "BOS" : "bos"
                        int labelBar = bosLabelPosition == "Center of Line" ? int((x1 + bar_index) / 2) : bar_index
                        label. new(labelBar, y, labelText, color=color.new(color.white, 100), textcolor=labelColor, style=label.style_none, yloc=yloc.price, size=getLabelSize(bosLabelSizeStr))
                    
                    currentTrend := -1
            
            else if lowBelow and not closeBelow and enableLiq
                if not array.get(swingLowTouched, i)
                    array.set(swingLowTouched, i, true)
                    curLiqBear += 1
                    hasAnyEvent := true
                    
                    if showLiqLabels
                        label.new(bar_index, y, "LIQ", color=color.new(color.white, 100), textcolor=liqDownColor, style=label.style_none, yloc=yloc.price, size=getLabelSize(liqLabelSizeStr))
                    
                    if not na(l)
                        line.set_color(l, swingLowTouchedColor)
                        line.set_width(l, swingLowTouchedWidth)
                        line.set_style(l, getLineStyle(swingLowTouchedStyle))
                
                if not na(l)
                    line. set_x2(l, bar_index)
            
            else
                if not na(l)
                    line.set_x2(l, bar_index)

// ════════════════════════════════════════════════════════════════════════════════
// EVENT STORAGE ARRAYS
// ════════════════════════════════════════════════════════════════════════════════

var array<int> evtTime = array.new_int(0)
var array<int> evtChochBull = array.new_int(0)
var array<int> evtChochBear = array.new_int(0)
var array<int> evtBosBull = array.new_int(0)
var array<int> evtBosBear = array.new_int(0)
var array<int> evtLiqBull = array.new_int(0)
var array<int> evtLiqBear = array.new_int(0)
var array<float> evtSprdMult = array.new_float(0)
var array<float> evtVolMult = array.new_float(0)
var array<float> evtUpperWickPct = array.new_float(0)
var array<float> evtBodyPct = array.new_float(0)
var array<float> evtLowerWickPct = array.new_float(0)
var array<bool> evtIsBull = array.new_bool(0)
var array<string> evtCandleType = array.new_string(0)
var array<string> evtControl = array.new_string(0)

if barstate.ishistory or barstate.isconfirmed
    array.unshift(evtTime, time)
    array.unshift(evtChochBull, curChochBull)
    array.unshift(evtChochBear, curChochBear)
    array.unshift(evtBosBull, curBosBull)
    array.unshift(evtBosBear, curBosBear)
    array.unshift(evtLiqBull, curLiqBull)
    array.unshift(evtLiqBear, curLiqBear)
    array.unshift(evtSprdMult, curSprdMult)
    array.unshift(evtVolMult, curVolMult)
    array.unshift(evtUpperWickPct, curUpperWickPct)
    array.unshift(evtBodyPct, curBodyPct)
    array.unshift(evtLowerWickPct, curLowerWickPct)
    array.unshift(evtIsBull, curIsBull)
    array. unshift(evtCandleType, curCandleType)
    array.unshift(evtControl, curControl)

int maxArraySize = math.max(avgLookback, 5000)
if array.size(evtTime) > maxArraySize
    array. pop(evtTime)
    array.pop(evtChochBull)
    array.pop(evtChochBear)
    array.pop(evtBosBull)
    array.pop(evtBosBear)
    array.pop(evtLiqBull)
    array. pop(evtLiqBear)
    array.pop(evtSprdMult)
    array.pop(evtVolMult)
    array.pop(evtUpperWickPct)
    array.pop(evtBodyPct)
    array. pop(evtLowerWickPct)
    array.pop(evtIsBull)
    array.pop(evtCandleType)
    array. pop(evtControl)

// ════════════════════════════════════════════════════════════════════════════════
// ROLLING WINDOW STATS FUNCTION
// ════════════════════════════════════════════════════════════════════════════════

calcWindowStats(windowSize) =>
    int chB = 0
    int chS = 0
    int bosB = 0
    int bosS = 0
    int liqB = 0
    int liqS = 0
    int buyScore = 0
    int sellScore = 0
    int evtCount = math.min(array.size(evtChochBull), windowSize)
    if evtCount > 0
        for i = 0 to evtCount - 1
            chB += array.get(evtChochBull, i)
            chS += array.get(evtChochBear, i)
            bosB += array.get(evtBosBull, i)
            bosS += array.get(evtBosBear, i)
            liqB += array.get(evtLiqBull, i)
            liqS += array. get(evtLiqBear, i)
            string ctrl = array.get(evtControl, i)
            buyScore += getControlBuyScore(ctrl)
            sellScore += getControlSellScore(ctrl)
    [chB, chS, bosB, bosS, liqB, liqS, buyScore, sellScore]

// ════════════════════════════════════════════════════════════════════════════════
// SPREAD WINDOW TABLE
// ════════════════════════════════════════════════════════════════════════════════

var table spreadTable = table.new(getSpreadWindowPosition(), 2, 12, bgcolor=color.rgb(18,18,18), border_width=1, border_color=color.new(color.gray, 50))

if showSpreadWindow and barstate.islast
    swSize = getSpreadWindowSize()
    table.cell(spreadTable, 0, 0, "SPREAD", bgcolor=color.rgb(38,38,38), text_color=color.white, text_size=swSize)
    table.cell(spreadTable, 1, 0, curIsBull ? "BULL" : "BEAR", bgcolor=curIsBull ? colorBull : colorBear, text_color=color.white, text_size=swSize)
    table.cell(spreadTable, 0, 1, "Current:", text_color=color.gray, text_size=swSize, bgcolor=color.rgb(28,28,28))
    table.cell(spreadTable, 1, 1, str. tostring(currentSpreadVal, "#. ###") + (showSpreadAsPercent ? "%" : ""), bgcolor=spreadThresholdColor, text_color=color.white, text_size=swSize)
    table.cell(spreadTable, 0, 2, "Mean:", text_color=color.gray, text_size=swSize, bgcolor=color.rgb(28,28,28))
    table. cell(spreadTable, 1, 2, str.tostring(avgSpreadWindow, "#.###") + (showSpreadAsPercent ? "%" : ""), bgcolor=color.rgb(50,50,50), text_color=color.white, text_size=swSize)
    float spreadMult = avgSpreadWindow > 0 ? currentSpreadVal / avgSpreadWindow : 1
    table.cell(spreadTable, 0, 3, "Mult:", text_color=color. gray, text_size=swSize, bgcolor=color.rgb(28,28,28))
    table.cell(spreadTable, 1, 3, str.tostring(spreadMult, "#.##") + "x", bgcolor=spreadThresholdColor, text_color=color. white, text_size=swSize)
    table.cell(spreadTable, 0, 4, "Regime:", text_color=color.gray, text_size=swSize, bgcolor=color.rgb(28,28,28))
    color regimeColor = volatilityRegime == "HIGH VOLA" ? spreadColorHigh : volatilityRegime == "LOW VOLA" ? spreadColorCompression : spreadColorNormal
    table.cell(spreadTable, 1, 4, volatilityRegime, bgcolor=regimeColor, text_color=color.white, text_size=swSize)
    table.cell(spreadTable, 0, 5, "DIFF:", text_color=color.gray, text_size=swSize, bgcolor=color.rgb(28,28,28))
    table. cell(spreadTable, 1, 5, getDiffPctLabel(curSprdMult, curVolMult), text_color=getDiffColorWithFlow(curSprdMult, curVolMult), text_size=swSize, bgcolor=color.rgb(28,28,28))

// ════════════════════════════════════════════════════════════════════════════════
// MAIN TABLE - NEU MIT GRUPPEN-HEADER
// ════════════════════════════════════════════════════════════════════════════════
// Spalten: TIME | CH BOS LIQ | SPRD% DIFF% VOL% | H/WK BODY L/WK | TYPE | BULL BEAR NEUT
// Columns:  0   |  1   2   3 |  4     5     6   |  7    8    9   |  10  |  11   12   13

int tableColumns = 14
var table tbl = table.new(getTablePosition(), tableColumns, 90, bgcolor=tableBgColor, border_width=1, border_color=color.new(color.gray, 80))

if showTable and barstate.islast
    tSize = getTextSize()
    int evtCount = array.size(evtTime)
    int currentRow = 0
    int effectiveOffset = math.min(scrollOffset, math.max(0, evtCount - visibleRows))
    
    // ═══════════════════════════════════════════════════════════════════════════
    // ROW 0: TITLE
    // ═══════════════════════════════════════════════════════════════════════════
    string titleText = "ORDERFLOW BREAK TAPE v24"
    string filterText = tableFilterMode != "All Candles" ? " [" + tableFilterMode + "]" : ""
    string settingsText = "SW:" + str.tostring(swingLookback) + " AVG:" + str.tostring(avgLookback) + filterText
    
    table.cell(tbl, 0, currentRow, titleText, bgcolor=headerBgColor, text_color=textColor, text_size=tSize, text_halign=text. align_left)
    table.merge_cells(tbl, 0, currentRow, 6, currentRow)
    table.cell(tbl, 7, currentRow, settingsText, bgcolor=headerBgColor, text_color=colorNeut, text_size=tSize, text_halign=text. align_right)
    table.merge_cells(tbl, 7, currentRow, 13, currentRow)
    currentRow += 1
    
    // ═══════════════════════════════════════════════════════════════════════════
    // ROLLING WINDOWS (if enabled)
    // ═══════════════════════════════════════════════════════════════════════════
    if showRollingWindows
        windowSizes = array.from(window1, window2, window3, window4, window5, window6)
        for idx = 0 to 5
            int winSize = array.get(windowSizes, idx)
            if winSize > 0
                [chB, chS, bosB, bosS, liqB, liqS, buyScore, sellScore] = calcWindowStats(winSize)
                string winLabel = str.tostring(winSize)
                string bullText = "UP CH:" + str.tostring(chB) + " BOS:" + str.tostring(bosB) + " LIQ:" + str.tostring(liqB)
                string bearText = "DN CH:" + str.tostring(chS) + " BOS:" + str.tostring(bosS) + " LIQ:" + str.tostring(liqS)
                string ctrlText = "BULL:" + str.tostring(buyScore) + " | BEAR:" + str.tostring(sellScore)
                int totalBull = chB + bosB + liqB
                int totalBear = chS + bosS + liqS
                color winColor = totalBull > totalBear ? colorBull : totalBear > totalBull ? colorBear : colorNeut
                color ctrlColor = buyScore > sellScore ? colorBull : sellScore > buyScore ? colorBear : colorNeut
                table. cell(tbl, 0, currentRow, winLabel, bgcolor=color.new(winColor, 85), text_color=winColor, text_size=tSize, text_halign=text. align_center)
                table.cell(tbl, 1, currentRow, bullText, bgcolor=color.new(colorBull, 90), text_color=colorBull, text_size=tSize, text_halign=text.align_left)
                table.merge_cells(tbl, 1, currentRow, 5, currentRow)
                table. cell(tbl, 6, currentRow, bearText, bgcolor=color.new(colorBear, 90), text_color=colorBear, text_size=tSize, text_halign=text.align_left)
                table.merge_cells(tbl, 6, currentRow, 10, currentRow)
                table.cell(tbl, 11, currentRow, ctrlText, bgcolor=color.new(ctrlColor, 85), text_color=ctrlColor, text_size=tSize, text_halign=text. align_center)
                table. merge_cells(tbl, 11, currentRow, 13, currentRow)
                currentRow += 1
    
    // ═══════════════════════════════════════════════════════════════════════════
    // ROW: GROUP HEADERS (übergreifende Namen)
    // ═══════════════════════════════════════════════════════════════════════════
    table.cell(tbl, 0, currentRow, "───", bgcolor=groupHeaderBgColor, text_color=color.rgb(100,200,255), text_size=tSize)
    table.cell(tbl, 1, currentRow, "══ EVENTS ══", bgcolor=groupHeaderBgColor, text_color=color.rgb(255,200,100), text_size=tSize)
    table.merge_cells(tbl, 1, currentRow, 3, currentRow)
    table. cell(tbl, 4, currentRow, "══ VOLUME ══", bgcolor=groupHeaderBgColor, text_color=color.rgb(150,255,150), text_size=tSize)
    table.merge_cells(tbl, 4, currentRow, 6, currentRow)
    table.cell(tbl, 7, currentRow, "══ ANATOMY ══", bgcolor=groupHeaderBgColor, text_color=color.rgb(255,150,255), text_size=tSize)
    table.merge_cells(tbl, 7, currentRow, 9, currentRow)
    table. cell(tbl, 10, currentRow, "───", bgcolor=groupHeaderBgColor, text_color=color.rgb(255,220,100), text_size=tSize)
    table.cell(tbl, 11, currentRow, "══ CONTROL ══", bgcolor=groupHeaderBgColor, text_color=color.rgb(200,200,255), text_size=tSize)
    table.merge_cells(tbl, 11, currentRow, 13, currentRow)
    currentRow += 1
    
    // ═══════════════════════════════════════════════════════════════════════════
    // ROW: COLUMN HEADERS
    // ═══════════════════════════════════════════════════════════════════════════
    table.cell(tbl, 0, currentRow, "TIME", bgcolor=headerBgColor, text_color=textColor, text_size=tSize)
    table.cell(tbl, 1, currentRow, "CH", bgcolor=headerBgColor, text_color=textColor, text_size=tSize)
    table.cell(tbl, 2, currentRow, "BOS", bgcolor=headerBgColor, text_color=textColor, text_size=tSize)
    table.cell(tbl, 3, currentRow, "LIQ", bgcolor=headerBgColor, text_color=textColor, text_size=tSize)
    table.cell(tbl, 4, currentRow, "SPRD%", bgcolor=headerBgColor, text_color=textColor, text_size=tSize)
    table.cell(tbl, 5, currentRow, "DIFF%", bgcolor=headerBgColor, text_color=textColor, text_size=tSize)
    table.cell(tbl, 6, currentRow, "VOL%", bgcolor=headerBgColor, text_color=textColor, text_size=tSize)
    table.cell(tbl, 7, currentRow, "H/WK", bgcolor=headerBgColor, text_color=textColor, text_size=tSize)
    table.cell(tbl, 8, currentRow, "BODY", bgcolor=headerBgColor, text_color=textColor, text_size=tSize)
    table.cell(tbl, 9, currentRow, "L/WK", bgcolor=headerBgColor, text_color=textColor, text_size=tSize)
    table.cell(tbl, 10, currentRow, "TYPE", bgcolor=headerBgColor, text_color=textColor, text_size=tSize)
    table.cell(tbl, 11, currentRow, "BULL", bgcolor=headerBgColor, text_color=colorBull, text_size=tSize)
    table.cell(tbl, 12, currentRow, "BEAR", bgcolor=headerBgColor, text_color=colorBear, text_size=tSize)
    table.cell(tbl, 13, currentRow, "NEUT", bgcolor=headerBgColor, text_color=colorNeut, text_size=tSize)
    currentRow += 1
    
    // ═══════════════════════════════════════════════════════════════════════════
    // LIVE ROW
    // ═══════════════════════════════════════════════════════════════════════════
    if effectiveOffset == 0 and barstate.isrealtime
        // Get ranking for anatomy
        [liveRank1, liveRank2, liveRank3] = getRanking(curUpperWickPct, curBodyPct, curLowerWickPct)
        
        // CH text
        string chTextLive = ""
        if curChochBull > 0 and curChochBear > 0
            chTextLive := str.tostring(curChochBull) + "U " + str.tostring(curChochBear) + "D"
        else if curChochBull > 0
            chTextLive := str.tostring(curChochBull) + "U"
        else if curChochBear > 0
            chTextLive := str.tostring(curChochBear) + "D"
        color chColorLive = curChochBull > 0 and curChochBear > 0 ? colorMid : curChochBull > 0 ?  chochUpStrongColor : curChochBear > 0 ? chochDownStrongColor : tableBgColor
        
        // BOS text
        string bosTextLive = ""
        if curBosBull > 0 and curBosBear > 0
            bosTextLive := str.tostring(curBosBull) + "U " + str.tostring(curBosBear) + "D"
        else if curBosBull > 0
            bosTextLive := str.tostring(curBosBull) + "U"
        else if curBosBear > 0
            bosTextLive := str.tostring(curBosBear) + "D"
        color bosColorLive = curBosBull > 0 and curBosBear > 0 ? colorMid : curBosBull > 0 ? bosUpStrongColor : curBosBear > 0 ? bosDownStrongColor : tableBgColor
        
        // LIQ text
        string liqTextLive = ""
        if curLiqBull > 0 and curLiqBear > 0
            liqTextLive := str.tostring(curLiqBull) + "U " + str.tostring(curLiqBear) + "D"
        else if curLiqBull > 0
            liqTextLive := str.tostring(curLiqBull) + "U"
        else if curLiqBear > 0
            liqTextLive := str.tostring(curLiqBear) + "D"
        color liqColorLive = curLiqBull > 0 and curLiqBear > 0 ? colorMid : curLiqBull > 0 or curLiqBear > 0 ? liqUpColor : tableBgColor
        
        // Ranking border colors
        color hwkBorderLive = getRankBorderColor(0, liveRank1, liveRank2, liveRank3)
        color bodyBorderLive = getRankBorderColor(1, liveRank1, liveRank2, liveRank3)
        color lwkBorderLive = getRankBorderColor(2, liveRank1, liveRank2, liveRank3)
        
        // Control
        string liveBullCtrl = curControl == "BULL" ? "●" : ""
        string liveBearCtrl = curControl == "BEAR" ? "●" : ""
        string liveNeutCtrl = curControl == "NEUT" ? "●" : ""
        
        table.cell(tbl, 0, currentRow, formatTime(time), bgcolor=hasAnyEvent ? color.new(colorMid, 80) : tableBgColor, text_color=color.rgb(0,255,0), text_size=tSize)
        table.cell(tbl, 1, currentRow, chTextLive, bgcolor=color.new(chColorLive, 90), text_color=chColorLive, text_size=tSize)
        table.cell(tbl, 2, currentRow, bosTextLive, bgcolor=color.new(bosColorLive, 90), text_color=bosColorLive, text_size=tSize)
        table.cell(tbl, 3, currentRow, liqTextLive, bgcolor=color.new(liqColorLive, 90), text_color=liqColorLive, text_size=tSize)
        table.cell(tbl, 4, currentRow, getSprdPctLabel(curSprdMult), bgcolor=tableBgColor, text_color=getSprdColor(curSprdMult), text_size=tSize)
        table.cell(tbl, 5, currentRow, getDiffPctLabel(curSprdMult, curVolMult), bgcolor=tableBgColor, text_color=getDiffColorWithFlow(curSprdMult, curVolMult), text_size=tSize)
        table.cell(tbl, 6, currentRow, getVolPctLabel(curVolMult), bgcolor=tableBgColor, text_color=getVolColor(curVolMult), text_size=tSize)
        table.cell(tbl, 7, currentRow, formatPct(curUpperWickPct), bgcolor=color.new(hwkBorderLive, 80), text_color=getWickColor(curUpperWickPct), text_size=tSize)
        table.cell(tbl, 8, currentRow, formatPct(curBodyPct), bgcolor=color.new(bodyBorderLive, 80), text_color=getBodyColor(curBodyPct, curIsBull), text_size=tSize)
        table.cell(tbl, 9, currentRow, formatPct(curLowerWickPct), bgcolor=color.new(lwkBorderLive, 80), text_color=getWickColor(curLowerWickPct), text_size=tSize)
        table.cell(tbl, 10, currentRow, curCandleType, bgcolor=tableBgColor, text_color=getCandleTypeColor(curCandleType, curIsBull), text_size=tSize)
        table. cell(tbl, 11, currentRow, liveBullCtrl, bgcolor=curControl == "BULL" ? color.new(colorBull, 70) : tableBgColor, text_color=colorBull, text_size=tSize)
        table.cell(tbl, 12, currentRow, liveBearCtrl, bgcolor=curControl == "BEAR" ? color.new(colorBear, 70) : tableBgColor, text_color=colorBear, text_size=tSize)
        table.cell(tbl, 13, currentRow, liveNeutCtrl, bgcolor=curControl == "NEUT" ? color.new(colorNeut, 70) : tableBgColor, text_color=colorNeut, text_size=tSize)
        currentRow += 1
    
    // ═══════════════════════════════════════════════════════════════════════════
    // HISTORICAL ROWS
    // ═══════════════════════════════════════════════════════════════════════════
    int rowsShown = 0
    int arrayIdx = effectiveOffset
    
    while rowsShown < visibleRows and arrayIdx < evtCount
        int chB = array.get(evtChochBull, arrayIdx)
        int chS = array.get(evtChochBear, arrayIdx)
        int bosB = array.get(evtBosBull, arrayIdx)
        int bosS = array. get(evtBosBear, arrayIdx)
        int liqB = array.get(evtLiqBull, arrayIdx)
        int liqS = array.get(evtLiqBear, arrayIdx)
        
        if shouldShowRow(chB, chS, bosB, bosS, liqB, liqS)
            int t = array.get(evtTime, arrayIdx)
            float sprd = array.get(evtSprdMult, arrayIdx)
            float vol = array.get(evtVolMult, arrayIdx)
            float upperWick = array.get(evtUpperWickPct, arrayIdx)
            float body = array.get(evtBodyPct, arrayIdx)
            float lowerWick = array.get(evtLowerWickPct, arrayIdx)
            bool isBull = array.get(evtIsBull, arrayIdx)
            string candleType = array.get(evtCandleType, arrayIdx)
            string control = array.get(evtControl, arrayIdx)
            
            // Get ranking for anatomy
            [rank1, rank2, rank3] = getRanking(upperWick, body, lowerWick)
            
            // CH text
            string chText = ""
            if chB > 0 and chS > 0
                chText := str. tostring(chB) + "U " + str.tostring(chS) + "D"
            else if chB > 0
                chText := str.tostring(chB) + "U"
            else if chS > 0
                chText := str.tostring(chS) + "D"
            color chColor = chB > 0 and chS > 0 ? colorMid : chB > 0 ? chochUpStrongColor : chS > 0 ?  chochDownStrongColor : tableBgColor
            
            // BOS text
            string bosText = ""
            if bosB > 0 and bosS > 0
                bosText := str. tostring(bosB) + "U " + str.tostring(bosS) + "D"
            else if bosB > 0
                bosText := str.tostring(bosB) + "U"
            else if bosS > 0
                bosText := str.tostring(bosS) + "D"
            color bosColor = bosB > 0 and bosS > 0 ? colorMid : bosB > 0 ? bosUpStrongColor : bosS > 0 ? bosDownStrongColor : tableBgColor
            
            // LIQ text
            string liqText = ""
            if liqB > 0 and liqS > 0
                liqText := str.tostring(liqB) + "U " + str.tostring(liqS) + "D"
            else if liqB > 0
                liqText := str.tostring(liqB) + "U"
            else if liqS > 0
                liqText := str.tostring(liqS) + "D"
            color liqColorCell = liqB > 0 and liqS > 0 ? colorMid : liqB > 0 or liqS > 0 ?  liqUpColor : tableBgColor
            
            // Ranking border colors
            color hwkBorder = getRankBorderColor(0, rank1, rank2, rank3)
            color bodyBorder = getRankBorderColor(1, rank1, rank2, rank3)
            color lwkBorder = getRankBorderColor(2, rank1, rank2, rank3)
            
            // Control
            string bullCtrl = control == "BULL" ? "●" : ""
            string bearCtrl = control == "BEAR" ? "●" : ""
            string neutCtrl = control == "NEUT" ? "●" : ""
            
            // Time text
            string timeText = ""
            if tableFilterMode != "All Candles"
                timeText := "#" + str.tostring(arrayIdx) + " " + formatTime(t)
            else if effectiveOffset > 0
                timeText := str.tostring(arrayIdx) + "|" + formatTime(t)
            else
                timeText := formatTime(t)
            
            table.cell(tbl, 0, currentRow, timeText, bgcolor=tableBgColor, text_color=textColor, text_size=tSize)
            table.cell(tbl, 1, currentRow, chText, bgcolor=color.new(chColor, 90), text_color=chColor, text_size=tSize)
            table.cell(tbl, 2, currentRow, bosText, bgcolor=color.new(bosColor, 90), text_color=bosColor, text_size=tSize)
            table.cell(tbl, 3, currentRow, liqText, bgcolor=color. new(liqColorCell, 90), text_color=liqColorCell, text_size=tSize)
            table.cell(tbl, 4, currentRow, getSprdPctLabel(sprd), bgcolor=tableBgColor, text_color=getSprdColor(sprd), text_size=tSize)
            table.cell(tbl, 5, currentRow, getDiffPctLabel(sprd, vol), bgcolor=tableBgColor, text_color=getDiffColorWithFlow(sprd, vol), text_size=tSize)
            table.cell(tbl, 6, currentRow, getVolPctLabel(vol), bgcolor=tableBgColor, text_color=getVolColor(vol), text_size=tSize)
            table.cell(tbl, 7, currentRow, formatPct(upperWick), bgcolor=color.new(hwkBorder, 80), text_color=getWickColor(upperWick), text_size=tSize)
            table.cell(tbl, 8, currentRow, formatPct(body), bgcolor=color. new(bodyBorder, 80), text_color=getBodyColor(body, isBull), text_size=tSize)
            table.cell(tbl, 9, currentRow, formatPct(lowerWick), bgcolor=color.new(lwkBorder, 80), text_color=getWickColor(lowerWick), text_size=tSize)
            table.cell(tbl, 10, currentRow, candleType, bgcolor=tableBgColor, text_color=getCandleTypeColor(candleType, isBull), text_size=tSize)
            table. cell(tbl, 11, currentRow, bullCtrl, bgcolor=control == "BULL" ? color. new(colorBull, 70) : tableBgColor, text_color=colorBull, text_size=tSize)
            table.cell(tbl, 12, currentRow, bearCtrl, bgcolor=control == "BEAR" ? color.new(colorBear, 70) : tableBgColor, text_color=colorBear, text_size=tSize)
            table.cell(tbl, 13, currentRow, neutCtrl, bgcolor=control == "NEUT" ? color.new(colorNeut, 70) : tableBgColor, text_color=colorNeut, text_size=tSize)
            
            currentRow += 1
            rowsShown += 1
        
        arrayIdx += 1
    
    // ═══════════════════════════════════════════════════════════════════════════
    // FOOTER
    // ═══════════════════════════════════════════════════════════════════════════
    int footerRow = currentRow + 1
    
    int filteredCount = 0
    if evtCount > 0
        for i = 0 to evtCount - 1
            int chB = array.get(evtChochBull, i)
            int chS = array. get(evtChochBear, i)
            int bosB = array.get(evtBosBull, i)
            int bosS = array.get(evtBosBear, i)
            int liqB = array. get(evtLiqBull, i)
            int liqS = array.get(evtLiqBear, i)
            if shouldShowRow(chB, chS, bosB, bosS, liqB, liqS)
                filteredCount += 1
    
    [fChB, fChS, fBosB, fBosS, fLiqB, fLiqS, fBuyScore, fSellScore] = calcWindowStats(avgLookback)
    
    int totalBull = fChB + fBosB + fLiqB
    int totalBear = fChS + fBosS + fLiqS
    int totalEvents = totalBull + totalBear
    
    float bullPct = totalEvents > 0 ? (float(totalBull) / float(totalEvents)) * 100 : 50
    float bearPct = totalEvents > 0 ? (float(totalBear) / float(totalEvents)) * 100 : 50
    
    string filterInfo = tableFilterMode != "All Candles" ? " | FILTER: " + str.tostring(filteredCount) : ""
    string footerText = "BULL:" + str.tostring(bullPct, "#.#") + "% | BEAR:" + str. tostring(bearPct, "#.#") + "% | CTRL B:" + str.tostring(fBuyScore) + " S:" + str.tostring(fSellScore) + filterInfo
    color footerColor = bullPct > 55 ?  colorBull : bearPct > 55 ? colorBear : colorNeut
    
    table.cell(tbl, 0, footerRow, footerText, bgcolor=footerBgColor, text_color=footerColor, text_size=tSize, text_halign=text. align_center)
    table.merge_cells(tbl, 0, footerRow, 13, footerRow)

// ════════════════════════════════════════════════════════════════════════════════
// ALERTS
// ════════════════════════════════════════════════════════════════════════════════

alertcondition(curChochBull > 0 and curChochBullStrong, title="CHoCH Bullish Strong", message="STRONG CHoCH UP - Bullish Change of Character!")
alertcondition(curChochBull > 0 and not curChochBullStrong, title="CHoCH Bullish Weak", message="weak choch up - Bullish Change of Character")
alertcondition(curChochBear > 0 and curChochBearStrong, title="CHoCH Bearish Strong", message="STRONG CHoCH DN - Bearish Change of Character!")
alertcondition(curChochBear > 0 and not curChochBearStrong, title="CHoCH Bearish Weak", message="weak choch dn - Bearish Change of Character")
alertcondition(curBosBull > 0 and curBosBullStrong, title="BOS Bullish Strong", message="STRONG BOS UP - Bullish Break of Structure!")
alertcondition(curBosBull > 0 and not curBosBullStrong, title="BOS Bullish Weak", message="weak bos up - Bullish Break of Structure")
alertcondition(curBosBear > 0 and curBosBearStrong, title="BOS Bearish Strong", message="STRONG BOS DN - Bearish Break of Structure!")
alertcondition(curBosBear > 0 and not curBosBearStrong, title="BOS Bearish Weak", message="weak bos dn - Bearish Break of Structure")
alertcondition(curLiqBull > 0, title="LIQ Bullish", message="LIQ UP - Liquidity Sweep Above!")
alertcondition(curLiqBear > 0, title="LIQ Bearish", message="LIQ DN - Liquidity Sweep Below!")
alertcondition(curLiqBull > 0 and curLiqBear > 0, title="DUAL LIQ", message="DUAL LIQ - Both Sides Swept!")

// ════════════════════════════════════════════════════════════════════════════════
// END OF SCRIPT v24
// ════════════════════════════════════════════════════════════════════════════════

Overview

Breaks can be filtered by a volume strength check that compares the breaking bar with the last few bars or with a tape average, and weaker breaks can be shown or hidden. Swing lines change colour and style depending on whether they are active, touched or broken. Swing length, maximum swings and many colours are adjustable.

Details

Published by

Blendoxius on GitHub

Type

Indicator, Pine Script v6

Draws

On the price chart

Category

SMC / ICT / price action, Volume, 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
Max Swingsint50maxSwings
Average Lookbackint100avgLookback
Enable CHoCHbooltrueenableChoch
Enable BOSbooltrueenableBos
Enable LIQbooltrueenableLiq
Enable Volume FilterbooltrueenableVolumeFilter
Compare ModestringCustom BarsvolumeCompareMode
Compare to Last X Barsint3volumeCompareBars
Strength Thresholdfloat1.0volumeStrengthThreshold
Apply to CHoCHbooltrueapplyFilterToChoch
Apply to BOSbooltrueapplyFilterToBos
Show Weak CHoCHbooltrueshowWeakChoch
Show all 40 settings
SettingTypeDefaultVariable
Show Weak BOSbooltrueshowWeakBos
Active Colorcolorcolor.rgb(244,67,54)swingHighActiveColor
Widthint1swingHighActiveWidth
StylestringsolidswingHighActiveStyle
Strong Colorcolorcolor. rgb(0,255,0)swingHighBrokenStrongColor
Widthint2swingHighBrokenStrongWidth
StylestringsolidswingHighBrokenStrongStyle
Weak Colorcolorcolor. rgb(100,100,100)swingHighBrokenWeakColor
Widthint1swingHighBrokenWeakWidth
StylestringdottedswingHighBrokenWeakStyle
Touched Colorcolorcolor.rgb(255,193,7)swingHighTouchedColor
Widthint1swingHighTouchedWidth
Active Colorcolorcolor.rgb(76,175,80)swingLowActiveColor
Widthint1swingLowActiveWidth
StylestringsolidswingLowActiveStyle
Strong Colorcolorcolor.rgb(255,0,0)swingLowBrokenStrongColor
StylestringsolidswingLowBrokenStrongStyle
Weak Colorcolorcolor.rgb(100,100,100)swingLowBrokenWeakColor
StylestringdottedswingLowBrokenWeakStyle
Touched Colorcolorcolor. rgb(255,193,7)swingLowTouchedColor
Widthint1swingLowTouchedWidth
StylestringdashedswingLowTouchedStyle
Show CHoCH LabelsbooltrueshowChochLabels
Up Strongcolorcolor.rgb(0,255,255)chochUpStrongColor
Up Weakcolorcolor.rgb(0,120,120)chochUpWeakColor
Down Strongcolorcolor.rgb(255,165,0)chochDownStrongColor
Down Weakcolorcolor.rgb(150,100,0)chochDownWeakColor
Label SizestringsmallchochLabelSizeStr
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

Moon Dev GEX Sweep & CVD

by moondevonyt
92 stars

The indicator detects liquidity sweeps across key price levels and calculates a cumulative volume delta proxy. It uses pivot high and low lookbacks to identify swing points, marking sweeps when price breaks beyond a level and quickly closes back inside. Featur

Indicator v5 Support & resistanceSMC / ICT / price action
Updated 2 months ago · Custom licence GitHub repository of Moon Dev GEX Sweep & CVD

Calculates higher-timeframe volume profiles to identify Value Area High (VAH), Value Area Low (VAL), and Point of Control (POC) levels directly on the price chart. It flags potential reversal setups and Change in State of Delivery (CISD) patterns relative to v

Indicator v6 VolumeSupport & resistance
Updated 2 months ago · None stated GitHub repository of CandelaCharts - Value Area Reversals

Copilot

by milocaetano
48 stars

Copilot is an order flow range-reversal indicator designed to overlay trading setups directly on the price chart. It evaluates four criteria: market context (sideways vs trending regime based on ATR height), structure (double top or double bottom retests), abs

Indicator v5 SMC / ICT / price actionSupport & resistance
Updated 2 days ago · MIT GitHub repository of Copilot

Supply and Demand Visible Range identifies supply, demand, and equilibrium zones across the visible chart range. It accumulates high, low, and volume data starting from the leftmost visible bar, optionally requesting lower timeframe intrabar data for finer res

Indicator v5 Support & resistanceVolume Repaints
Updated 2 months ago · AGPL-3.0 GitHub repository of Supply and Demand Visible Range [LuxAlgo]
13 stars

This script identifies and visualizes bullish and bearish order blocks on the price chart. It detects low-volatility consolidation ranges followed by breakout moves accompanied by high trading volume. Users can select between Simple, Relative, or Weighted volu

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 6 months ago · MIT GitHub repository of Advanced Order Blocks with Volume

This indicator identifies and visualizes key support and resistance heatmap zones directly on the price chart. Using closed one-hour price data, it evaluates multi-scale pivots, liquidity clusters, relative volume, and round-number resonances to score structur

Indicator v6 Support & resistanceSMC / ICT / price action
Updated 7 weeks ago · MIT GitHub repository of 加密货币1小时关键价位热力图 V2

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