OPEN-SOURCE SCRIPT

CVD Divergence & Absorption [UAlgo]

5 489
CVD Divergence & Absorption is a dual context indicator that combines a cumulative volume delta (CVD) oscillator with price pivot structure to detect three important signal classes: Regular Divergence, Hidden Divergence, and Absorption. The script is designed to help traders compare price movement against directional volume participation and identify moments where price and CVD disagree, or where price stalls at similar levels while CVD continues to expand or contract.

The indicator runs in a separate pane (overlay=false) and plots a continuous CVD line, while signal labels and price side connecting lines are projected onto the main chart using force_overlay=true. This gives a clean workflow where you can monitor the CVD series in its own panel and still see exact divergence locations directly on price.

A key strength of this script is its lower timeframe volume decomposition. Instead of assigning the full chart bar volume to a single direction, it samples lower timeframe candles through request.security_lower_tf(), classifies each sub candle as up volume or down volume based on its close versus open, and aggregates the result into a bar level delta. That delta is then accumulated into the running CVD value. This approach is practical, efficient, and more granular than a simple chart timeframe approximation.

The script also includes quality controls for signal validation:

Pivot based comparisons for both price and CVD

Minimum and maximum bar distance filters between pivot comparisons

Equal price tolerance for absorption detection

A line of sight filter that rejects visually obstructed divergences where intervening candles violate the connecting path

The result is a professional divergence framework focused on cleaner, more interpretable signals rather than high frequency marking of every pivot mismatch.

Educational tool only. Not financial advice.

🔹 Features

🔸 1) Lower Timeframe CVD Construction (LTF Volume Decomposition)
The script builds CVD using lower timeframe candles selected by the user through the Lower Timeframe (LTF) input. For each chart bar, it retrieves arrays of lower timeframe open, close, and volume values and computes a signed delta:

Up LTF candle (close > open) adds volume

Down LTF candle (close < open) subtracts volume

Neutral LTF candle contributes zero

This produces a more refined bar delta than a single bar directional assumption and makes the CVD line more responsive to intrabar rotation.

🔸 2) Pivot Based Signal Engine for Price and CVD
Signal generation is anchored to confirmed price pivots using user defined left and right pivot bars. A signal candidate is considered only when:

A price pivot high/low is confirmed by ta.pivothigh or ta.pivotlow

The CVD value at that pivot location also behaves like a local high/low (simple local extremum check)

This means the script does not compare arbitrary points. It compares structurally meaningful swing locations.

🔸 3) Regular Divergence Detection (Bullish and Bearish)
The indicator supports classic regular divergence logic:

Bullish Regular Divergence: price makes a lower low while CVD makes a higher low

Bearish Regular Divergence: price makes a higher high while CVD makes a lower high

These signals can indicate weakening trend continuation pressure and potential reversal behavior, depending on context.

🔸 4) Hidden Divergence Detection (Bullish and Bearish)
The script also detects hidden divergence, which many traders use as continuation style confirmation:

Bullish Hidden Divergence: price makes a higher low while CVD makes a lower low

Bearish Hidden Divergence: price makes a lower high while CVD makes a higher high

Hidden divergence is optional and can be toggled independently from regular divergence.

🔸 5) Absorption Detection with Equal Price Tolerance
Absorption logic is included to capture situations where price prints near equal pivots, but CVD continues moving in a direction that suggests aggressive participation is being absorbed at the level:

Bearish Absorption (at highs): price is approximately equal high, but CVD is higher

Bullish Absorption (at lows): price is approximately equal low, but CVD is lower

The Equal Price Tolerance % input allows the script to treat two pivots as "equal" within a configurable percentage band. This makes absorption detection adaptable across instruments with different volatility profiles.

🔸 6) Minimum / Maximum Pivot Distance Filters
To avoid weak or overly stale comparisons, the script enforces:

A minimum number of bars between pivots

A maximum lookback distance for valid pivot pairing

This helps reduce noisy signals from pivots that are too close together and prevents pairing pivots that are too far apart to be contextually useful.

