Skip to content

Free TradingView indicator

Money Flow Index Zones

Money Flow Index with shaded overbought and oversold zones and signals when MFI exits a zone on a closed bar.

Momentumv1.0TradingView (Pine Script v6) Non-repainting signals Alerts

What it does

The Money Flow Index (MFI) is an oscillator from 0 to 100 that combines price and volume. It is often described as a volume-weighted version of the RSI. Readings near the top suggest strong buying pressure over the lookback, readings near the bottom strong selling pressure.

This version shades the overbought and oversold zones, highlights the pane while MFI is inside one, and marks the bar where MFI leaves a zone. Exits are often more useful than entries into a zone, because an oscillator can stay overbought for a long time in a strong trend.

How it works

  1. Typical price = the chosen source (hlc3 by default).
  2. Raw money flow = typical price × volume.
  3. Over the last MFI length bars, money flow is summed separately for bars where typical price rose (positive flow) and fell (negative flow).
  4. MFI = 100 − 100 ÷ (1 + positive flow ÷ negative flow).
  5. Exit from overbought: a closed bar where MFI is below the overbought level after being at or above it on the previous bar, with at least the minimum number of bars spent inside the zone. Exit from oversold mirrors this.
  6. Alerts are also available for entering each zone.

How to use it

An exit from oversold says selling pressure measured by MFI has eased. An exit from overbought says buying pressure has eased. Neither is a reversal signal on its own, but many traders use them as timing triggers in the direction of a larger setup, for example looking for long entries near support only after MFI leaves the oversold zone.

Some practical points:

  • In strong trends, consider only the exit that agrees with the trend (oversold exits in an uptrend).
  • Raising "Min bars inside zone" filters brief one-bar touches.
  • Levels of 80/20 are common; 70/30 gives more frequent signals.

Settings

InputDefaultWhat it changes
MFI length14Lookback of the oscillator.
Sourcehlc3Typical price used.
Overbought level80Upper zone threshold.
Oversold level20Lower zone threshold.
Min bars inside zone before an exit counts1Filters short zone visits.
Shade pane while MFI is in a zoneonBackground highlight.
Show zone-exit markersonTriangles on exit bars.

Limitations

  • MFI depends on volume. On spot forex, TradingView shows tick volume from one data feed, which is a proxy for activity.
  • Like other oscillators, MFI can stay in a zone for many bars during trends, and exits can be followed by a quick return into the zone.
  • It reacts to closing prices of completed bars; the signal appears only when the bar closes.
  • Symbols without volume data produce no MFI and the script stops with an error.
  • Not a standalone system. Combine it with price structure and risk management.

Pine Script source

In TradingView open Pine Editor, paste the code, click Save and then Add to chart.

FXP_MFIZones.pine

66 lines

// © FXPIPS ONLINE — https://fxpips.online/tradingview-indicators/money-flow-index-zones/
// License: MIT. Educational tool — not financial advice. Trading involves substantial risk.
//@version=6
indicator("FXP Money Flow Index Zones", shorttitle = "FXP MFI Zones", overlay = false)

// ── Inputs ─────────────────────────────────────────────────────────────
grpM     = "Money Flow Index"
mfiLen   = input.int(14, "MFI length", minval = 2, group = grpM)
src      = input.source(hlc3, "Source", group = grpM)

grpZ     = "Zones"
obLevel  = input.float(80.0, "Overbought level", minval = 50.0, maxval = 100.0, step = 1.0, group = grpZ)
osLevel  = input.float(20.0, "Oversold level", minval = 0.0, maxval = 50.0, step = 1.0, group = grpZ)
minStay  = input.int(1, "Min bars inside zone before an exit counts", minval = 1, group = grpZ)

grpVis   = "Display"
showBg   = input.bool(true, "Shade pane while MFI is in a zone", group = grpVis)
showSig  = input.bool(true, "Show zone-exit markers", group = grpVis)
obCol    = input.color(color.red, "Overbought color", group = grpVis)
osCol    = input.color(color.teal, "Oversold color", group = grpVis)

