Master this unique volume-based indicator in TradingView's Pinescript, designed to track "smart money" activity, particularly on low-volume days, to confirm trends and anticipate price movements.
The Negative Volume Index (NVI) is a cumulative momentum indicator that focuses on periods of decreasing volume. Developed by Paul Dysart and popularized by Norman Fosback, the underlying theory behind NVI is that "smart money" (institutional or well-informed investors) tends to operate on low-volume days, while "uninformed money" operates on high-volume days. Therefore, changes in price action on low-volume days are considered more significant than changes on high-volume days.
The NVI essentially tracks a cumulative sum that is adjusted only when volume decreases from the previous day. If volume decreases, the NVI is adjusted by the percentage change in price. If volume increases, the NVI remains unchanged. A rising NVI suggests smart money is accumulating an asset, even on low volume, which often precedes price increases. A falling NVI suggests smart money is distributing. NVI is primarily used to:
The calculation of the Negative Volume Index is cumulative and depends on the relationship between current and previous volume:
//@version=5
indicator("My Negative Volume Index (NVI)", overlay=false) // overlay=false to plot in a separate pane
// Input for NVI starting value (arbitrary, but common to start at 1000)
nviStartValue = input.float(1000, title="NVI Start Value")
// Calculate NVI using the built-in function
// ta.nvi() uses 'close' for price comparison and 'volume' for volume comparison
nviValue = ta.nvi(nviStartValue, close, volume)
// Plot the NVI line
plot(nviValue, title="NVI", color=color.blue, linewidth=2)
// Optional: Add a Moving Average of NVI (often a long-term EMA) as a signal line
// A common length for the NVI MA is 255 (representing roughly a year of trading days)
nviMALength = input.int(255, title="NVI MA Length", minval=1)
nviMA = ta.ema(nviValue, nviMALength)
// Plot the NVI Moving Average
plot(nviMA, title="NVI MA", color=color.orange, linewidth=1)
NVI specifically tracks activity on low-volume days, believing that these are the days when informed investors subtly position themselves.
//@version=5
strategy("NVI Crossover Strategy", overlay=true)
nviStartValue = input.float(1000, title="NVI Start Value")
nviMALength = input.int(255, title="NVI MA Length", minval=1) // Long-term MA
nviValue = ta.nvi(nviStartValue, close, volume)
nviMA = ta.ema(nviValue, nviMALength)
plot(nviValue, "NVI", color.blue, display=display.pane_only)
plot(nviMA, "NVI MA", color.orange, display=display.pane_only)
// Long entry: NVI crosses above its MA
longCondition = ta.crossover(nviValue, nviMA)
// Short entry: NVI crosses below its MA
shortCondition = ta.crossunder(nviValue, nviMA)
if (longCondition)
strategy.entry("Long NVI", strategy.long)
if (shortCondition)
strategy.entry("Short NVI", strategy.short)
// Basic exit: opposite signal
strategy.close("Long NVI", when=shortCondition)
strategy.close("Short NVI", when=longCondition)
//@version=5
strategy("NVI Divergence Strategy", overlay=true)
nviStartValue = input.float(1000, title="NVI Start Value")
nviValue = ta.nvi(nviStartValue, close, volume)
nviMALength = input.int(255, title="NVI MA Length", minval=1)
nviMA = ta.ema(nviValue, nviMALength)
plot(nviValue, "NVI", color.blue, display=display.pane_only)
plot(nviMA, "NVI MA", color.orange, display=display.pane_only)
// Simple divergence detection (conceptual, robust detection requires advanced pivot logic)
// This example looks for recent higher/lower swings in price and NVI.
// Bullish Divergence: Price lower low, NVI higher low
bullishDiv = close < close[1] and close[1] < close[2] and nviValue > nviValue[1] and nviValue[1] > nviValue[2]
// Bearish Divergence: Price higher high, NVI lower high
bearishDiv = close > close[1] and close[1] > close[2] and nviValue < nviValue[1] and nviValue[1] < nviValue[2]
// Plot shapes on the chart to indicate divergence
plotshape(bullishDiv, title="Bullish NVI Divergence", location=location.belowbar, color=color.new(color.green, 0), style=shape.triangleup, size=size.small)
plotshape(bearishDiv, title="Bearish NVI Divergence", location=location.abovebar, color=color.new(color.red, 0), style=shape.triangledown, size=size.small)
if (bullishDiv)
strategy.entry("Long Divergence", strategy.long)
if (bearishDiv)
strategy.entry("Short Divergence", strategy.short)
// Basic exit after a few bars or on opposite signal
strategy.exit("Long Divergence Exit", from_entry="Long Divergence", profit=close*0.02, loss=close*0.01)
strategy.exit("Short Divergence Exit", from_entry="Short Divergence", profit=close*0.02, loss=close*0.01)
//@version=5
strategy("NVI Trend Filter Strategy", overlay=true)
nviStartValue = input.float(1000, title="NVI Start Value")
nviMALength = input.int(255, title="NVI MA Length", minval=1) // Long-term MA filter
nviValue = ta.nvi(nviStartValue, close, volume)
nviMA = ta.ema(nviValue, nviMALength)
plot(nviValue, "NVI", color.blue, display=display.pane_only)
plot(nviMA, "NVI MA", color.orange, display=display.pane_only)
// Define NVI trend direction
isNviUptrend = nviValue > nviMA
isNviDowntrend = nviValue < nviMA
// Example: Combine with a simple price EMA crossover strategy
fastPriceMALength = input.int(10, title="Fast Price MA Length", minval=1)
slowPriceMALength = input.int(20, title="Slow Price MA Length", minval=1)
fastPriceMA = ta.ema(close, fastPriceMALength)
slowPriceMA = ta.ema(close, slowPriceMALength)
longEntrySignal = ta.crossover(fastPriceMA, slowPriceMA)
shortEntrySignal = ta.crossunder(fastPriceMA, slowPriceMA)
// Only take long entries if NVI confirms a bullish trend
if (longEntrySignal and isNviUptrend)
strategy.entry("Filtered Long", strategy.long)
// Only take short entries if NVI confirms a bearish trend
if (shortEntrySignal and isNviDowntrend)
strategy.entry("Filtered Short", strategy.short)
// Exit on opposite price MA crossover, regardless of NVI filter for simplicity
strategy.close("Filtered Long", when=ta.crossunder(fastPriceMA, slowPriceMA))
strategy.close("Filtered Short", when=ta.crossover(fastPriceMA, slowPriceMA))
// Optional: Color background based on NVI trend
bgcolor(isNviUptrend ? color.new(color.lime, 95) : na, title="NVI Bullish Bias")
bgcolor(isNviDowntrend ? color.new(color.maroon, 95) : na, title="NVI Bearish Bias")
To get the most from the Negative Volume Index in Pinescript:
NVI offers a rare glimpse into the actions of potentially more informed investors, as it attributes greater significance to price changes that occur on quiet, low-volume days.
The Negative Volume Index (NVI) is a unique and insightful technical indicator available in Pinescript for TradingView. By specifically focusing on price movements on low-volume days, it attempts to track the activity of "smart money" and provide a distinct perspective on underlying market sentiment. While its greatest strengths lie in confirming long-term trends and identifying powerful divergences with price (signaling potential trend reversals), it is most effective when smoothed with a moving average and integrated strategically with price action and other technical analysis tools. By understanding its calculation and thoughtfully utilizing its signals, you can leverage NVI to enhance your Pinescript strategies and gain a clearer understanding of market conviction, particularly from the perspective of informed investors.
Get a high-performance Pinescript analysis tool for actionable market insights, designed for traders on the move.
This strategy runs in live mode on TradingView, helping you identify potential opportunities.
Get Pinescript Strategy