What it measures
The Money Flow Index is often described as a volume-weighted RSI. Like RSI it runs from 0 to 100 and compares buying pressure with selling pressure over the last N bars, but each bar's contribution is its typical price multiplied by its volume. A rise on heavy volume pushes MFI up more than the same rise on light volume.
Gene Quong and Avrum Soudack introduced it in 1989. It sits between a momentum oscillator and a volume indicator, and it needs real volume data to mean what it says.
The formula in words
- Typical price = (high + low + close) ÷ 3.
- Raw money flow = typical price × volume.
- If the typical price is higher than the previous bar's, the raw money flow counts as positive; if lower, as negative; if unchanged, it's left out.
- Add up the positive and the negative money flows over the last N bars (14 by default).
- Money ratio = positive total ÷ negative total.
- MFI = 100 − 100 ÷ (1 + money ratio).
Unlike RSI, the totals are plain sums, not smoothed averages, so a heavy-volume bar counts in full for N bars and then drops out at once. Pine Script's ta.mfi(source, length) implements this, with hlc3 as the usual source.
How traders read it
- Zones. Above 80 is called overbought and below 20 oversold. Because volume is involved, readings beyond 90 or below 10 are less common than RSI extremes and get more attention.
- Leaving a zone. MFI crossing back below 80 or back above 20 is a more specific event than simply being in a zone. The script marks those crosses.
- Divergence. Price makes a new high while MFI makes a lower high: the move continues on weaker volume-weighted buying. As with RSI divergence, it needs a defined trigger.
- Comparing with RSI. When MFI and RSI disagree, volume is the reason. A rally with a high RSI but a modest MFI has been made on light volume.
Common settings
| Setting | Typical value | Notes |
|---|---|---|
| Length | 14 | Shorter lengths are noisier and reach the extremes more often. |
| Levels | 80 / 20 | 90 / 10 for extremes only. |
| Source | Typical price (hlc3) | The standard definition. |
Pine Script v6 code
The complete, self-contained script is below. Copy it into a new indicator in TradingView's Pine Editor, or download the .pine file.
//@version=6
indicator("Money Flow Index (MFI)", shorttitle = "MFI", format = format.price, precision = 2)
src = input.source(hlc3, "Typical price", group = "Calculation")
len = input.int(14, "Length", minval = 1, group = "Calculation")
obLevel = input.int(80, "Overbought level", minval = 50, maxval = 100, group = "Levels")
osLevel = input.int(20, "Oversold level", minval = 0, maxval = 50, group = "Levels")
mfi = ta.mfi(src, len)
// MFI leaving a zone: crossing back above oversold, or back below overbought.
leavesOversold = ta.crossover(mfi, osLevel)
leavesOverbought = ta.crossunder(mfi, obLevel)
plot(mfi, "MFI", color = color.new(color.purple, 0), linewidth = 2)
obLine = hline(obLevel, "Overbought", color = color.gray, linestyle = hline.style_dashed)
hline(50, "Midline", color = color.new(color.gray, 60), linestyle = hline.style_dotted)
osLine = hline(osLevel, "Oversold", color = color.gray, linestyle = hline.style_dashed)
fill(obLine, osLine, color = color.new(color.purple, 92), title = "Range")
plotshape(leavesOversold, "Leaves oversold", shape.triangleup, location.bottom, color.new(color.teal, 0), size = size.tiny)
plotshape(leavesOverbought, "Leaves overbought", shape.triangledown, location.top, color.new(color.red, 0), size = size.tiny)
alertcondition(leavesOversold, "MFI leaves oversold", "MFI crossed back above the oversold level on {{ticker}} ({{interval}})")
alertcondition(leavesOverbought, "MFI leaves overbought", "MFI crossed back below the overbought level on {{ticker}} ({{interval}})")
totalVol = ta.cum(nz(volume))
if barstate.islast and totalVol == 0
runtime.error("This symbol has no volume data, so MFI can't be calculated.")MFI is drawn in its own pane with the 80/20 zone shaded and triangles when it crosses back out of a zone. Both events are available as alert conditions; set them to Once per bar close.
The script stops with an error message on symbols with no volume data, where MFI can't be calculated.
Add it to your chart
- Open any chart on TradingView and open the Pine Editor.
- Create a new indicator, delete the template code and paste the script.
- Click Save, then Add to chart. Change lengths and levels from the indicator's settings.
Stuck on an error? See how to add a Pine Script indicator to TradingView.
Pitfalls
- Tick volume. On spot forex and many CFDs, volume is a count of price changes. MFI still calculates, but it weights by activity, not by money traded.
- Overbought in trends. As with RSI, strong trends keep MFI high. Use the zones in ranges or with a trend filter.
- Volume spikes. One very large bar dominates the totals for 14 bars, then leaves the window and makes MFI jump. Look for such bars before reading a sudden move.
- Live-bar crosses. Price and volume are still changing on the current bar.
Related reading
- How to code RSI divergence in Pine Script v6 (without repainting)
- Pine Script alerts: alertcondition() vs alert(), messages, webhooks and frequency
- RSI Calculator (free tool)
- Risk/Reward Calculator (free tool)
The script is an educational example: test it on your own markets before relying on it. Indicators describe the past; they don't predict the future. Trading involves substantial risk of loss and is not suitable for every investor. Edgoro is a software tool, not a broker or financial adviser: nothing it produces is investment advice, and past or backtested performance does not guarantee future results.