Indicator · Pine Script v6 · On the chart

Delta Break and Retest Stage 2 POI Extraction

by rosijay17-cmd

An indicator that builds a delta profile for each session and extracts points of interest from it at session close: the delta point of control, positive and negative delta extremes, a delta flip level and an absorption node.

View on GitHub

GitHub stars1on the repository
Pine versionv6current
Lines of code440
Settings18inputs
LicenceGPL-3.0
Last update7 days ago22 Oct 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

440 lines of Pine Script v6 from delta_break_retest/Stage2_POIExtraction.pine, published under GPL-3.0. Keep the author's credit and licence lines when you reuse it.

Stage2_POIExtraction.pine
//@version=6

// ============================================================================
// DELTA BREAK & RETEST -- STAGE 2: POI EXTRACTION
// ----------------------------------------------------------------------------
// Per the build spec (Section 9), Stage 2: "Delta profile + POI extraction.
// Plot POI zones. No trading logic yet. Eyeball 10 sessions: do the levels
// land where price actually reacts?"
//
// Builds on Stage 1 (delta engine + price-binned session profile, carried
// forward unchanged) and adds POI extraction per Section 3 of the spec:
//   - Delta POC        (row with max |net delta|)
//   - Delta Extreme +  (most positive net-delta row -- session buy initiative)
//   - Delta Extreme -  (most negative net-delta row -- session sell initiative)
//   - Delta Flip Level (price where cumulative delta-by-price changes sign)
//   - Absorption Node  (high |delta| relative to price range traversed --
//                        the passive side ate aggression without giving up
//                        ground)
// Each POI extracted at session close, turned into a ZONE (price +/- 0.25 x
// ATR(14) on 15m, per spec), then tracked with the hygiene rules from
// Section 3: contamination counter (>=3 crossings retires it), freshness
// expiry (default 2 sessions untested), minimum-separation merge, and a
// capped active set (default 6).
//
// A prior session's still-untouched Delta POC naturally becomes the spec's
// "Untested Naked Level" simply by surviving to a later session still
// tested=false -- no separate extraction step needed, it's a STATUS a POC
// POI can carry, flagged as such once it's outlived its own session.
//
// STILL NO TRADING LOGIC -- indicator only. No break detection, no retest,
// no triggers, no orders. Those are Stages 4-7.
//
// SCOPE DISCIPLINE (Section 0) unchanged: f_delta() is the only thing ever
// inherited from the old script. All POI/zone/registry code below is
// written fresh for this rebuild.
//
// KNOWN RISK: this stage introduces Pine v6 user-defined types and an array
// of object references (the POI registry) -- meaningfully more syntactic
// surface area than the simple scalar diagnostics used so far, and I have
// no live Pine compiler to verify it against. Flagging that plainly rather
// than presenting it with the same confidence as Stage 1's simpler code --
// if it throws a compile error, send the exact message and I'll fix it
// directly rather than guess again.
// ============================================================================

indicator(title = "Delta Break & Retest - Stage 2 POI Extraction", shorttitle = "DBR Stage2", overlay = true, max_boxes_count = 200, max_labels_count = 200)

// ============================================================================
// PURE DELTA FUNCTION (unchanged from Stage 1 / the original port)
// ============================================================================

f_delta(float o, float h, float l, float c, float v) =>
    float safeRange = math.max(h - l, syminfo.mintick)
    float pressure = math.max(math.min((c - o) / safeRange, 1.0), -1.0)
    v * pressure

float barDelta = f_delta(open, high, low, close, nz(volume, 0.0))

// ============================================================================
// INPUTS
// ============================================================================

int profileRowsInput = input.int(40, "Profile Rows", minval = 10, maxval = 120, group = "Delta Profile")
int histogramOffsetInput = input.int(6, "Histogram Offset (Bars)", minval = 1, maxval = 60, group = "Delta Profile")
int histogramWidthInput = input.int(30, "Histogram Max Width (Bars)", minval = 5, maxval = 100, group = "Delta Profile")
color positiveDeltaColorInput = input.color(color.teal, "Positive Delta Color", group = "Delta Profile")
color negativeDeltaColorInput = input.color(color.orange, "Negative Delta Color", group = "Delta Profile")
bool showLiveProfileInput = input.bool(true, "Show Live In-Session Profile", group = "Delta Profile")

