Volume Flow Indicator on TradingView
The Volume Flow Indicator (VFI) adds signed volume only when a price change exceeds a volatility threshold, caps each bar's volume contribution, and normalizes the total by average volume. Above zero, positive contributions outweigh negative ones in the selected window. That is a description of past chart data, not a forecast.
Markos Katsanos introduced VFI. This guide identifies the Pineify implementation, shows what its two filters actually do, and provides a Pine Script v6 example that leaves the plot blank when its data checks fail.
Inspect the VFI codePrice change → threshold test → capped signed volume → rolling sum ÷ prior average volume
The price test can reject a high-volume bar. The volume cap can reduce a bar that passes the price test.
Check the VFI version before comparing values
VFI is a calculation family rather than one identical TradingView script. Katsanos's published examples use a 130-bar baseline, a 0.2 price coefficient, and a 2.5 volume multiplier. His displayed Amibroker version smooths raw VFI with a three-period EMA and adds a 30-period moving average. See the author's original formula and settings.
The Pineify core function reproduced below uses typical price, hlc3. Its optional smoothing is a three-bar SMA, disabled by default, and it calculates a five-bar EMA signal. The example plots only VFI and zero so that the missing-data policy is explicit. It does not claim to reproduce the original smoothed curve exactly.
TradingView also hosts LazyBear's VFI publication, which exposes a signal EMA and configurable parameters. Record the author and settings when comparing a chart with another user's chart.
The calculation used here
- Typical price is (high + low + close) / 3. Compute its one-bar log change, then the standard deviation of those changes over 30 bars.
- The price cutoff is coefficient × that standard deviation × current close. Compare the ordinary change in typical price with this cutoff, not the log change itself.
- Average volume is the length-bar SMA from the previous bar. The cap is that average × the volume multiplier. Keep the smaller of current volume and the cap.
- If the price change is strictly above the cutoff, add capped volume. If strictly below the negative cutoff, subtract it. Otherwise, contribute zero; equality also contributes zero.
- Sum those contributions over the selected length and divide by the current prior-bar average volume. Apply the optional three-bar SMA only when enabled.
The code is the exact reference for these steps. The prior-bar average excludes the current volume spike from its own cap; the spike can still affect averages used on later bars.
A volume spike can count less, or not at all
Illustrative inputs: prior average volume is 100,000 units, the volume multiplier is 2.5, and the price cutoff is 0.20 price units. The volume cap is therefore 250,000 units. These are hypothetical bars, not market observations.
| Typical-price change | Volume | Signed contribution |
|---|---|---|
| +0.30 | 600,000 | +250,000 (capped) |
| +0.10 | 600,000 | 0 (below price cutoff) |
| −0.40 | 80,000 | −80,000 |
| +0.20 | 200,000 | 0 (equal to cutoff) |
If the complete rolling window sums to +300,000 units and its current denominator is 100,000, raw VFI is +3. This is a normalized indicator value, not a 3% return or three dollars of inflow. A capped earnings-day spike still matters; its contribution is limited, not erased.
What changing a parameter changes
A larger price coefficient rejects more small moves. A smaller volume multiplier clips more large-volume bars. Length changes both the summation window and average-volume baseline. Smoothing changes the displayed curve and adds lag. None of these changes repairs missing data or establishes a more profitable setting.
Use 130 / 0.2 / 2.5 as a reproducible baseline, then change one assumption at a time. Keep the feed, session and chart type fixed. Test a separate period before judging any full strategy; a parameter selected from its best historical outcome is not independent evidence.
Read the zero line without treating it as an entry rule
A cross above zero means the filtered rolling balance has changed sign. It can happen because a new positive contribution arrived or an old negative contribution left the window. A positive but falling VFI still has a positive balance; it is not the same event as a cross below zero.
Repeated crosses are possible in a sideways market. A signal-line cross answers a different question: whether VFI is above or below its own moving average. If you test either event, define the bar-close condition, entry timing, exit, position size and trading costs before measuring results.
A higher price high paired with a lower VFI high is a bearish divergence candidate, not a timed reversal. Specify how the highs are paired. Pivot rules that need right-side bars can only confirm after those bars arrive; placing a marker on the earlier pivot does not make it available then.
The open candle's high, low, close and volume can change, so its VFI can cross zero and return before close. Waiting for the close removes that intrabar ambiguity at the cost of delay. TradingView's repainting documentation explains this distinction and later data revisions.
For another volume calculation, compare the Money Flow Index. Its bounded ratio answers a different question. Neither name establishes a performance advantage.
Pine Script with an explicit missing-volume policy
Check the chart's Volume pane before interpreting VFI. TradingView receives volume from its data providers; some symbols lack it, and some provide tick volume, which counts price updates. See TradingView's volume availability notes. Nonzero volume alone does not verify its quality.
This example preserves Pineify's VFI calculation and adds a conservative display check. It requires 2 × length + 31 consecutive bars with positive volume, typical price and close, covering the nested volume windows, volatility lookback and optional smoothing. At length 130 it waits for 291 bars, including after a bad bar.
Zero volume is deliberately rejected even when it represents a genuine no-trade bar. That policy sacrifices availability for an obvious missing-data state; it is not a requirement of every VFI implementation. Missing readings stay blank instead of being converted to zero. Only VFI is plotted; the internal signal output is unused.
Copy the script into TradingView's Pine Editor and add it to a standard candlestick chart. Match the exchange, timeframe, session and settings when comparing versions. A successful syntax check does not validate the data feed or a trading strategy.
// This source code is subject to the Mozilla Public License 2.0.
// https://mozilla.org/MPL/2.0/ | VFI calculation: Pineify core
//@version=6
indicator("VFI with explicit data availability", overlay = false)
length = input.int(130, "VFI length", minval = 2, maxval = 500)
coef = input.float(0.2, "Price cutoff coefficient", minval = 0)
vcoef = input.float(2.5, "Volume cap multiplier", minval = 0.1)
smoothVFI = input.bool(false, "Apply 3-bar SMA")
p_ta_vfi_ma(float x, int y, bool smoothVFI) =>
ma = ta.sma(x, y)
smoothVFI ? ma : x
p_ta_vfi(simple int length, simple float coef, simple float vcoef, simple int signalLength, simple bool smoothVFI) =>
typical = hlc3
inter = math.log(typical) - math.log(typical[1])
vinter = ta.stdev(inter, 30)
cutoff = coef * vinter * close
vave = ta.sma(volume, length)[1]
vmax = vave * vcoef
vc = volume < vmax ? volume : vmax
mf = typical - typical[1]
vcp = mf > cutoff ? vc : (mf < -cutoff ? -vc : 0)
vfi = p_ta_vfi_ma(math.sum(vcp, length) / vave, 3, smoothVFI)
vfima = ta.ema(vfi, signalLength)
diff = vfi - vfima
[vfi, vfima, diff]
[rawVfi, unusedSignal, unusedDifference] = p_ta_vfi(length, coef, vcoef, 5, smoothVFI)
// Conservative display policy; zero volume is rejected even if genuine.
cleanBarsNeeded = 2 * length + 31
validBar = not na(volume) and volume > 0 and not na(hlc3) and hlc3 > 0 and close > 0
validWindow = ta.lowest(validBar ? 1.0 : 0.0, cleanBarsNeeded) == 1.0 and bar_index >= cleanBarsNeeded - 1
vfi = validWindow ? rawVfi : na
plot(vfi, "VFI", color = color.blue, linewidth = 2, style = plot.style_linebr)
hline(0, "Zero", color = color.gray)
var table status = table.new(position.top_right, 1, 1)
if barstate.islast
message = na(vfi) ? "VFI unavailable: check volume, prices and history" : "VFI uses this chart feed; open-bar values can change"
table.cell(status, 0, 0, message, text_color = color.white, bgcolor = color.new(color.black, 20))Make the VFI assumptions reviewable in Pineify
Pineify's AI Coding Agent can help write and revise Pine Script from explicit requirements. Give it the chosen VFI version, coefficients, smoothing and missing-volume policy. Ask for a separate bar-close alert or strategy only after specifying the rule you intend to test.
Keep the VFI formula shown here. Expose its price coefficient and volume multiplier as inputs. Explain the data availability check, and list any calculation changes before adding a zero-cross alert that waits for bar close.
Review the generated code and test it in TradingView. Code generation and syntax checking do not establish a trading edge.
Review VFI with the AI Coding AgentVFI questions
What does the Volume Flow Indicator measure?
VFI sums volume assigned a positive or negative sign by changes in typical price, after applying a price threshold and volume cap. It is a price-and-volume oscillator, not a measurement of institutional inflows, net dollars entering the market, or buyer-initiated trades.
Why do two TradingView VFI scripts show different values?
Check the author, source price, lookback, coefficients, smoothing, signal line, symbol feed, and session. The Katsanos code shown on his website uses EMA smoothing; the Pineify core variant used here has optional three-bar SMA smoothing, disabled by default. Matching the name alone does not match the formula.
Are 130, 0.2, and 2.5 the best VFI settings?
They are a documented baseline, not a universal optimum. Length is measured in chart bars. A daily window and an intraday window cover different elapsed time. Compare any changed settings on a separate test period using the same feed and complete trading rules.
Why is the VFI pane blank in this example?
The example requires 2 × length + 31 consecutive bars with positive volume, typical price, and close. That is 291 bars at the default length. A missing or zero-volume bar restarts this conservative waiting period. Check the data feed and available history; do not interpret a blank plot as neutral flow.
Does VFI repaint?
The open-bar reading can change with price and volume. This example uses chart data without future offsets or higher-timeframe requests, but its current value is still provisional until the bar closes. Feed corrections can also change historical values.
Can VFI be used with forex or crypto?
Only with an understood volume series. Some symbols have no volume, and some feeds provide tick counts rather than traded units. Crypto volume belongs to the selected exchange or feed. A nonzero series does not prove data quality or make different feeds directly comparable.
Sources and related reading
Source review: October 16, 2026. Formula details are also visible in the code above.
- Markos Katsanos: Volume Flow (VFI) Indicator and original code
- TradingView: Volume Flow Indicator by LazyBear
- TradingView: Missing, zero, and tick volume
- TradingView Pine Script: Repainting
Continue with MFI, Chaikin Money Flow, or the TradingView indicator guides.
Educational information, not investment advice. The numerical example is hypothetical. VFI readings do not guarantee future price direction or profitable trades.