TradingView indicator guides

Negative Volume Index on TradingView: formula and limits

The Negative Volume Index indicator updates only when a bar has less volume than the preceding bar. On those bars, it compounds the closing-price return into its previous value. Equal or higher volume leaves NVI unchanged. This page shows the arithmetic and a Pine Script implementation you can inspect.

For valid prices and a known volume pair:

NVI[t] = NVI[t−1] × close[t] / close[t−1] if volume falls.

NVI[t] = NVI[t−1] otherwise.

Volume selects the bar; its magnitude does not multiply the return.

An eight-bar calculation you can reproduce

These are invented prices and volumes, with a starting NVI of 1,000. They demonstrate arithmetic, not market performance. The custom script explicitly holds its internal value when either volume observation is missing; the script below hides the affected plot points.

Hypothetical NVI calculation with falling, equal, rising and missing volume
BarCloseVolumeRule and calculationNVI
01001,000Seed1,000
1110800Lower: 1,000 × 1.101,100
299800Equal: hold1,100
31001,200Higher: hold1,100
490900Lower: 1,100 × 0.90990
599MissingNo valid volume pair: hold990
6100700Previous volume missing: hold990
7110500Lower: 990 × 1.101,089

Bar 2 loses 10% in price but contributes nothing because volume is equal. Bar 4 loses 10% on declining volume, so NVI falls from 1,100 to 990. Bar 6 cannot compare its 700 volume with a missing observation. Bar 7 resumes with its own 10% return; it does not recover the skipped price moves.

The final result is 1,000 × 1.10 × 0.90 × 1.10 = 1,089. Summing the selected returns would produce 1,100, which is a different calculation. A lower-volume bar with an unchanged close would also leave NVI flat.

Initial values and adjusted prices

TradingView documents a 1,000 seed for its NVI chart indicator; the Pine reference implementation of ta.nvi starts at 1. This page implements the recurrence directly with an editable initial value and explicit input checks. For the same positive-price history, starting the worked example at 1 gives a final 1.089 instead of 1,089.

Scaling a series and its EMA by the same positive constant preserves their crossover bars. An absolute threshold such as 1,050 must scale too. Starting on another date can change the accumulated level: compare the same feed, session, timeframe and history before attributing a difference to the formula.

Price adjustments can change a selected return. Consider a hypothetical 2-for-1 split: an unadjusted close moves from 100 to 50. If volume declines, the raw input would halve NVI. With both closes expressed on the same post-split basis, 50 to 50 contributes zero. The split itself did not create that loss. TradingView documents historical split adjustments and a separate dividend-adjustment option.

A constant positive multiplier applied to every close cancels in the return ratio. Adjustments across a corporate-action boundary need not cancel. Record the adjustment setting when comparing calculations, and keep the price and volume histories consistent.

Copy the NVI Pine Script v6 indicator

Paste this into a new indicator in TradingView's Pine Editor, save it and add it to the chart. The blue line is the custom NVI; amber is its EMA. The two alert conditions describe confirmed crossovers. This indicator places no orders.

Pine Script v6

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Pineify
//@version=6
indicator("Negative Volume Index audit", overlay=false)

scale = input.float(1000.0, "Initial scale", minval=0.01)
emaLength = input.int(255, "EMA length", minval=1)

// Explicit policy: hold the index when either input pair is invalid.
validVolumePair = not na(volume) and not na(volume[1]) and volume >= 0 and volume[1] >= 0
validPricePair = not na(close) and not na(close[1]) and close > 0 and close[1] > 0
validInputs = validVolumePair and validPricePair
var float nvi = scale
if validInputs and volume < volume[1]
    nvi := nvi * close / close[1]
signal = ta.ema(nvi, emaLength)