string poiAtrTimeframeInput = input.timeframe("15", "POI Zone ATR Timeframe", group = "POI Extraction", tooltip = "Per spec: zone half-width is 0.25 x ATR(14) on 15m by default.")
float poiAtrMultInput = input.float(0.25, "POI Zone Half-Width (x ATR)", minval = 0.05, maxval = 2.0, step = 0.05, group = "POI Extraction")
int contaminationThresholdInput = input.int(3, "Contamination Threshold (Crossings)", minval = 1, maxval = 10, group = "POI Extraction", tooltip = "A POI is retired once price has crossed into its zone this many separate times.")
int poiFreshnessSessionsInput = input.int(2, "POI Freshness (Sessions Untested)", minval = 1, maxval = 10, group = "POI Extraction")
float minSeparationAtrMultInput = input.float(0.5, "Minimum POI Separation (x ATR)", minval = 0.1, maxval = 3.0, step = 0.1, group = "POI Extraction")
int maxActivePoisInput = input.int(6, "Max Active POIs", minval = 1, maxval = 10, group = "POI Extraction")
bool showAbsorptionInput = input.bool(true, "Extract Absorption Node", group = "POI Extraction")
int minEndedSessionBarsInput = input.int(10, "Minimum Bars To Finalize A Session", minval = 3, maxval = 100, group = "POI Extraction", tooltip = "Safety floor -- a degenerate near-empty session (holiday, data gap) below this many bars is skipped rather than extracting garbage POIs from it.")

color pocColorInput = input.color(color.aqua, "Delta POC Color", group = "POI Colors")
color extremeColorInput = input.color(color.fuchsia, "Delta Extreme Color", group = "POI Colors")
color flipColorInput = input.color(color.yellow, "Delta Flip Color", group = "POI Colors")
color absorptionColorInput = input.color(color.silver, "Absorption Node Color", group = "POI Colors")

// ============================================================================
// 15m ATR (zone sizing only -- not a trade signal, so the standard
// non-repainting request.security call is sufficient here; a formal
// no-repaint check is explicit work in Stage 4's MTF bias stack, not
// skipped, just not duplicated here)
// ============================================================================

float atr15 = request.security(syminfo.tickerid, poiAtrTimeframeInput, ta.atr(14), lookahead = barmerge.lookahead_off)

// ============================================================================
// SESSION TRACKING
// ============================================================================

bool newSession = ta.change(time("D")) != 0

var int sessionStartBar = bar_index
var int sessionIndex = 0

int barsIntoSession = bar_index - sessionStartBar + 1

var float cumulativeDelta = 0.0

if newSession
    cumulativeDelta := 0.0

cumulativeDelta := cumulativeDelta + barDelta

// ============================================================================
// POI TYPE
// ============================================================================

type Poi
    float price
    float zoneLow
    float zoneHigh
    string poiType
    int createdBar
    int createdSessionIndex
    int crossCount = 0
    bool contaminated = false
    bool tested = false
    bool touchedLastBar = false
    box zoneBox = na
    label zoneLabel = na

var array<Poi> poiRegistry = array.new<Poi>()

// ============================================================================
// SESSION PROFILE EXTRACTION (called once, at the close of each session)
//-----------------------------------------------------------------------------
// barsBack = number of bars in the just-ended session, referenced via [1]..
// [barsBack] since this runs on the FIRST bar of the NEW session (bar_index
// itself is the new session's first bar, "yesterday" starts at offset 1).
// Returns [pocPrice, extremeHighPrice, extremeLowPrice, flipPrice,
// absorptionPrice].
// ============================================================================

