OPEN-SOURCE SCRIPT
Volume + RVOL + Directional Delta [Clean]

# Volume + RVOL + Directional Delta [Clean]
## What this is
A volume pane with three layers: raw volume colored by relative volume, a
signed Directional Delta histogram, and a dashboard that reports **how each
number was actually produced**.
The third layer is the point. Relative volume and volume delta both depend on
data that is not always available, and most implementations substitute a
different measurement when the real one is missing — without saying so. This
indicator computes the same things everyone else computes, then tells you when
what you are looking at is not what the label claims.
Every fallback in the script is visible in the dashboard. There are no silent
substitutions.
---
## The problem it addresses
Two silent substitutions happen constantly in volume tooling.
**1. Time-of-day RVOL that isn't.** Comparing a bar to prior bars at the same
clock time is the right way to do intraday RVOL — 9:30 volume and 2:00 volume
are not the same population. But it only works if session bars land on
consistent clock times. On a 65-minute regular-hours chart there are six bars
per session and the opens repeat cleanly. Turn on extended hours and the
session runs about 14.8 bars, the opens drift, and the same-time search returns
almost nothing. Most scripts fall back to a rolling average at that point and
keep displaying the number as though nothing changed.
**2. Volume delta that is really just bar direction.** Estimating delta
requires summing signed intrabar volume from a lower timeframe. TradingView's
intrabar budget is finite — at 65m/1m that is 65 intrabars per chart bar,
covering roughly a year of history before `request.security_lower_tf()` starts
returning empty arrays. The usual fallback is a chart-bar proxy: positive if
the bar closed up, negative if it closed down. That proxy can only ever return
exactly ±volume, i.e. ±100% delta. It is not a noisier version of intrabar
delta. It is a different measurement with a different range, and a single proxy
bar contributes the largest value any bar can contribute.
Both substitutions are reasonable as fallbacks. Neither is acceptable as a
silent one.
---
## Relative volume
**Baseline statistic.** Median by default rather than mean. The mean is dragged
upward by exactly the news-driven spikes RVOL exists to detect, which makes a
fixed threshold like 2.0x mean different things on different tickers and in
different regimes. The median keeps the threshold comparable across names.
**Time-of-day mode** walks backward collecting prior bars whose open lands on
the same hour and minute as the current bar, then takes the median of those.
The setting is a **target sample count, not a search window**. This matters
more than it sounds. A search-window setting produces a completely different
statistical baseline on every timeframe — 120 bars finds about 20 samples on
65m, 12 on 39m, and 4 on 15m. Asking for 20 comparable sessions instead means
20 sessions wherever they are reachable. A separate maximum search distance
bounds how far the scan may walk to find them.
Sizing guidance, on a 390-minute regular-hours session:
Chart TF Bars/session Search distance for 20 samples
10m 39 ~780
15m 26 ~520
39m 10 ~200
65m 6 ~120
78m 5 ~100
130m 3 ~60
195m 2 ~40
The default 1000-bar ceiling reaches 20 samples down through 10m. Some
combinations are simply unreachable — 20 sessions on a 1-minute chart would
need 7800 bars — and those degrade to the rolling baseline and say so.
**Attainment is a three-state result**, because once the setting means "20
sessions", clearing a bare minimum of 10 is not the same as meeting the
request:
MODE TOD target met — the baseline you configured
MODE TOD* minimum met, target missed — usable, but not what you asked
MODE ROLL* minimum missed — fell back to rolling entirely
The middle state keeps a useful 15-sample baseline rather than discarding it,
while refusing to report it as though 20 sessions had been achieved.
**Coloring.** Gray below the high threshold, green at high RVOL, gold at
extreme. Thresholds are configurable.
---
## Bar completion, and why nothing is projected
RVOL divides a **partial** current bar by a median of **completed** bars. It
therefore reads low at the start of a bar and climbs throughout. A 0.4x forty
minutes into a 65-minute bar is not the same statement as a 0.4x at the close.
This is deliberately not projected to a full-bar estimate. Intraday volume is
U-shaped, so scaling linearly by elapsed time overstates near the open and
understates into the close — and an extrapolated figure displayed to two
decimals invites more trust than it has earned. The honest fix is a baseline
built from the same elapsed *fraction* of prior same-time-of-day bars, which
requires intrabar history for every baseline bar and is a substantially larger
build.
So the indicator reports completion instead and lets you discount. The `BAR%`
cell turns amber below 95%, which is precisely when the RVOL cell beside it is
understated.
One caveat: this is wall-clock elapsed against nominal bar duration. A bar
truncated by a session boundary or a holiday early close reads below 100% even
at its close. In time-of-day mode such bars are compared against other bars at
the same clock time, so RVOL itself stays meaningful — only the completion
figure misreports.
---
## Directional Delta
Each lower-timeframe bar's entire volume is signed by that bar's own candle
direction, with dojis resolved against the prior close, and the signed values
are summed across the chart bar.
**It is called Directional Delta because that is what it is.** It is not
market-buy volume minus market-sell volume. No lower-timeframe reconstruction
can see bid/ask trade classification; it can only sign small bars by their
direction. That is genuinely useful information about intrabar pressure, and it
is not order flow, and the name should not imply otherwise.
**Cumulative Directional Delta uses real intrabar bars only.** Bars that fell
back to the proxy are excluded from the total rather than included and flagged.
This is worth explaining, because it drives the display. Proxy bars are not
scattered randomly through the window — the intrabar budget runs out going
*backward*, so they form the oldest contiguous block. Filtering therefore
produces a **shorter, more recent window**, not a cleaned full-length one. The
column header reports the real bar count for that reason:
57B DΔ +8.7M
57B DΔ% +12.6%
VALID 57/60
You asked for 60 bars and you are looking at a clean measurement over 57. With
zero valid bars both cells read `n/a` rather than a confident `+0`.
Cumulative delta % is total delta divided by total volume across those same
valid bars — not the average of per-bar percentages.
The lookback is left in bars rather than normalized to sessions, deliberately.
It means different amounts of market time on different charts — 60 bars is ten
sessions on 65m but 2.3 sessions on 15m — and the tooltip says so. Which span
you want is a judgment, not something the script should make for you.
---
## Dashboard reference
RVOL current bar volume / active baseline
BAR% bar completion; amber below 95%, when RVOL is understated
MODE TOD / TOD* / ROLL / ROLL*, plus "med" or "avg"
SAMP 20+ (target met with margin) / 20 (met exactly) / 15/20 (short)
BAR DΔ current bar Directional Delta
BAR DΔ% as a share of bar volume
nB DΔ cumulative over valid bars; header states how many
nB DΔ% cumulative delta / cumulative volume, same bars
VALID valid bars / requested bars
Δ TF intrabar timeframe in use, or why there isn't one
The `Δ TF` cell distinguishes four outcomes, because "no intrabar data" has
causes that call for different responses:
1 / 15S intrabar data genuinely in use
Chart* a valid lower timeframe was requested, no data came back
INVALID manual timeframe is not lower than the chart — fix the setting
Chart no lower timeframe exists at all (1-second chart)
`INVALID` exists because entering 65m as the delta timeframe on a 65m chart
used to display a calm white "Chart", identical to the legitimate case. Both
fall through to the proxy; only one is a mistake.
**Color convention.** Amber means one thing throughout: *the number is usable
but is not the measurement you asked for.* Red appears in exactly one place and
means *this setting cannot work as entered*. Keeping those separate is what
makes the pane readable at a glance.
---
## Settings guidance
- **65m regular hours:** defaults work as-is. About 120 bars of search finds
the 20-sample target.
- **15m and 10m:** also fine at the 1000-bar default, but the scan runs much
further. If the script becomes slow, turn off *Compute Time-of-Day Baseline
on History* — historical bar coloring then uses the rolling baseline while
the dashboard uses time-of-day, which is a real inconsistency and is why it
is a visible toggle rather than a silent optimization.
- **Extended-hours charts:** time-of-day will degrade to `ROLL*`. Session bar
opens do not repeat. Either switch to regular hours or accept the rolling
baseline knowingly.
- **Daily and above:** time-of-day is inapplicable and is bypassed.
- **Delta timeframe:** leave on automatic. It steps down correctly including on
1-minute charts. Sub-minute intrabar data requires a higher TradingView plan
tier; on a lower tier the request returns empty and `Δ TF` reports `Chart*`.
- **Below ~15 samples**, the median becomes sensitive to holiday early-close
sessions, whose truncated final bars carry structurally low volume.
---
## Alerts
Six conditions. High RVOL and Extreme RVOL are straightforward.
The two combined alerts — extreme volume with positive or negative Directional
Delta — **require real intrabar data**. On a proxy bar the delta sign is
nothing more than the candle body's direction, so an ungated version would fire
on "heavy volume, bar closed up" while appearing to describe something more.
Two ungated variants are provided separately and named for what they actually
test: *Extreme Volume + Up Bar* and *Extreme Volume + Down Bar*, each stating in
its own message that it does not test Directional Delta.
---
## What this is not
- It does not project or estimate finished bar volume.
- Directional Delta is not bid/ask trade classification and does not claim to be.
- It makes no directional claim, generates no entries, and has no backtest.
- The proxy fallback is not "close enough." It is excluded from cumulative
figures and labeled where it appears, so you can decide whether a number is
usable for what you are doing.
---
## Implementation notes
Both rolling statistics (`ta.sma` and `ta.median`) are evaluated
unconditionally and then selected, rather than being called inside a
conditional branch, which would produce an inconsistent series.
The sample scan probes for one more than the target, then discards it. That is
what makes `20+` truthful: it means a 21st match genuinely existed, not merely
that the loop stopped. A bare `20` means the target was met with no margin left
in the window, which is worth distinguishing.
The scan exits as soon as the target is met, so the search ceiling costs
nothing on timeframes that reach it — 65m stops near bar 126 regardless of the
setting. It is not free where the target is unreachable: the loop then runs the
full distance on every bar, which is what the history toggle is for.
`todActive` reflects what the code actually used, never what was requested. The
dashboard reads that flag rather than the input, which is what prevents MODE
from displaying `TOD` while a rolling baseline is in use.
The compact number formatter uses `"#0"` rather than `"#"` for sub-thousand
values — a bare `"#"` drops the digit on sub-1 values and renders a lone minus
sign.
Open source.
## What this is
A volume pane with three layers: raw volume colored by relative volume, a
signed Directional Delta histogram, and a dashboard that reports **how each
number was actually produced**.
The third layer is the point. Relative volume and volume delta both depend on
data that is not always available, and most implementations substitute a
different measurement when the real one is missing — without saying so. This
indicator computes the same things everyone else computes, then tells you when
what you are looking at is not what the label claims.
Every fallback in the script is visible in the dashboard. There are no silent
substitutions.
---
## The problem it addresses
Two silent substitutions happen constantly in volume tooling.
**1. Time-of-day RVOL that isn't.** Comparing a bar to prior bars at the same
clock time is the right way to do intraday RVOL — 9:30 volume and 2:00 volume
are not the same population. But it only works if session bars land on
consistent clock times. On a 65-minute regular-hours chart there are six bars
per session and the opens repeat cleanly. Turn on extended hours and the
session runs about 14.8 bars, the opens drift, and the same-time search returns
almost nothing. Most scripts fall back to a rolling average at that point and
keep displaying the number as though nothing changed.
**2. Volume delta that is really just bar direction.** Estimating delta
requires summing signed intrabar volume from a lower timeframe. TradingView's
intrabar budget is finite — at 65m/1m that is 65 intrabars per chart bar,
covering roughly a year of history before `request.security_lower_tf()` starts
returning empty arrays. The usual fallback is a chart-bar proxy: positive if
the bar closed up, negative if it closed down. That proxy can only ever return
exactly ±volume, i.e. ±100% delta. It is not a noisier version of intrabar
delta. It is a different measurement with a different range, and a single proxy
bar contributes the largest value any bar can contribute.
Both substitutions are reasonable as fallbacks. Neither is acceptable as a
silent one.
---
## Relative volume
**Baseline statistic.** Median by default rather than mean. The mean is dragged
upward by exactly the news-driven spikes RVOL exists to detect, which makes a
fixed threshold like 2.0x mean different things on different tickers and in
different regimes. The median keeps the threshold comparable across names.
**Time-of-day mode** walks backward collecting prior bars whose open lands on
the same hour and minute as the current bar, then takes the median of those.
The setting is a **target sample count, not a search window**. This matters
more than it sounds. A search-window setting produces a completely different
statistical baseline on every timeframe — 120 bars finds about 20 samples on
65m, 12 on 39m, and 4 on 15m. Asking for 20 comparable sessions instead means
20 sessions wherever they are reachable. A separate maximum search distance
bounds how far the scan may walk to find them.
Sizing guidance, on a 390-minute regular-hours session:
Chart TF Bars/session Search distance for 20 samples
10m 39 ~780
15m 26 ~520
39m 10 ~200
65m 6 ~120
78m 5 ~100
130m 3 ~60
195m 2 ~40
The default 1000-bar ceiling reaches 20 samples down through 10m. Some
combinations are simply unreachable — 20 sessions on a 1-minute chart would
need 7800 bars — and those degrade to the rolling baseline and say so.
**Attainment is a three-state result**, because once the setting means "20
sessions", clearing a bare minimum of 10 is not the same as meeting the
request:
MODE TOD target met — the baseline you configured
MODE TOD* minimum met, target missed — usable, but not what you asked
MODE ROLL* minimum missed — fell back to rolling entirely
The middle state keeps a useful 15-sample baseline rather than discarding it,
while refusing to report it as though 20 sessions had been achieved.
**Coloring.** Gray below the high threshold, green at high RVOL, gold at
extreme. Thresholds are configurable.
---
## Bar completion, and why nothing is projected
RVOL divides a **partial** current bar by a median of **completed** bars. It
therefore reads low at the start of a bar and climbs throughout. A 0.4x forty
minutes into a 65-minute bar is not the same statement as a 0.4x at the close.
This is deliberately not projected to a full-bar estimate. Intraday volume is
U-shaped, so scaling linearly by elapsed time overstates near the open and
understates into the close — and an extrapolated figure displayed to two
decimals invites more trust than it has earned. The honest fix is a baseline
built from the same elapsed *fraction* of prior same-time-of-day bars, which
requires intrabar history for every baseline bar and is a substantially larger
build.
So the indicator reports completion instead and lets you discount. The `BAR%`
cell turns amber below 95%, which is precisely when the RVOL cell beside it is
understated.
One caveat: this is wall-clock elapsed against nominal bar duration. A bar
truncated by a session boundary or a holiday early close reads below 100% even
at its close. In time-of-day mode such bars are compared against other bars at
the same clock time, so RVOL itself stays meaningful — only the completion
figure misreports.
---
## Directional Delta
Each lower-timeframe bar's entire volume is signed by that bar's own candle
direction, with dojis resolved against the prior close, and the signed values
are summed across the chart bar.
**It is called Directional Delta because that is what it is.** It is not
market-buy volume minus market-sell volume. No lower-timeframe reconstruction
can see bid/ask trade classification; it can only sign small bars by their
direction. That is genuinely useful information about intrabar pressure, and it
is not order flow, and the name should not imply otherwise.
**Cumulative Directional Delta uses real intrabar bars only.** Bars that fell
back to the proxy are excluded from the total rather than included and flagged.
This is worth explaining, because it drives the display. Proxy bars are not
scattered randomly through the window — the intrabar budget runs out going
*backward*, so they form the oldest contiguous block. Filtering therefore
produces a **shorter, more recent window**, not a cleaned full-length one. The
column header reports the real bar count for that reason:
57B DΔ +8.7M
57B DΔ% +12.6%
VALID 57/60
You asked for 60 bars and you are looking at a clean measurement over 57. With
zero valid bars both cells read `n/a` rather than a confident `+0`.
Cumulative delta % is total delta divided by total volume across those same
valid bars — not the average of per-bar percentages.
The lookback is left in bars rather than normalized to sessions, deliberately.
It means different amounts of market time on different charts — 60 bars is ten
sessions on 65m but 2.3 sessions on 15m — and the tooltip says so. Which span
you want is a judgment, not something the script should make for you.
---
## Dashboard reference
RVOL current bar volume / active baseline
BAR% bar completion; amber below 95%, when RVOL is understated
MODE TOD / TOD* / ROLL / ROLL*, plus "med" or "avg"
SAMP 20+ (target met with margin) / 20 (met exactly) / 15/20 (short)
BAR DΔ current bar Directional Delta
BAR DΔ% as a share of bar volume
nB DΔ cumulative over valid bars; header states how many
nB DΔ% cumulative delta / cumulative volume, same bars
VALID valid bars / requested bars
Δ TF intrabar timeframe in use, or why there isn't one
The `Δ TF` cell distinguishes four outcomes, because "no intrabar data" has
causes that call for different responses:
1 / 15S intrabar data genuinely in use
Chart* a valid lower timeframe was requested, no data came back
INVALID manual timeframe is not lower than the chart — fix the setting
Chart no lower timeframe exists at all (1-second chart)
`INVALID` exists because entering 65m as the delta timeframe on a 65m chart
used to display a calm white "Chart", identical to the legitimate case. Both
fall through to the proxy; only one is a mistake.
**Color convention.** Amber means one thing throughout: *the number is usable
but is not the measurement you asked for.* Red appears in exactly one place and
means *this setting cannot work as entered*. Keeping those separate is what
makes the pane readable at a glance.
---
## Settings guidance
- **65m regular hours:** defaults work as-is. About 120 bars of search finds
the 20-sample target.
- **15m and 10m:** also fine at the 1000-bar default, but the scan runs much
further. If the script becomes slow, turn off *Compute Time-of-Day Baseline
on History* — historical bar coloring then uses the rolling baseline while
the dashboard uses time-of-day, which is a real inconsistency and is why it
is a visible toggle rather than a silent optimization.
- **Extended-hours charts:** time-of-day will degrade to `ROLL*`. Session bar
opens do not repeat. Either switch to regular hours or accept the rolling
baseline knowingly.
- **Daily and above:** time-of-day is inapplicable and is bypassed.
- **Delta timeframe:** leave on automatic. It steps down correctly including on
1-minute charts. Sub-minute intrabar data requires a higher TradingView plan
tier; on a lower tier the request returns empty and `Δ TF` reports `Chart*`.
- **Below ~15 samples**, the median becomes sensitive to holiday early-close
sessions, whose truncated final bars carry structurally low volume.
---
## Alerts
Six conditions. High RVOL and Extreme RVOL are straightforward.
The two combined alerts — extreme volume with positive or negative Directional
Delta — **require real intrabar data**. On a proxy bar the delta sign is
nothing more than the candle body's direction, so an ungated version would fire
on "heavy volume, bar closed up" while appearing to describe something more.
Two ungated variants are provided separately and named for what they actually
test: *Extreme Volume + Up Bar* and *Extreme Volume + Down Bar*, each stating in
its own message that it does not test Directional Delta.
---
## What this is not
- It does not project or estimate finished bar volume.
- Directional Delta is not bid/ask trade classification and does not claim to be.
- It makes no directional claim, generates no entries, and has no backtest.
- The proxy fallback is not "close enough." It is excluded from cumulative
figures and labeled where it appears, so you can decide whether a number is
usable for what you are doing.
---
## Implementation notes
Both rolling statistics (`ta.sma` and `ta.median`) are evaluated
unconditionally and then selected, rather than being called inside a
conditional branch, which would produce an inconsistent series.
The sample scan probes for one more than the target, then discards it. That is
what makes `20+` truthful: it means a 21st match genuinely existed, not merely
that the loop stopped. A bare `20` means the target was met with no margin left
in the window, which is worth distinguishing.
The scan exits as soon as the target is met, so the search ceiling costs
nothing on timeframes that reach it — 65m stops near bar 126 regardless of the
setting. It is not free where the target is unreachable: the loop then runs the
full distance on every bar, which is what the history toggle is for.
`todActive` reflects what the code actually used, never what was requested. The
dashboard reads that flag rather than the input, which is what prevents MODE
from displaying `TOD` while a rolling baseline is in use.
The compact number formatter uses `"#0"` rather than `"#"` for sub-thousand
values — a bare `"#"` drops the digit on sub-1 values and renders a lone minus
sign.
Open source.
Open-source Skript
Ganz im Sinne von TradingView hat dieser Autor sein/ihr Script als Open-Source veröffentlicht. Auf diese Weise können nun auch andere Trader das Script rezensieren und die Funktionalität überprüfen. Vielen Dank an den Autor! Sie können das Script kostenlos verwenden, aber eine Wiederveröffentlichung des Codes unterliegt unseren Hausregeln.
Haftungsausschluss
Die Informationen und Veröffentlichungen sind nicht als Finanz-, Anlage-, Handels- oder andere Arten von Ratschlägen oder Empfehlungen gedacht, die von TradingView bereitgestellt oder gebilligt werden, und stellen diese nicht dar. Lesen Sie mehr in den Nutzungsbedingungen.
Open-source Skript
Ganz im Sinne von TradingView hat dieser Autor sein/ihr Script als Open-Source veröffentlicht. Auf diese Weise können nun auch andere Trader das Script rezensieren und die Funktionalität überprüfen. Vielen Dank an den Autor! Sie können das Script kostenlos verwenden, aber eine Wiederveröffentlichung des Codes unterliegt unseren Hausregeln.
Haftungsausschluss
Die Informationen und Veröffentlichungen sind nicht als Finanz-, Anlage-, Handels- oder andere Arten von Ratschlägen oder Empfehlungen gedacht, die von TradingView bereitgestellt oder gebilligt werden, und stellen diese nicht dar. Lesen Sie mehr in den Nutzungsbedingungen.