Edgoro
Volume indicator

Money Flow Index (MFI): formula, levels and Pine Script v6 code

How the Money Flow Index weights an RSI-style ratio by volume, how traders read 80/20 and divergence, settings, and a free MFI script for TradingView.

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

  1. Typical price = (high + low + close) ÷ 3.
  2. Raw money flow = typical price × volume.
  3. 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.
  4. Add up the positive and the negative money flows over the last N bars (14 by default).
  5. Money ratio = positive total ÷ negative total.
  6. 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

SettingTypical valueNotes
Length14Shorter lengths are noisier and reach the extremes more often.
Levels80 / 2090 / 10 for extremes only.
SourceTypical 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.

Pine Script v6
//@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

  1. Open any chart on TradingView and open the Pine Editor.
  2. Create a new indicator, delete the template code and paste the script.
  3. 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.

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.

Make it yours with Edgoro

Describe the change in plain English and Edgoro writes the Pine Script v6 for you, ready to paste. For example:

“Plot MFI(14) with 80/20 levels and alert when MFI crosses back above 20 while RSI(14) is above 40, once per bar close.”

Build your MFI indicator