f_extractSessionPois(int barsBack, int rows) =>
    float scanHigh = -1.0e20
    float scanLow = 1.0e20

    for i = 1 to barsBack
        scanHigh := math.max(scanHigh, high[i])
        scanLow := math.min(scanLow, low[i])

    float rowStep = math.max((scanHigh - scanLow) / rows, syminfo.mintick)

    array<float> rowDelta = array.new_float(rows, 0.0)
    array<float> rowRange = array.new_float(rows, 0.0)
    array<float> rowVolume = array.new_float(rows, 0.0)

    for i = 1 to barsBack
        float d = f_delta(open[i], high[i], low[i], close[i], nz(volume[i], 0.0))
        int row = int(math.floor((close[i] - scanLow) / rowStep))
        row := math.max(0, math.min(rows - 1, row))
        array.set(rowDelta, row, array.get(rowDelta, row) + d)
        array.set(rowRange, row, array.get(rowRange, row) + (high[i] - low[i]))
        array.set(rowVolume, row, array.get(rowVolume, row) + nz(volume[i], 0.0))

    float maxAbs = -1.0
    int pocRow = -1

    for row = 0 to rows - 1
        float d = array.get(rowDelta, row)
        if math.abs(d) > maxAbs
            maxAbs := math.abs(d)
            pocRow := row

    float pocPrice = pocRow >= 0 ? scanLow + (pocRow + 0.5) * rowStep : na

    float maxPos = 0.0
    int maxPosRow = -1
    float maxNeg = 0.0
    int maxNegRow = -1

    for row = 0 to rows - 1
        float d = array.get(rowDelta, row)
        if d > maxPos
            maxPos := d
            maxPosRow := row
        if d < maxNeg
            maxNeg := d
            maxNegRow := row

    float extremeHighPrice = maxPosRow >= 0 ? scanLow + (maxPosRow + 0.5) * rowStep : na
    float extremeLowPrice = maxNegRow >= 0 ? scanLow + (maxNegRow + 0.5) * rowStep : na

    float cum = 0.0
    float prevCum = 0.0
    float flipPrice = na

    for row = 0 to rows - 1
        prevCum := cum
        cum := cum + array.get(rowDelta, row)
        if row > 0 and ((prevCum <= 0 and cum > 0) or (prevCum >= 0 and cum < 0))
            flipPrice := scanLow + row * rowStep

    float totalVol = 0.0
    for row = 0 to rows - 1
        totalVol += array.get(rowVolume, row)
    float avgVol = totalVol / rows

    float bestRatio = -1.0
    int absorptionRow = -1

    for row = 0 to rows - 1
        if row != pocRow and array.get(rowVolume, row) > avgVol * 0.5
            float rng = array.get(rowRange, row)
            float ratio = rng > 0 ? math.abs(array.get(rowDelta, row)) / rng : 0.0
            if ratio > bestRatio
                bestRatio := ratio
                absorptionRow := row

    float absorptionPrice = absorptionRow >= 0 ? scanLow + (absorptionRow + 0.5) * rowStep : na

    [pocPrice, extremeHighPrice, extremeLowPrice, flipPrice, absorptionPrice]

// ============================================================================
// POI REGISTRY: cleanup (contaminated / expired-untested) and add-with-hygiene
// ============================================================================

f_cleanupPois(array<Poi> registry, int currentSessionIndex, int freshnessSessions) =>
    int i = array.size(registry) - 1
    while i >= 0
        Poi p = array.get(registry, i)
        bool expired = not p.tested and (currentSessionIndex - p.createdSessionIndex) >= freshnessSessions
        if p.contaminated or expired
            if not na(p.zoneBox)
                box.delete(p.zoneBox)
            if not na(p.zoneLabel)
                label.delete(p.zoneLabel)
            array.remove(registry, i)
        i -= 1

// If the registry is full, evict the oldest TESTED entry to make room --
// a POI that got tested once, long ago, and never crossed again (so it
// never contaminates) would otherwise occupy its slot forever once
// "tested" takes it out of freshness-expiry eligibility. Untested/naked
// levels are deliberately protected from eviction (the spec calls them
// out as the cleanest, most valuable POI type) unless literally every
// active slot is naked, in which case the oldest naked one goes instead
// of refusing the new POI outright. A capped set that never rotates
// isn't a watchlist, it's a monument.
f_evictOldestForRoom(array<Poi> registry) =>
    int evictIdx = -1
    int oldestTestedSession = 999999
    int oldestAnySession = 999999
    int oldestAnyIdx = -1

    if array.size(registry) > 0
        for i = 0 to array.size(registry) - 1
            Poi existing = array.get(registry, i)
            if existing.createdSessionIndex < oldestAnySession
                oldestAnySession := existing.createdSessionIndex
                oldestAnyIdx := i
            if existing.tested and existing.createdSessionIndex < oldestTestedSession
                oldestTestedSession := existing.createdSessionIndex
                evictIdx := i

    if evictIdx < 0
        evictIdx := oldestAnyIdx

    if evictIdx >= 0
        Poi evicted = array.get(registry, evictIdx)
        if not na(evicted.zoneBox)
            box.delete(evicted.zoneBox)
        if not na(evicted.zoneLabel)
            label.delete(evicted.zoneLabel)
        array.remove(registry, evictIdx)

