The Money Flow Index, or MFI, is what you get when you take the familiar logic of the RSI and fold volume into it. Where the RSI measures momentum from price alone, the MFI weights each move by how much traded, so a strong push on heavy volume counts for more than the same push on a quiet bar. That is why it is often described as the volume-weighted RSI, and why it appeals to traders who want a single oscillator that respects both price and participation. This guide explains what the MFI measures, why traders use it, and how to build it from scratch in Pine Script v6 on TradingView.
This is a coding tutorial, not trading advice. The MFI is a way to express volume-weighted momentum in code, and building it clarifies both what it adds over the RSI and where the two share the same weaknesses.
What the MFI measures
The calculation starts with the typical price of each bar, the average of the high, low, and close. That typical price is multiplied by the bar's volume to produce what is called raw money flow, a volume-weighted measure of the bar's activity. Bars where the typical price rose from the prior bar count as positive money flow, and bars where it fell count as negative money flow. Over a lookback period, traditionally 14 bars, the indicator sums the positive and negative money flows, forms a ratio, and scales it onto a 0-to-100 range, exactly like the RSI.
The result is a bounded oscillator that behaves much like the RSI but responds more strongly when a move is backed by volume. Because volume is baked in, the MFI can flag a move as overbought or oversold with more conviction when heavy trading is behind it, and can stay more subdued when a price move happens on thin volume. The conventional overbought and oversold levels are 80 and 20, a little more extreme than the RSI's 70 and 30.
| RSI | Money Flow Index | |
|---|---|---|
| Inputs | Price only | Price and volume |
| Overbought / oversold | 70 / 30 | 80 / 20 |
| Reads | Momentum of price | Momentum weighted by volume |
| Pine function | ta.rsi() | ta.mfi() |
Why traders use it
Traders reach for the MFI when they want the RSI's readability but suspect that volume is telling part of the story the RSI misses. The two most common uses mirror the RSI: overbought and oversold readings as a sign a move may be stretched, and divergence between the indicator and price as a hint that momentum is fading. The volume weighting is what differentiates it. An overbought MFI reached on heavy volume carries a different weight than an overbought RSI reached on quiet drift, and some traders find that the volume component filters out weak, low-participation moves that fool a price-only oscillator.
The honest caveat is that the MFI inherits the RSI's core weakness. In a strong trend it can sit in overbought or oversold territory for a long time while price keeps going, so fading every extreme is still a way to get run over. It also depends entirely on volume data being available and trustworthy, a requirement it shares with On-Balance Volume.
Building the indicator
Pine Script provides the MFI as a single built-in function, so the indicator is short. Here is the complete v6 code.
//@version=6
indicator("Money Flow Index", overlay = false)
length = input.int(14, "MFI Length")
mfiValue = ta.mfi(hlc3, length)
plot(mfiValue, "MFI", color = color.teal, linewidth = 2)
hline(80, "Overbought", color = color.red)
hline(20, "Oversold", color = color.green)
hline(50, "Midline", color = color.gray, linestyle = hline.style_dotted)The working line is ta.mfi(hlc3, length). The first argument is the source price, and passing hlc3, the average of high, low, and close, matches the typical-price definition the indicator is built on. The function handles the volume weighting internally, so you do not pass volume explicitly; it reads the chart's volume for you. Setting overlay = false keeps the oscillator in its own pane, and the hline() calls mark the 80, 20, and 50 levels. If you want to see the raw money flow and the positive-and-negative accumulation computed step by step, our Money Flow Index calculator lays out the math with the Pine Script equivalent alongside.
Turning it into a strategy
A straightforward MFI strategy mirrors the RSI approach: enter when the indicator crosses back up through the oversold level, signalling a stretched move that is turning with volume behind it, and exit when it crosses down through overbought. Here it is in v6.
//@version=6
strategy("MFI Strategy", overlay = true, margin_long = 100, margin_short = 100)
length = input.int(14, "MFI Length")
osLevel = input.int(20, "Oversold")
obLevel = input.int(80, "Overbought")
mfiValue = ta.mfi(hlc3, length)
buySignal = ta.crossover(mfiValue, osLevel)
sellSignal = ta.crossunder(mfiValue, obLevel)
if buySignal
strategy.entry("Long", strategy.long)
if sellSignal
strategy.close("Long")The entry uses ta.crossover(mfiValue, osLevel) rather than a plain mfiValue < osLevel, so it fires only on the single bar the MFI climbs back through 20, the moment volume-weighted momentum is turning up, rather than on every bar it sits below the level. The order calls live inside if blocks as v6 requires. Because the MFI, like the RSI, struggles in trends, the same refinement applies: adding a longer-term trend filter and only taking oversold entries when the broader market is pointing up tends to cut the false signals, exactly as we do in the RSI strategy guide.
MFI or RSI?
The natural question is whether to use the MFI or the RSI, and the honest answer is that they are close cousins that agree most of the time. The MFI earns its keep when volume genuinely diverges from price, flagging moves that look strong on price but happen on thin participation, or moves that look weak on price but attract heavy volume. When volume is steady, the two oscillators track each other closely and there is little reason to prefer one. The MFI's dependence on volume data is also a real constraint: on a symbol with poor or missing volume, the RSI is the more reliable choice precisely because it needs no volume at all.
The honest pitfalls
The first pitfall is the shared one with the RSI: treating an extreme reading as a signal to trade against a trend, when in a strong trend the MFI can stay pinned in an extreme while price runs. The second is trusting volume data that does not deserve it. In fragmented markets the reported volume can be incomplete or inconsistent, which quietly distorts the money-flow calculation, so know what your symbol is actually reporting before you lean on the MFI.
As always, resist over-tuning the length to fit one chart, and judge any MFI strategy across a meaningful sample of trades and more than one market. A backtest that looks flawless on a single volume-rich symbol may fall apart on a market whose volume feed behaves differently.
Building it faster
Coding the MFI by hand is a good way to see how volume weighting changes an otherwise RSI-like oscillator. When you already know the rules you want, describing them in plain English is faster than assembling the script. A tool like PineScripter generates the v6 code and, when it does not compile, reads TradingView's error and fixes it automatically rather than making you copy it back and forth. You can compare that workflow against other options in our roundup of the best AI Pine Script generators.
The takeaway
The Money Flow Index is a volume-weighted momentum oscillator delivered by one function, ta.mfi(), that reads much like the RSI but respects how much traded behind each move. It adds the most value when volume and price disagree, and the least when volume is steady, and it depends on trustworthy volume data to mean anything. Build it, decide whether the volume weighting earns its place over a plain RSI for your market, and test the result honestly.
Disclaimer: PineScripter is a coding tool for Pine Script development. It does not provide financial advice and does not guarantee trading profits. Always backtest strategies thoroughly and understand the risks before live trading.