TradingView indicator calculations

Volume-weighted RSI: choose what volume weights

Volume-weighted RSI can mean weighting price gains and losses before calculating an oscillator, or applying a volume-weighted average to an already calculated RSI. These operations produce different numbers. Choose the weighting stage, averaging method and missing-volume policy before comparing TradingView scripts. MFI has a separate formula based on typical-price money flow.

See the decision guide

Four calculations that should not share one label

Use close-to-close change d = C(t) − C(t−1), gain g = max(d, 0), loss l = max(−d, 0), and bar volume V. TradingView documents ordinary RSI using Wilder averages of gains and losses. The weighted variants below are explicit public definitions for comparison, not a claim that every community indicator implements them.

  • RMA uses an arithmetic-mean seed for the first N valid observations, then A(t) = [(N−1) × A(t−1) + x(t)] / N. Initial history therefore matters.
  • Dividing both rolling weighted gain and loss averages by the same total volume cancels in their ratio. Smoothing those normalized averages afterward is a different operation and need not cancel.
  • All displayed formulas require a positive denominator. A flat or zero-weight window has no directional ratio; this page returns unavailable instead of inventing a neutral observation.
CalculationDefinitionWhat changes
Ordinary RSI100 × RMA(g, N) / [RMA(g, N) + RMA(l, N)]Price changes determine the ratio; volume has no role.
Contribution-weighted, rolling100 × sum(V × g, N) / [sum(V × g, N) + sum(V × l, N)]A large-volume move has more weight; the oldest contribution leaves after N bars.
Contribution-weighted, Wilder100 × RMA(V × g, N) / [RMA(V × g, N) + RMA(V × l, N)]Weighted contributions decay recursively rather than dropping out at N bars.
Volume-smoothed RSIsum(V × RSI, M) / sum(V, M)Volume averages the last M ordinary RSI readings after their calculation.

A share-volume and tick-volume calculation fixture

This hypothetical fixture uses completed bars and N = 3. Bar 0 closes at 100. For every bar, high = close + 1 and low = close − 1, so typical price equals close. The share column represents actual traded quantity in a simulated stock feed; the tick column represents price-update counts in a separate simulated feed. These are teaching inputs, not downloaded market observations or a conversion between units.

  • At bar 3, ordinary RSI seeds average gain at 4/3 and average loss at 1/3: 100 × 4/5 = 80.0000.
  • Using shares, weighted gains total 100 × 2 + 100 × 2 = 400 and weighted losses total 300 × 1 = 300. Rolling weighted RSI is 100 × 400/700 = 57.1429.
  • Using ticks, weighted gains total 30 × 2 + 30 × 2 = 120 and losses total 10 × 1 = 10. The result is 100 × 120/130 = 92.3077. Ordinary RSI remains 80.0000.
  • Multiplying every volume by the same positive constant leaves these ratios unchanged. Replacing the shares with the nonproportional tick counts changes the result.
BarCloseChangeTraded sharesPrice updates (ticks)
1102+210030
2101−130010
3103+210030
4102−110010

A fourth bar separates rolling weights from Wilder smoothing

At bar 3, rolling and Wilder contribution weighting happen to agree because Wilder has just seeded from the same three observations. At bar 4, the rolling version discards bar 1 while the Wilder version retains a decayed contribution. Matching one seed value is not enough to establish equivalence.

  • Rolling at bar 4: gains = 200, losses = 300 + 100 = 400, so 100 × 200/600 = 33.3333.
  • Wilder at bar 4: weighted average gain = (2 × 400/3 + 0)/3 = 800/9; weighted average loss = (2 × 100 + 100)/3 = 100. The oscillator is 100 × 800/1700 = 47.0588.
  • Ordinary average gain becomes 8/9 and average loss 5/9, giving 100 × 8/13 = 61.5385. The two-bar post-smoothed line is (100 × 80 + 100 × 61.5384615)/200 = 70.7692.
  • The post-smoothed series needs M complete RSI readings. With N = 3 and M = 2 here, its first value needs five closes, including bar 0.
Share-volume calculationBar 3Bar 4
Ordinary RSI, N = 380.000061.5385
Rolling contribution weighting, N = 357.142933.3333
Wilder contribution weighting, N = 357.142947.0588
Volume-smoothed ordinary RSI, M = 2Unavailable70.7692

MFI weights typical-price money flow

TradingView defines typical price as (high + low + close)/3 and raw money flow as typical price × volume. A rising typical price assigns the full raw flow to the positive sum; a falling one assigns it to the negative sum. Equal typical prices contribute to neither directional sum. MFI is 100 × positive flow / (positive flow + negative flow), subject to a positive denominator.

  • The tick-based MFI arithmetic is possible, but typical price × tick count is not traded cash value. Label the input feed rather than presenting it as measured money entering a market.
  • A close can rise while typical price falls if the high and low shift enough. MFI and close-based RSI can therefore classify the same bar in opposite directions.
At bar 3, three-bar sampleShare-volume inputsTick-volume inputs
Positive raw flow102 × 100 + 103 × 100 = 20,500102 × 30 + 103 × 30 = 6,150
Negative raw flow101 × 300 = 30,300101 × 10 = 1,010
MFI calculation100 × 20,500/50,800 = 40.3543100 × 6,150/7,160 = 85.8939
Contribution-weighted RSI57.142992.3077
Ordinary RSI80.000080.0000

Define missing volume before adding alerts