// ── Calculation ────────────────────────────────────────────────────────
float mfi = ta.mfi(src, mfiLen)

bool inOB = mfi >= obLevel
bool inOS = mfi <= osLevel

// Consecutive bars spent inside each zone, counted up to the previous bar.
var int obBars = 0
var int osBars = 0
int obBarsPrev = obBars
int osBarsPrev = osBars
obBars := inOB ? obBars + 1 : 0
osBars := inOS ? osBars + 1 : 0

bool enterOB = inOB and not inOB[1]
bool enterOS = inOS and not inOS[1]
// Exits: MFI leaves the zone after spending at least minStay bars inside it.
bool exitOB  = barstate.isconfirmed and not inOB and inOB[1] and obBarsPrev >= minStay and not na(mfi)
bool exitOS  = barstate.isconfirmed and not inOS and inOS[1] and osBarsPrev >= minStay and not na(mfi)

float cumVol = ta.cum(nz(volume))
if barstate.islast and cumVol == 0
    runtime.error("This symbol provides no volume data, so MFI cannot be calculated.")

// ── Plots ──────────────────────────────────────────────────────────────
hOB  = hline(obLevel, "Overbought", color = color.new(color.red, 40), linestyle = hline.style_dashed)
hMid = hline(50, "Midline", color = color.new(color.gray, 60), linestyle = hline.style_dotted)
hOS  = hline(osLevel, "Oversold", color = color.new(color.teal, 40), linestyle = hline.style_dashed)
hTop = hline(100, "Top", color = color.new(color.gray, 100))
hBot = hline(0, "Bottom", color = color.new(color.gray, 100))
fill(hOB, hTop, color = color.new(color.red, 92), title = "Overbought zone")
fill(hOS, hBot, color = color.new(color.teal, 92), title = "Oversold zone")

plot(mfi, "MFI", color = inOB ? obCol : inOS ? osCol : color.purple, linewidth = 2)
bgcolor(showBg and inOB ? color.new(obCol, 88) : showBg and inOS ? color.new(osCol, 88) : na)

plotshape(showSig and exitOB ? mfi : na, "Exit from overbought", shape.triangledown, location.absolute, obCol, size = size.tiny)
plotshape(showSig and exitOS ? mfi : na, "Exit from oversold", shape.triangleup, location.absolute, osCol, size = size.tiny)

// ── Alerts ─────────────────────────────────────────────────────────────
alertcondition(exitOB, "MFI exited overbought", "FXP MFI Zones: MFI dropped back below overbought on {{ticker}} {{interval}}")
alertcondition(exitOS, "MFI exited oversold", "FXP MFI Zones: MFI rose back above oversold on {{ticker}} {{interval}}")
alertcondition(enterOB and barstate.isconfirmed, "MFI entered overbought", "FXP MFI Zones: MFI entered the overbought zone on {{ticker}} {{interval}}")
alertcondition(enterOS and barstate.isconfirmed, "MFI entered oversold", "FXP MFI Zones: MFI entered the oversold zone on {{ticker}} {{interval}}")

Key inputs

Key inputs of Money Flow Index Zones
InputDefaultDescription
MFI length14Bars used in the Money Flow Index.
Sourcehlc3Typical price used to compute money flow.
Overbought level80MFI at or above this value is in the overbought zone.
Oversold level20MFI at or below this value is in the oversold zone.
Min bars inside zone before an exit counts1Requires MFI to stay in a zone for a number of bars before an exit signal.

Educational tools, not advice. Indicators and Expert Advisors describe price; they do not predict it, and past behaviour does not guarantee future results. Test everything on a demo account first and never risk money you cannot afford to lose. See our disclaimer.

Keep exploring

Related tradingview indicators