// Plot gaps expose skipped bars without resetting the cumulative value.
plot(validInputs ? nvi : na, "NVI", color=#2962ff, linewidth=2, style=plot.style_linebr)
plot(validInputs ? signal : na, "NVI EMA", color=#f59e0b, style=plot.style_linebr)
plotchar(not validInputs, "Invalid input pair", "?", location.top, color=color.orange)

// Evaluate crosses on every bar; publish alert conditions only at close.
crossUp = ta.crossover(nvi, signal)
crossDown = ta.crossunder(nvi, signal)
alertcondition(barstate.isconfirmed and validInputs and crossUp, "NVI above EMA", "NVI crossed above its EMA at bar close.")
alertcondition(barstate.isconfirmed and validInputs and crossDown, "NVI below EMA", "NVI crossed below its EMA at bar close.")
Initial scale: 1,000
Changes the index units. It does not change the volume comparison.
EMA length: 255 bars
Smooths NVI on every bar, including held values. It is not an NVI lookback window.
Question mark and plot gap
Either input pair is missing, volume is negative, or a close is zero or negative. The first dataset bar also has no previous observation. These gaps expose skipped comparisons; they do not repair the feed.

This custom recurrence requires two positive closes and two nonnegative volumes. It holds NVI when that condition fails and never substitutes zero for missing volume. It does not attempt to reproduce every exceptional-data branch of ta.nvi. After a skipped pair, it resumes with the next valid adjacent pair rather than bridging the gap.

Check the data before interpreting the line

  • A reported zero volume is a number, not missing data. Zero after positive volume satisfies the decline rule. A feed filled with zeros produces a flat series after initialization; that cannot establish a lack of buying or selling.
  • Volume comes from the selected symbol and feed. Confirm its units and coverage. A venue-specific crypto feed and a market-wide series are different inputs, even when they quote the same asset.
  • Live volume accumulates before close. A bar can initially qualify for an NVI update and later fail the decline condition. The plotted line can change during that bar; the example alerts require barstate.isconfirmed.
  • The EMA can move during flat NVI segments. A crossover describes the relation between two calculated series. It does not reveal institutional positions or establish an entry edge.

NVI is a conditional price-return index. Price Volume Trend instead adds volume-weighted returns. OBV adds or subtracts bar volume according to the direction of the close change. Their values have different meanings and cannot share arbitrary thresholds.

Specify the NVI behavior in Pineify

Use the Pine Script AI Coding Agent to adapt the script to an explicit calculation contract. Include the initial scale, chart timeframe, missing-volume treatment and bar-close requirement in the request.

Build an NVI indicator with a 1,000 initial scale and a 255-bar EMA. Explicitly hold NVI when either volume is missing, either volume is negative, or either close is missing or nonpositive. Mark skipped bars. Confirm crossover alerts at bar close. Verify the eight-bar example ends at 1,089 before adding trading rules.

Check individual bars in TradingView's Data Window after reviewing the generated source. A trading strategy also needs exits, position sizing, commissions and slippage. Syntax validation checks compilation, not predictive value. This guide is educational and is not investment advice.

Adapt NVI with Pineify

Negative Volume Index questions

NVI compounds closing-price returns on bars whose volume is lower than the preceding bar. It uses relative volume, so a very active bar can qualify if the previous bar was even more active. It does not identify buyers or sellers.

The Pine reference implementation of ta.nvi starts at 1, while the TradingView NVI indicator uses 1000. On matching data, multiplying ta.nvi by 1000 reconciles that scale difference. History, sessions and price adjustments must also match.

No. Equal volume fails the strict less-than condition, so NVI holds its previous value even when price moves. A lower-volume bar with an unchanged close also leaves NVI flat.

This page uses an explicit skip-missing rule: if either volume observation is missing, the custom script holds NVI, marks the bar with a question mark and leaves a plot gap. The EMA still processes the held value. The first bar after a missing-volume bar is also skipped because its previous observation is missing.

255 is the TradingView indicator default and roughly a trading year on daily equities. It is a bar count, so it covers a different span on hourly or weekly charts. Choosing another length changes smoothing; no length establishes trading profitability.

No. The comparison states that the NVI value is above its smoothed history. The smart-money explanation is an interpretation based on assumptions about participation. Price and total volume do not reveal trader identity.

NVI uses volume as an update condition and compounds the previous index by the selected price return. PVT adds volume multiplied by the fractional price change on each bar. Increasing volume magnitude without changing its ordering leaves NVI unchanged but changes PVT contributions.

Yes. The live close and accumulated volume can change while the bar is open. A bar can begin below the preceding volume and finish above it. The script plots live values but restricts its crossover alert conditions to confirmed bar closes.