f_tryAddPoi(array<Poi> registry, float price, string poiType, color poiColor, float atrVal, float zoneMult, float minSepMult, int maxActive, int sessIdx) =>
    bool added = false
    if not na(price) and not na(atrVal) and atrVal > 0
        float halfWidth = atrVal * zoneMult
        float zLow = price - halfWidth
        float zHigh = price + halfWidth

        bool tooClose = false
        if array.size(registry) > 0
            for i = 0 to array.size(registry) - 1
                Poi existing = array.get(registry, i)
                if not existing.contaminated and math.abs(existing.price - price) < atrVal * minSepMult
                    tooClose := true

        if not tooClose
            if array.size(registry) >= maxActive
                f_evictOldestForRoom(registry)

        if not tooClose and array.size(registry) < maxActive
            Poi newPoi = Poi.new(price = price, zoneLow = zLow, zoneHigh = zHigh, poiType = poiType, createdBar = bar_index, createdSessionIndex = sessIdx)
            newPoi.zoneBox := box.new(left = bar_index, top = zHigh, right = bar_index, bottom = zLow, xloc = xloc.bar_index, bgcolor = color.new(poiColor, 85), border_color = poiColor)
            newPoi.zoneLabel := label.new(bar_index, zHigh, poiType, style = label.style_label_down, color = color.new(poiColor, 20), textcolor = color.white, size = size.tiny)
            array.push(registry, newPoi)
            added := true
    added

// ============================================================================
// SESSION CLOSE: finalize the ended session's profile, extract POIs
// ============================================================================

if newSession
    if bar_index > 0 and barsIntoSession > 1
        int endedBars = bar_index - sessionStartBar
        if endedBars >= minEndedSessionBarsInput and not na(atr15)
            [pocPx, exHighPx, exLowPx, flipPx, absPx] = f_extractSessionPois(endedBars, profileRowsInput)

            f_cleanupPois(poiRegistry, sessionIndex, poiFreshnessSessionsInput)

            f_tryAddPoi(poiRegistry, pocPx, "Delta POC", pocColorInput, atr15, poiAtrMultInput, minSeparationAtrMultInput, maxActivePoisInput, sessionIndex)
            f_tryAddPoi(poiRegistry, exHighPx, "Delta Extreme +", extremeColorInput, atr15, poiAtrMultInput, minSeparationAtrMultInput, maxActivePoisInput, sessionIndex)
            f_tryAddPoi(poiRegistry, exLowPx, "Delta Extreme -", extremeColorInput, atr15, poiAtrMultInput, minSeparationAtrMultInput, maxActivePoisInput, sessionIndex)
            f_tryAddPoi(poiRegistry, flipPx, "Delta Flip", flipColorInput, atr15, poiAtrMultInput, minSeparationAtrMultInput, maxActivePoisInput, sessionIndex)
            if showAbsorptionInput
                f_tryAddPoi(poiRegistry, absPx, "Absorption Node", absorptionColorInput, atr15, poiAtrMultInput, minSeparationAtrMultInput, maxActivePoisInput, sessionIndex)

    sessionIndex += 1
    sessionStartBar := bar_index

// ============================================================================
// EVERY BAR: update contamination / tested status, extend active zone boxes
// ============================================================================

if array.size(poiRegistry) > 0
    for i = 0 to array.size(poiRegistry) - 1
        Poi p = array.get(poiRegistry, i)

        if not p.contaminated
            bool touchedNow = high >= p.zoneLow and low <= p.zoneHigh

            if touchedNow and not p.touchedLastBar
                if not p.tested
                    p.tested := true
                p.crossCount := p.crossCount + 1
                if p.crossCount >= contaminationThresholdInput
                    p.contaminated := true

            p.touchedLastBar := touchedNow

            if not na(p.zoneBox)
                box.set_right(p.zoneBox, bar_index)

            if p.contaminated and not na(p.zoneBox)
                box.set_bgcolor(p.zoneBox, color.new(color.gray, 92))
                box.set_border_color(p.zoneBox, color.new(color.gray, 60))