🔸 7) Line of Sight Validation (Signal Quality Filter)
Before accepting a pivot comparison, the script checks whether the straight line connecting the two price pivots is "clear" from intervening candle violations:

For bearish (high based) comparisons, intervening highs must not cross above the connecting line

For bullish (low based) comparisons, intervening lows must not cross below the connecting line

This is a strong visual integrity filter. It avoids many cluttered or ambiguous divergence lines that would look invalid once drawn on the chart.

🔸 8) Dual Visualization on Price and CVD
When a signal is detected, the script draws:

A label on price ("Reg", "Hid", or "Abs")

A line connecting the two relevant price pivots on the main chart

A line connecting the corresponding CVD pivot values in the CVD pane

Line styles are used to distinguish signal types:

Solid for Regular Divergence

Dashed for Hidden Divergence

Dotted for Absorption

This synchronized plotting makes it easy to verify the signal logic visually.

🔸 9) Conflict Handling for Cleaner Labels
Absorption labels are intentionally suppressed when a Hidden Divergence signal is already active on the same side in the same event block:

bullAbs and not bullHidDiv

bearAbs and not bearHidDiv

This prevents duplicate labels on the same pivot and improves chart readability.

🔸 10) Lightweight Pivot Memory Management
The script stores historical pivot comparison points in separate arrays for highs and lows and caps them using a helper method (maxSize = 15). This keeps the logic efficient while preserving enough recent history for valid comparisons.

🔹 Calculations

1) Lower Timeframe Delta Aggregation
The script retrieves lower timeframe OHLCV arrays and computes bar delta by summing signed volume from each LTF candle:
Pine Script®
array<float> ltf_open = request.security_lower_tf(syminfo.tickerid, i_ltf, open) array<float> ltf_close = request.security_lower_tf(syminfo.tickerid, i_ltf, close) array<float> ltf_volume = request.security_lower_tf(syminfo.tickerid, i_ltf, volume)


Pine Script®
if ltf_c > ltf_o totalDelta += ltf_v else if ltf_c < ltf_o totalDelta -= ltf_v


Interpretation:

The script uses candle direction as a proxy for buying/selling pressure inside each chart bar.

This is an estimated delta model based on candle body direction, not true bid/ask tape delta.

2) CVD Accumulation
Bar delta is added into a running cumulative value stored inside a custom tracker object:
Pine Script®
method update_cvd(CVD_Tracker this, float delta) => this.currentCVD += delta this.currentCVD


The tracker persists across bars using:
Pine Script®
var CVD_Tracker tracker = CVD_Tracker.new(0.0, array.new<Pivot>(), array.new<Pivot>())


This design keeps both the CVD value and pivot histories in one structured container.

3) Price Pivot Detection
Price pivots are confirmed using standard left/right pivot logic:
Pine Script®
float ph = ta.pivothigh(high, i_left, i_right) float pl = ta.pivotlow(low, i_left, i_right)


Because pivot confirmation occurs after i_right bars, signal labels and lines are placed at:
Pine Script®
bar_index - i_right


This aligns the plotted signal with the actual pivot bar, not the confirmation bar.

4) CVD Pivot Confirmation at the Same Pivot Location
The script requires CVD to form a local extremum at the price pivot location using a simple 3-point comparison around currentCVD[i_right]:
Pine Script®
bool cvdIsPh = currentCVD[i_right] > currentCVD[i_right + 1] and currentCVD[i_right] > currentCVD[i_right - 1] bool cvdIsPl = currentCVD[i_right] < currentCVD[i_right + 1] and currentCVD[i_right] < currentCVD[i_right - 1]


Then:
Pine Script®
bool isPh = not na(ph) and cvdIsPh bool isPl = not na(pl) and cvdIsPl


This ensures price and CVD are compared on synchronized pivot events rather than unrelated timestamps.

5) Pivot Pair Selection with Distance Constraints
When a new pivot is confirmed, the script scans prior pivots of the same type (highs with highs, lows with lows) and applies:

i_min_bars as the minimum spacing

i_max_bars as the maximum valid distance

Pine Script®
if barsBetween < minBars continue if barsBetween > maxBars break


This keeps comparisons within a user defined structural window.

