Indicator · Pine Script v6 · Own pane

Candle Pressure Index [WavesUnchained]

by casoon

The Candle Pressure Index measures buying versus selling pressure from candle geometry and relative volume.

View on GitHub

GitHub stars9on the repository
Pine versionv6current
Lines of code148
Settings5inputs
LicenceMIT
Last updateyesterday27 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

148 lines of Pine Script v6 from indicators/money_flow/candle_pressure_index/candle_pressure_index.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

candle_pressure_index.pine
//@version=6
// ============================================================================
// Candle Pressure Index [WavesUnchained]
// Version: 1.1.5
// Author: WavesUnchained
// Build: 2026-10-12
// ============================================================================
// Measures buying vs. selling pressure from raw candle microstructure —
// no derived oscillators, only price geometry and relative volume.
// Per-bar pressure = (2 × close_location − 1) × body_ratio × volume_rank.
//
// Features:
//   ✓ Per-bar pressure: close location × body ratio × relative volume
//   ✓ CPI oscillator (EMA of pressure, −1 to +1 range)
//   ✓ Momentum line (CPI 1st derivative)
//   ✓ Initiation / Absorption spike markers (extreme single-bar pressure)
//   ✓ Optional zero-cross pressure-turn markers with momentum gate
//   ✓ Dashboard: state, CPI value, momentum direction, bar pressure
//   ✓ Alerts: pressure turns, initiation/absorption spike
//
// Data Contract:
//   Price:     REQUIRED   chart symbol
//   Volume:    REQUIRED   real trade volume — feed must deliver volume and
//                         syminfo.volumetype must not be "tick"; otherwise not available
//   OI:        NO
//   Reference: NO
//   Verdict:   Exchange-only
// ============================================================================

indicator("Candle Pressure Index [WavesUnchained]", "CPI [WU]", format=format.price, precision=2, overlay=false)

// ─── Inputs ───────────────────────────────────────────────────────────────────

grCPI       = "Candle Pressure Index"
cpiLen      = input.int(20,   "Smoothing Length",      minval=2,  maxval=100,  group=grCPI)
volLookback = input.int(20,   "Volume Rank Lookback",  minval=5,  maxval=100,  group=grCPI)
spikeThresh = input.float(0.6, "Spike Threshold",      minval=0.2, maxval=1.0, step=0.05, group=grCPI,
     tooltip="Minimum |raw pressure| to mark a bar as an initiation or absorption spike.")



grD      = "Display"
showDash = input.bool(true, "Show Dashboard", group=grD)

// Echtes Handelsvolumen? Nur "tick" schließt es ausdrücklich aus (Anzahl
// Transaktionen, keine Menge). "n/a" heißt laut Referenz "kein Volumen ODER Art
// nicht angegeben" — die meisten Feeds außer Krypto melden das, auch Futures mit
// echten Kontrakten. Dort entscheidet, ob der Feed überhaupt Volumen liefert.
var bool feedHasVolume = false
if nz(volume) > 0
    feedHasVolume := true
bool volumeIsReal = syminfo.volumetype != "tick" and feedHasVolume
float vol = volumeIsReal ? volume : na

// ─── Per-bar raw pressure ─────────────────────────────────────────────────────
// close_location: 0 = closed at low, 1 = closed at high
// body_ratio:     0 = doji, 1 = marubozu
// volume_rank:    bar volume relative to recent max (0–1)
// net_pressure:   (2 × close_location − 1) × body_ratio × volume_rank
//                 → +1 strongest bull, −1 strongest bear

hl        = high - low
closeLoc  = hl > 0 ? (close - low) / hl : 0.5
bodyRat   = hl > 0 ? math.abs(close - open) / hl : 0.0
volMax    = ta.highest(vol, volLookback)
volRank   = not volumeIsReal ? na : volMax > 0 ? vol / volMax : 0.5

rawP = (2.0 * closeLoc - 1.0) * bodyRat * volRank