// ============================================================================
// LIVE IN-SESSION PROFILE (Stage 1, carried forward unchanged, optional)
// ============================================================================

var array<box> profileBoxes = array.new_box()

if showLiveProfileInput and barstate.islast

    if array.size(profileBoxes) > 0
        for i = 0 to array.size(profileBoxes) - 1
            box.delete(array.get(profileBoxes, i))
    array.clear(profileBoxes)

    float scanHigh2 = -1.0e20
    float scanLow2 = 1.0e20
    int scanBars2 = math.min(barsIntoSession, 2000)

    for i = 0 to scanBars2 - 1
        scanHigh2 := math.max(scanHigh2, high[i])
        scanLow2 := math.min(scanLow2, low[i])

    float rowStep2 = math.max((scanHigh2 - scanLow2) / profileRowsInput, syminfo.mintick)

    array<float> rowDelta2 = array.new_float(profileRowsInput, 0.0)

    for i = 0 to scanBars2 - 1
        float d2 = f_delta(open[i], high[i], low[i], close[i], nz(volume[i], 0.0))
        int row2 = int(math.floor((close[i] - scanLow2) / rowStep2))
        row2 := math.max(0, math.min(profileRowsInput - 1, row2))
        array.set(rowDelta2, row2, array.get(rowDelta2, row2) + d2)

    float maxAbs2 = 0.0
    for row2 = 0 to profileRowsInput - 1
        maxAbs2 := math.max(maxAbs2, math.abs(array.get(rowDelta2, row2)))

    int centerX2 = bar_index + histogramOffsetInput

    for row2 = 0 to profileRowsInput - 1
        float d2 = array.get(rowDelta2, row2)
        if d2 != 0
            float rowLow2 = scanLow2 + row2 * rowStep2
            float rowHigh2 = rowLow2 + rowStep2
            int barWidth2 = maxAbs2 > 0 ? int(math.round(histogramWidthInput * math.abs(d2) / maxAbs2)) : 0
            if barWidth2 > 0
                color barColor2 = d2 >= 0 ? positiveDeltaColorInput : negativeDeltaColorInput
                box rowBox2 = box.new(left = centerX2, top = rowHigh2, right = centerX2 + barWidth2, bottom = rowLow2, xloc = xloc.bar_index, bgcolor = color.new(barColor2, 15), border_color = color.new(barColor2, 40))
                array.push(profileBoxes, rowBox2)

// ============================================================================
// DASHBOARD
// ============================================================================

var table statusTable = table.new(position.top_right, 2, 16, bgcolor = color.new(color.rgb(15, 20, 27), 10), border_width = 1)

if barstate.islast
    table.cell(statusTable, 0, 0, "STAGE 2 POI EXTRACTION", text_color = color.white, bgcolor = color.rgb(22, 52, 86))
    table.cell(statusTable, 1, 0, "", text_color = color.white, bgcolor = color.rgb(22, 52, 86))

    table.cell(statusTable, 0, 1, "Session Index", text_color = color.white)
    table.cell(statusTable, 1, 1, str.tostring(sessionIndex), text_color = color.white)

    table.cell(statusTable, 0, 2, "ATR(14) on " + poiAtrTimeframeInput, text_color = color.white)
    table.cell(statusTable, 1, 2, str.tostring(atr15, format.mintick), text_color = color.white)

    table.cell(statusTable, 0, 3, "Active POIs", text_color = color.white)
    table.cell(statusTable, 1, 3, str.tostring(array.size(poiRegistry)) + " / " + str.tostring(maxActivePoisInput), text_color = color.white)

    table.cell(statusTable, 0, 4, "Session Net Delta", text_color = color.white)
    table.cell(statusTable, 1, 4, str.tostring(cumulativeDelta, "#"), text_color = cumulativeDelta >= 0 ? positiveDeltaColorInput : negativeDeltaColorInput)

    int listRowStart = 5
    int maxListRows = 10

    for r = 0 to maxListRows - 1
        int tableRow = listRowStart + r
        if r < array.size(poiRegistry)
            Poi p = array.get(poiRegistry, r)
            string statusText = p.contaminated ? "DEAD" : (not p.tested and (sessionIndex - p.createdSessionIndex) >= 1 ? "NAKED" : (p.tested ? "TESTED" : "FRESH"))
            table.cell(statusTable, 0, tableRow, p.poiType, text_color = color.white)
            table.cell(statusTable, 1, tableRow, str.tostring(p.price, format.mintick) + " " + statusText + " x" + str.tostring(p.crossCount), text_color = p.contaminated ? color.gray : color.white)
        else
            table.cell(statusTable, 0, tableRow, "", text_color = color.white)
            table.cell(statusTable, 1, tableRow, "", text_color = color.white)

