Money Flow Index (MFI)

Haiyue
10min

I. What is MFI

The Money Flow Index (MFI) is a technical analysis indicator jointly developed by Gene Quong and Avrum Soudack. MFI was first introduced in technical analysis literature in 1989 and has since gained widespread recognition in the trading community.

MFI belongs to the Volume Oscillator category of indicators and is often referred to as the “Volume-Weighted RSI” because it incorporates a volume factor on top of the traditional RSI framework. Unlike RSI, which is based solely on price movements, MFI simultaneously considers the direction of price changes and the accompanying volume, providing a more comprehensive measure of the intensity of money flowing in and out.

The default parameter is a period of n=14n = 14, and the output value ranges from [0,100][0, 100].

Tip

The key difference between MFI and RSI lies in the introduction of volume. For the same magnitude of price change, if it is accompanied by larger volume, MFI will produce a more extreme reading. This allows MFI to better capture market conditions where price and volume move in tandem.


II. Mathematical Principles and Calculation

2.1 Core Formulas

Step 1: Calculate the Typical Price

TPt=Ht+Lt+Ct3TP_t = \frac{H_t + L_t + C_t}{3}

Where HtH_t, LtL_t, and CtC_t are the high, low, and close prices on day tt, respectively.

Step 2: Calculate the Raw Money Flow

RMFt=TPt×VtRMF_t = TP_t \times V_t

Where VtV_t is the volume on day tt.

Step 3: Classify Positive and Negative Money Flow