// ─── CPI oscillator ───────────────────────────────────────────────────────────

cpi    = ta.ema(rawP, cpiLen)
cpiAcc = cpi - nz(cpi[1])

// ─── Spikes ───────────────────────────────────────────────────────────────────

spikeBull = rawP >=  spikeThresh
spikeBear = rawP <= -spikeThresh



// ─── Colors ───────────────────────────────────────────────────────────────────

bullC    = color.new(#00c853, 0)
bearC    = color.new(#d50000, 0)
neutC    = color.new(color.gray, 30)
cpiColor = cpi > 0.15 ? bullC : cpi < -0.15 ? bearC : neutC
accColor = cpiAcc >= 0 ? color.new(#00c853, 50) : color.new(#d50000, 50)

// ─── Plots ────────────────────────────────────────────────────────────────────

hline(0,    "Zero",      color=color.new(color.gray, 50))
hline(0.3,  "Bull Zone", color=color.new(#00c853, 70), linestyle=hline.style_dotted)
hline(-0.3, "Bear Zone", color=color.new(#d50000, 70), linestyle=hline.style_dotted)

plot(cpi,    "CPI",      color=cpiColor, linewidth=2)
plot(cpiAcc, "Momentum", color=accColor, linewidth=1)

plotshape(spikeBull, "Initiation", shape.circle, location.bottom,
     color=color.new(#00c853, 30), size=size.tiny)
plotshape(spikeBear, "Absorption", shape.circle, location.top,
     color=color.new(#d50000, 30), size=size.tiny)



// ─── Dashboard ────────────────────────────────────────────────────────────────

color tc = color.new(color.gray, 20)
color hd = color.new(color.gray, 90)

var table t = table.new(position.top_right, 2, 5,
     bgcolor=color.new(color.white, 5),
     border_color=color.new(color.gray, 60), border_width=1,
     frame_color=color.new(color.gray, 40), frame_width=1)

if showDash and barstate.islast and volumeIsReal
    table.cell(t, 0, 0, "CPI",         text_color=tc, bgcolor=hd, text_size=size.small)
    table.cell(t, 1, 0, "Value",       text_color=tc, bgcolor=hd, text_size=size.small)

    cpiState  = cpi > 0.3 ? "Strong Bull" : cpi > 0.15 ? "Bull" : cpi < -0.3 ? "Strong Bear" : cpi < -0.15 ? "Bear" : "Neutral"
    cpiStateC = cpi > 0.15 ? bullC : cpi < -0.15 ? bearC : tc

    table.cell(t, 0, 1, "State",       text_color=tc,        text_size=size.small)
    table.cell(t, 1, 1, cpiState,      text_color=cpiStateC, text_size=size.small)
    table.cell(t, 0, 2, "CPI",         text_color=tc,        text_size=size.small)
    table.cell(t, 1, 2, str.tostring(cpi, "#.##"), text_color=cpiStateC, text_size=size.small)

    accStr = cpiAcc >= 0 ? "Rising ↑" : "Falling ↓"
    accC2  = cpiAcc >= 0 ? bullC : bearC
    table.cell(t, 0, 3, "Momentum",    text_color=tc,   text_size=size.small)
    table.cell(t, 1, 3, accStr,        text_color=accC2, text_size=size.small)

    table.cell(t, 0, 4, "Bar Pressure", text_color=tc, text_size=size.small)
    table.cell(t, 1, 4, str.tostring(rawP, "#.##"), text_color=tc, text_size=size.small)

// Kurzer Hinweis unten rechts; was fehlt, steht im Data Contract oben.
var table volWarn = table.new(position.bottom_right, 1, 1)
if barstate.islast and not volumeIsReal
    table.cell(volWarn, 0, 0, "CPI · not available",
         bgcolor = color.new(color.orange, 20), text_color = color.white, text_size = size.small)

// ─── Alerts ───────────────────────────────────────────────────────────────────

bool alertsOnBarClose = input.bool(true, "Alerts only on bar close (confirmed)", group="Alerts")
bool alertOk = not alertsOnBarClose or barstate.isconfirmed

alertcondition(alertOk and (spikeBull), "CPI Initiation Spike", "CPI · INITIATION SPIKE · {{ticker}} {{interval}}")
alertcondition(alertOk and (spikeBear), "CPI Absorption Spike", "CPI · ABSORPTION SPIKE · {{ticker}} {{interval}}")

Overview

Each bar combines close location, body ratio, and volume rank into a raw pressure value. An exponential moving average of that pressure forms the CPI oscillator between minus one and plus one, while a momentum line tracks its first derivative. Spike markers flag extreme initiation or absorption bars, and optional markers show zero-cross turns gated by momentum. Settings change smoothing, volume lookback, and spike threshold. It plots in a separate pane and requires real trade volume rather than tick volume.

Details

Published by

casoon on GitHub

Type

Indicator, Pine Script v6

Draws

Separate pane below the chart

Category

Oscillators & momentum, Volume, Candlestick patterns, Screeners & dashboards

Markets

Stocks, Crypto, Indices, Oil & commodities

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.

Topics

pine-scriptpinescripttechnical-analysistrading-indicatorstrading-strategiestradingview

Settings

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

SettingTypeDefaultVariable
Smoothing Lengthint20cpiLen
Volume Rank Lookbackint20volLookback
Spike Thresholdfloat0.6spikeThresh
Show DashboardbooltrueshowDash
Alerts only on bar close (confirmed)booltruealertsOnBarClose
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

Commitment Gauge

by harryguiacorn
219 stars

This indicator measures directional momentum by evaluating candlestick body proportions and volume over a user-defined lookback window. It computes the ratio of candle body to total range, weights the cumulative value by volume and absolute body size, and dete

Indicator v4 VolumeCandlestick patterns
Updated 1 year ago · None stated GitHub repository of Commitment Gauge

Oscillator Suite

by TamaraKGreen
46 stars

Oscillator Suite plots a normalised price oscillator in a separate pane and overlays a signal line that can use SMA, EMA, WMA, HMA, RMA, VWMA, T3, ZEMA, KAMA, or GKEMA. It marks bullish and bearish divergences, a smoothed money-flow series, confluence areas an

Indicator v5 Oscillators & momentumDivergence
Updated 7 weeks ago · None stated GitHub repository of Oscillator Suite

This indicator calculates the Relative Strength Index (RSI) alongside a simple moving average to generate directional momentum signals in a separate pane. It supports Break Flip and Break Continuous scanning modes for long and short setups. A wide array of opt

Indicator v5 Oscillators & momentumVolatility & bands
Updated 1 year ago · None stated GitHub repository of Momentum Setup: RSI Direction Confirmation
11 stars

This indicator plots a smoothed Z-score of cumulative volume delta in a separate pane, showing whether buying or selling pressure is dominant and when the reading enters extreme zones. It marks spot accumulation, climax or exhaustion, and pivot-based price-vol

Indicator v6 Oscillators & momentumVolume Repaints
Updated 7 weeks ago · MIT GitHub repository of CVD Z-Score [NeuNue]

Nexural Pressure Pro

by JasonTeixeira
9 stars

Nexural Pressure Pro is a composite pressure indicator that measures directional market momentum using volume-weighted directional movement, order flow delta, aggression, and efficiency ratio metrics. It filters out low-activity bars using configurable volume

Indicator v6 Oscillators & momentumVolume
Updated 12 days ago · Custom licence GitHub repository of Nexural Pressure Pro

This overlay indicator screens a pasted list of up to forty symbols and draws a table on the price chart. It classifies bullish or bearish setups from the percent change between the current candle and the candle 250 bars back, then shows RSI with a simple movi

Indicator v5 Oscillators & momentumVolume
Updated 1 year ago · MPL-2.0 GitHub repository of Momentum Setup - Ankush Bajaj Momentum Investing Setup

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