// ============================================================================
// DATA WINDOW
// ============================================================================

plot(barDelta, title = "Per-Bar Delta", display = display.data_window)
plot(cumulativeDelta, title = "Cumulative Session Delta", display = display.data_window)
plot(atr15, title = "ATR(14) on POI Timeframe", display = display.data_window)
plot(array.size(poiRegistry), title = "Active POI Count", display = display.data_window)

Overview

Each becomes a zone sized by a fraction of the 15-minute ATR. Zones are retired after repeated crossings or when untested for set sessions, merged when close together and capped in number. It has no trading logic.

Details

Published by

rosijay17-cmd on GitHub

Type

Indicator, Pine Script v6

Draws

On the price chart

Category

Volume, Support & resistance

Markets

Any symbol

Timeframes

M15-H1

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
Profile Rowsint40profileRowsInput
Histogram Offset (Bars)int6histogramOffsetInput
Histogram Max Width (Bars)int30histogramWidthInput
Positive Delta Colorcolorcolor.tealpositiveDeltaColorInput
Negative Delta Colorcolorcolor.orangenegativeDeltaColorInput
Show Live In-Session ProfilebooltrueshowLiveProfileInput
POI Zone ATR Timeframetimeframe15poiAtrTimeframeInput
POI Zone Half-Width (x ATR)float0.25poiAtrMultInput
Contamination Threshold (Crossings)int3contaminationThresholdInput
POI Freshness (Sessions Untested)int2poiFreshnessSessionsInput
Minimum POI Separation (x ATR)float0.5minSeparationAtrMultInput
Max Active POIsint6maxActivePoisInput
Show all 18 settings
SettingTypeDefaultVariable
Extract Absorption NodebooltrueshowAbsorptionInput
Minimum Bars To Finalize A Sessionint10minEndedSessionBarsInput
Delta POC Colorcolorcolor.aquapocColorInput
Delta Extreme Colorcolorcolor.fuchsiaextremeColorInput
Delta Flip Colorcolorcolor.yellowflipColorInput
Absorption Node Colorcolorcolor.silverabsorptionColorInput
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

This overlay indicator draws a fixed-range volume profile on the price chart, splitting traded activity into up and down volume at each price level. It also plots a sentiment profile, a developing point of control, and value-area high and low around a configur

Indicator v5 VolumeSupport & resistance
Updated 2 months ago · MIT GitHub repository of Volume Profile and Indicator by DGT

MGIC-tracker

by Allen1212
303 stars

The MGIC-tracker is a TradingView indicator that overlays ARK Invest trade records onto stock price charts. It plots buy and sell labels at the exact timestamp of each transaction, showing share volume and ETF weight. Users select a specific ETF type via setti

Indicator v4 Support & resistanceVolume
Updated 2 years ago · None stated GitHub repository of MGIC-tracker
218 stars

Comprehensive Volume Profile is an overlay indicator that calculates and plots volume distribution across specified time ranges such as daily sessions, weekly, monthly, or custom bar lengths. It identifies key structural price levels including the Point of Con

Indicator v6 VolumeSupport & resistance
Updated 3 months ago · None stated GitHub repository of Comprehensive Volume Profile

Moon Dev GEX Arrows

by moondevonyt
92 stars

This overlay indicator plots option strike walls and an optional session VWAP on the price chart for SPY or ES. It spaces major strikes by the selected instrument, draws a set number of strikes on each side, and marks wall-trap and sweep events after a cooldow

Indicator v5 Support & resistanceSessions & time
Updated 2 months ago · Custom licence GitHub repository of Moon Dev GEX Arrows

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