Positive MFt={RMFtif TPt>TPt10otherwise\text{Positive MF}_t = \begin{cases} RMF_t & \text{if } TP_t > TP_{t-1} \\ 0 & \text{otherwise} \end{cases} Negative MFt={RMFtif TPt<TPt10otherwise\text{Negative MF}_t = \begin{cases} RMF_t & \text{if } TP_t < TP_{t-1} \\ 0 & \text{otherwise} \end{cases}
Note

When TPt=TPt1TP_t = TP_{t-1}, the money flow for that day is counted as neither positive nor negative.

Step 4: Calculate the Money Flow Ratio

MR=i=0n1Positive MFtii=0n1Negative MFtiMR = \frac{\sum_{i=0}^{n-1} \text{Positive MF}_{t-i}}{\sum_{i=0}^{n-1} \text{Negative MF}_{t-i}}

Step 5: Calculate the Money Flow Index (MFI)

MFI=1001001+MRMFI = 100 - \frac{100}{1 + MR}

2.2 Calculation Steps Summary

  1. Calculate the daily Typical Price TPTP
  2. Multiply TPTP by volume to get the Raw Money Flow RMFRMF
  3. Compare the current day’s TPTP with the previous day’s TPTP and classify RMFRMF as positive or negative money flow
  4. Sum the positive and negative money flows over the last nn days (default 14)
  5. Calculate the Money Flow Ratio MRMR, then plug into the formula to get MFIMFI

III. Python Implementation

import numpy as np
import pandas as pd


def money_flow_index(high: pd.Series, low: pd.Series,
                     close: pd.Series, volume: pd.Series,
                     period: int = 14) -> pd.Series:
    """
    Calculate the Money Flow Index (MFI).

    Parameters:
        high   : Series of high prices
        low    : Series of low prices
        close  : Series of close prices
        volume : Series of volume
        period : Lookback period, default 14

    Returns:
        Series of MFI values, range [0, 100]
    """
    # 1. Typical Price
    tp = (high + low + close) / 3.0

    # 2. Raw Money Flow
    raw_mf = tp * volume

    # 3. Determine money flow direction
    tp_diff = tp.diff()
    positive_mf = pd.Series(np.where(tp_diff > 0, raw_mf, 0.0), index=tp.index)
    negative_mf = pd.Series(np.where(tp_diff < 0, raw_mf, 0.0), index=tp.index)

    # 4. Rolling sum
    positive_sum = positive_mf.rolling(window=period).sum()
    negative_sum = negative_mf.rolling(window=period).sum()

    # 5. Money Flow Ratio and MFI
    money_ratio = positive_sum / negative_sum.replace(0, np.nan)
    mfi = 100.0 - 100.0 / (1.0 + money_ratio)

    return mfi


# ============ Usage Example ============
if __name__ == '__main__':
    np.random.seed(42)
    n_days = 120

    # Generate simulated OHLCV data
    base_price = 50 + np.cumsum(np.random.randn(n_days) * 0.5)
    df = pd.DataFrame({
        'open':   base_price + np.random.randn(n_days) * 0.3,
        'high':   base_price + np.abs(np.random.randn(n_days) * 1.0),
        'low':    base_price - np.abs(np.random.randn(n_days) * 1.0),
        'close':  base_price,
        'volume': np.random.randint(50000, 500000, n_days).astype(float)
    })

    # Calculate MFI
    df['mfi'] = money_flow_index(df['high'], df['low'], df['close'],
                                 df['volume'], period=14)

    print("=== MFI Calculation Results (last 15 rows) ===")
    print(df[['close', 'volume', 'mfi']].tail(15).to_string())

    # Generate trading signals
    df['signal'] = np.where(df['mfi'] > 80, 'Overbought',
                   np.where(df['mfi'] < 20, 'Oversold', 'Neutral'))
    print("\n=== Signal Statistics ===")
    print(df['signal'].value_counts())

IV. Problems the Indicator Solves

4.1 Price-Volume Confirmation Analysis

MFI incorporates volume into the overbought/oversold assessment framework, answering a critical question: Is the current price movement supported by sufficient capital flow? If price rises but MFI fails to rise accordingly, the rally lacks volume confirmation and its sustainability is questionable.

4.2 Overbought/Oversold Detection

  • MFI > 80: The market may be overbought. After sustained capital inflows, the potential for profit-taking increases.
  • MFI < 20: The market may be oversold. After significant capital outflows, prices may have been pushed down excessively.
Warning

Similar to RSI, MFI can remain in overbought or oversold territory for extended periods during strong trends. Taking contrarian trades based solely on MFI readings carries significant risk. It is advisable to combine MFI with trend analysis.

4.3 Divergence Signals

MFI divergences are among its most valuable signals:

  • Bearish Divergence: Price makes a new high, but MFI does not — upward momentum is weakening, a potential top may form.
  • Bullish Divergence: Price makes a new low, but MFI does not — downward momentum is weakening, a potential bottom may form.

Because MFI incorporates volume information, its divergence signals are generally more reliable than pure RSI divergences.

4.4 Typical Trading Strategies

  1. Overbought/Oversold Strategy: Sell when MFI drops back below 80; buy when MFI rises back above 20.
  2. Divergence Strategy: Prepare to go short on bearish divergence; prepare to go long on bullish divergence.
  3. Centerline Crossover Strategy: MFI crossing above 50 is a bullish signal; crossing below 50 is a bearish signal.
  4. Failure Swing: Similar to RSI failure swings, MFI forms a high/low in the overbought/oversold zone and fails to break through.

V. Advantages, Disadvantages, and Use Cases

Advantages

AdvantageDescription
Combines price and volumeConsiders both price movement and volume, providing richer information
Reliable divergence signalsBecause it includes a volume factor, MFI divergences have higher predictive value than RSI divergences
Bounded indicatorOutput is fixed within [0,100][0, 100], making it easy to set standardized trading thresholds
Simple calculationClear logic, easy to understand and implement

Disadvantages

DisadvantageDescription
Lagging natureThe 14-period rolling window introduces some signal delay
Requires volume dataLimited applicability in markets without standardized volume data such as forex
False signals in strong trendsLike RSI, overbought/oversold signals may fail frequently in one-directional trends
Sensitive to volume anomaliesSudden volume spikes (e.g., ex-dividend dates, IPO days) can cause significant indicator fluctuations

Use Cases

  • Best suited for: Stock and futures markets with reliable volume data; overbought/oversold detection in range-bound markets
  • Moderately suited for: Use as a supplementary confirmation tool alongside trend indicators
  • Not suited for: Forex markets (no centralized volume data); instruments with extremely low liquidity

Comparison with Similar Indicators

IndicatorVolumeOutput RangeCharacteristics
MFIIncorporated0—100Price-volume composite overbought/oversold indicator
RSINot considered0—100Momentum indicator based solely on price movement
OBVCumulativeUnboundedFocuses on cumulative volume trends, not an oscillator
CMFPeriod sum-1 to 1Measures buying/selling pressure over a period
Tip

Parameter Tuning Advice: The default 14-period is suitable for most daily chart analyses. Short-term traders may shorten it to 10 for more responsive signals; long-term investors may extend it to 21 to filter out noise. Overbought/oversold thresholds can be adjusted based on the characteristics of the instrument — use 90/10 for highly volatile instruments and 70/30 for less volatile ones.