6) Line of Sight Filter (Price Geometry Validation)
Before checking divergence conditions, the script verifies that the connecting price line is not invalidated by intervening candles.

For highs:
Pine Script®
if barsBack >= 0 and high[barsBack] >= lineY clear := false


For lows:
Pine Script®
if barsBack >= 0 and low[barsBack] <= lineY clear := false


Interpretation:

Bearish comparisons require a clean descending/ascending line between highs without intermediate highs breaking above it.

Bullish comparisons require a clean line between lows without intermediate lows breaking below it.

This is one of the script’s strongest anti-noise mechanisms.

7) Equal Price Tolerance for Absorption
The script calculates percentage difference between pivot prices and treats them as equal if the difference is within the tolerance:
Pine Script®
float priceDiffPct = math.abs(newPivot.priceVal - histPivot.priceVal) / histPivot.priceVal * 100 bool isEqual = priceDiffPct <= eqTol


This enables absorption logic to work with approximate equal highs/lows instead of requiring perfect price matches, which are rare in live markets.

8) Bearish Signal Logic (Regular, Hidden, Absorption)
For pivot highs, the script compares a new pivot high against a historical pivot high after passing distance and line of sight checks.

Bearish Regular Divergence
Pine Script®
newPivot.priceVal > histPivot.priceVal and not isEqual and newPivot.cvdVal < histPivot.cvdVal

Meaning:

Price makes a higher high

CVD makes a lower high

Bearish Hidden Divergence
Pine Script®
newPivot.priceVal < histPivot.priceVal and not isEqual and newPivot.cvdVal > histPivot.cvdVal

Meaning:

Price makes a lower high

CVD makes a higher high

Bearish Absorption
Pine Script®
isEqual and newPivot.cvdVal > histPivot.cvdVal

Meaning:

Price prints an approximately equal high

CVD pushes higher, suggesting buying effort is absorbed near the same price zone

9) Bullish Signal Logic (Regular, Hidden, Absorption)
For pivot lows, the script compares a new pivot low against a historical pivot low after passing distance and line of sight checks.

Bullish Regular Divergence
Pine Script®
newPivot.priceVal < histPivot.priceVal and not isEqual and newPivot.cvdVal > histPivot.cvdVal

Meaning:

Price makes a lower low

CVD makes a higher low

Bullish Hidden Divergence
Pine Script®
newPivot.priceVal > histPivot.priceVal and not isEqual and newPivot.cvdVal < histPivot.cvdVal

Meaning:

Price makes a higher low

CVD makes a lower low

Bullish Absorption
Pine Script®
isEqual and newPivot.cvdVal < histPivot.cvdVal

Meaning:

Price prints an approximately equal low

CVD pushes lower, suggesting selling effort is absorbed near the same price zone

10) Signal Plotting and Visual Encoding
When a condition is confirmed, the script plots both price side and CVD side lines between the historical pivot and the new pivot, plus a compact label at the new pivot location.

Examples:
Pine Script®
label.new(bar_index - i_right, low[i_right], text="Reg", ...) line.new(bullLastPivot.loc, bullLastPivot.priceVal, bullNewPivot.loc, bullNewPivot.priceVal, ..., force_overlay=true) line.new(bullLastPivot.loc, bullLastPivot.cvdVal, bullNewPivot.loc, bullNewPivot.cvdVal, ..., force_overlay=false)


Style mapping:

line.style_solid for Regular Divergence

line.style_dashed for Hidden Divergence

line.style_dotted for Absorption

11) Pivot History Storage and Capacity Control
Each confirmed pivot is stored in a side specific array (highs or lows) using a helper method:
Pine Script®
method add_pivot(array<Pivot> this, Pivot p, int maxSize = 15) => this.push(p) if this.size() > maxSize this.shift()


This preserves recent structural history for future comparisons while keeping memory usage controlled.

면책사항

해당 정보와 게시물은 금융, 투자, 트레이딩 또는 기타 유형의 조언이나 권장 사항으로 간주되지 않으며, 트레이딩뷰에서 제공하거나 보증하는 것이 아닙니다. 자세한 내용은 이용 약관을 참조하세요.