TradingView reports that some symbols have no volume, while others supply tick volume instead of trade volume. Inspect the exact provider, symbol and interval. Do not infer the volume type from the asset name. The example script below uses a strict rolling-window policy and offers a clearly marked ordinary-RSI fallback.

  • For a Wilder implementation, choose a separate gap policy: resetting requires a new N-observation seed; skipping gaps preserves older state. The code below uses rolling contributions and does not silently choose either Wilder policy.
  • A fallback line can jump when weighted data returns. Any later alert should require valid weighted values on both the current and previous completed bars, so a mode switch cannot masquerade as a crossover.
Input or statePolicy used in this example
Missing or negative volumeInvalidate every rolling window containing that bar. Never replace it with one share or a tick.
Valid zero volumeKeep the bar in the window with zero weight. An all-zero denominator returns unavailable.
Flat closes throughout the contribution windowReturn unavailable because weighted gains plus losses equal zero.
Price-only fallback enabledShow ordinary RSI when a weighted series is unavailable; mark that series in the Data Window. Its numerical meaning has changed.
Recovery after a missing observationResume rolling weighting only once N valid contributions remain; resume post-smoothing after M valid RSI-volume pairs.
Live barCalculate internally but display values only at confirmation. Do not treat provisional price or volume as a finished signal.

Pine Script v6: compare rolling weighting with post-smoothing

This implementation plots ordinary RSI, the rolling contribution-weighted version, and an M-bar volume average of ordinary RSI. It deliberately labels the rolling method. Set N = 3 and M = 2 when checking the fixture arithmetic; defaults of 14 and 5 are inputs, not recommended trading settings. The script does not include trade signals.

Completed-bar plots with strict windows and an optional labeled fallback.pine
//@version=6
indicator("Volume-weighted RSI comparison", overlay=false)
n = input.int(14, "Contribution and RSI length", minval=1)
m = input.int(5, "RSI volume smoothing length", minval=1)
fallback = input.bool(false, "Use ordinary RSI when weighted data is unavailable")
delta = ta.change(close)
ordinary = ta.rsi(close, n)
volumeValid = not na(volume) and volume >= 0
contributionValid = volumeValid and not na(delta)
gain = contributionValid ? math.max(delta, 0) * volume : 0.0
loss = contributionValid ? math.max(-delta, 0) * volume : 0.0
gains = math.sum(gain, n)
losses = math.sum(loss, n)
validContributions = math.sum(contributionValid ? 1.0 : 0.0, n)
weightedValid = validContributions == n and gains + losses > 0
weighted = weightedValid ? 100.0 * gains / (gains + losses) : na
pairValid = volumeValid and not na(ordinary)
pairCount = math.sum(pairValid ? 1.0 : 0.0, m)
volumeSum = math.sum(pairValid ? volume : 0.0, m)
rsiVolumeSum = math.sum(pairValid ? ordinary * volume : 0.0, m)
smoothedValid = pairCount == m and volumeSum > 0
smoothed = smoothedValid ? rsiVolumeSum / volumeSum : na
weightedFallback = fallback and not weightedValid and not na(ordinary)
smoothedFallback = fallback and not smoothedValid and not na(ordinary)
weightedShown = weightedFallback ? ordinary : weighted
smoothedShown = smoothedFallback ? ordinary : smoothed
plot(barstate.isconfirmed ? ordinary : na, "Ordinary RSI", color=color.gray, style=plot.style_linebr)
plot(barstate.isconfirmed ? weightedShown : na, "Rolling contribution-weighted RSI", color=color.blue, style=plot.style_linebr)
plot(barstate.isconfirmed ? smoothedShown : na, "Volume-smoothed ordinary RSI", color=color.orange, style=plot.style_linebr)
plot(barstate.isconfirmed ? (weightedFallback ? 1 : 0) : na, "Contribution fallback active", display=display.data_window)
plot(barstate.isconfirmed ? (smoothedFallback ? 1 : 0) : na, "Smoothing fallback active", display=display.data_window)
hline(50, "Midpoint", color=color.gray)

Test the calculation before turning it into a signal

Use standard candles and record the provider, symbol, interval, session, adjustment settings, source and lengths. Add ordinary RSI with the same close source and length as a baseline. Compare completed bars in the Data Window, including the first available value and a later bar after the seed. The hypothetical fixture is a calculation test, not a claim of chart performance.

  • Check constant positive volume: rolling weighted RSI should equal a rolling gain/loss oscillator, but need not equal Wilder RSI after initialization. The Wilder-weighted version should match ordinary RSI with matching seeds and gap rules.
  • Check a missing bar, an all-zero volume window, a flat-price window, and recovery. Verify fallback flags separately for the contribution and smoothing plots.
  • Changing feed, timeframe or extended-hours settings changes the observations. A threshold copied from ordinary RSI or another author has no established equivalence here.
  • Ask Pineify's Pine Script AI Coding Agent to adapt this explicit public formula, expose diagnostic values, and run syntax validation on request. Confirm the resulting values in TradingView before asking it to add a completed-bar alert. A syntax pass does not prove numerical equivalence or profitable signals.
Where Pineify fits

Pine Script AI Coding Agent

Turn a specified weighting method, initialization rule and missing-data policy into editable Pine Script. Request a syntax check, then compare completed-bar values before adding alerts.

Build a defined RSI variant

Frequently asked questions

Educational calculation examples, not investment advice. All fixture prices, share volumes and tick counts are hypothetical. Volume weighting does not guarantee better signals or trading returns.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.