Chaikin Money Flow (CMF)

Haiyue
10min

I. What is CMF

Chaikin Money Flow (CMF) is a technical analysis indicator developed by American financial analyst Marc Chaikin. CMF builds upon Chaikin’s own Accumulation/Distribution Line (A/D Line), but transforms the cumulative A/D Line into a bounded, period-based oscillator indicator.

CMF belongs to the Volume Oscillator category of indicators, with a default period parameter of n=20n = 20 (approximately one month of trading days). It measures the strength of buying and selling pressure over a given period by computing the volume-weighted close position within a fixed window.

The core idea behind CMF is: within a given period, if most trading days see the price close in the upper half of the intraday range accompanied by large volume, then CMF is positive, indicating that buying pressure dominates; conversely, CMF is negative, indicating that selling pressure dominates.

Tip

CMF can be viewed as a “normalized version” of the A/D Line — by dividing by total volume, it becomes bounded and thus allows for horizontal comparison across different instruments and time periods.


II. Mathematical Principles and Calculation

2.1 Core Formulas

Step 1: Calculate the Close Location Value (CLV)

CLVt=(CtLt)(HtCt)HtLt=2CtLtHtHtLtCLV_t = \frac{(C_t - L_t) - (H_t - C_t)}{H_t - L_t} = \frac{2C_t - L_t - H_t}{H_t - L_t}

CLV ranges from [1,+1][-1, +1].

Step 2: Calculate Chaikin Money Flow (CMF)

CMFt=i=0n1CLVti×Vtii=0n1VtiCMF_t = \frac{\sum_{i=0}^{n-1} CLV_{t-i} \times V_{t-i}}{\sum_{i=0}^{n-1} V_{t-i}}

Where nn is the lookback period (default 20) and VtV_t is the volume on day tt.

2.2 Intuitive Understanding

The CMF calculation logic can be understood as follows:

  • The numerator CLV×Volume\sum CLV \times Volume is the sum of “directional weighted volume,” with large contributions from days with high volume and high closing positions
  • The denominator Volume\sum Volume is the total volume sum, serving as a normalization factor
  • The final result represents: the volume-weighted average capital flow direction over the past nn days

The theoretical range of CMF is [1,+1][-1, +1], but extreme values are rarely reached in practice.

Note

The key difference between CMF and the A/D Line: the A/D Line accumulates continuously from the starting point, with values growing ever larger or smaller; CMF is calculated as a ratio within a fixed window, always remaining within a bounded range. This makes CMF more suitable as a direct basis for trading signals.

2.3 Calculation Steps

  1. Calculate CLV for each day: (2CLH)/(HL)(2C - L - H) / (H - L)
  2. Calculate CLV x Volume for each day (directional money flow)
  3. Within a rolling window of nn, sum CLV x Volume and Volume separately
  4. Divide the two sums to get CMF

III. Python Implementation

import numpy as np
import pandas as pd


def chaikin_money_flow(high: pd.Series, low: pd.Series,
                       close: pd.Series, volume: pd.Series,
                       period: int = 20) -> pd.Series:
    """
    Calculate Chaikin Money Flow (CMF).

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

    Returns:
        Series of CMF values, theoretical range [-1, +1]
    """
    # 1. Calculate CLV
    hl_range = high - low
    clv = pd.Series(
        np.where(hl_range != 0,
                 (2.0 * close - low - high) / hl_range,
                 0.0),
        index=close.index
    )

    # 2. CLV x Volume (directional money flow)
    mf_volume = clv * volume

    # 3. Rolling sum
    mf_sum = mf_volume.rolling(window=period).sum()
    vol_sum = volume.rolling(window=period).sum()

    # 4. CMF = money flow sum / volume sum
    cmf = mf_sum / vol_sum.replace(0, np.nan)

    return cmf


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

    # Generate simulated OHLCV data
    base_price = 60 + np.cumsum(np.random.randn(n_days) * 0.4)
    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 + np.random.randn(n_days) * 0.2,
        'volume': np.random.randint(80000, 600000, n_days).astype(float)
    })

    # Ensure high >= close >= low
    df['high'] = df[['open', 'high', 'close']].max(axis=1)
    df['low'] = df[['open', 'low', 'close']].min(axis=1)

    # Calculate CMF
    df['cmf'] = chaikin_money_flow(df['high'], df['low'], df['close'],
                                   df['volume'], period=20)

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

    # Generate trading signals
    df['pressure'] = np.where(df['cmf'] > 0.05, 'Buying Pressure',
                    np.where(df['cmf'] < -0.05, 'Selling Pressure', 'Neutral'))
    print("\n=== Buying/Selling Pressure Statistics ===")
    print(df['pressure'].value_counts())

    # CMF zero-line crossover signals
    df['cmf_prev'] = df['cmf'].shift(1)
    df['cross_signal'] = np.where(
        (df['cmf'] > 0) & (df['cmf_prev'] <= 0), 'Bullish Cross (above zero)',
        np.where(
            (df['cmf'] < 0) & (df['cmf_prev'] >= 0), 'Bearish Cross (below zero)',
            'No Signal'))
    crosses = df[df['cross_signal'] != 'No Signal'][['close', 'cmf', 'cross_signal']]
    print("\n=== Zero-Line Crossover Signals ===")
    print(crosses.to_string())

IV. Problems the Indicator Solves

4.1 Quantifying Buying/Selling Pressure

CMF transforms the abstract concept of “buying/selling pressure” into a clear numerical indicator:

  • CMF > 0: Buying pressure dominated over the past nn days — net capital inflow
  • CMF < 0: Selling pressure dominated over the past nn days — net capital outflow
  • Larger absolute CMF value: Stronger pressure in the corresponding direction

4.2 Zero-Line Crossover Signals

CMF crossing the zero line is its most basic trading signal:

  • CMF crosses from negative to positive (above zero): Buying forces begin to dominate, bullish signal
  • CMF crosses from positive to negative (below zero): Selling forces begin to dominate, bearish signal

4.3 Trend Confirmation and Divergence

  • Price rising + CMF > 0: The uptrend is supported by capital, the trend is healthy
  • Price rising + CMF < 0: The rally lacks capital support, possibly a false rally
  • Price falling + CMF > 0: Capital is still flowing in during the decline, possibly setting up a reversal
Warning

CMF tends to oscillate around the zero line during sideways consolidation, generating frequent false signals. It is recommended to set a buffer zone (e.g., ±0.05\pm 0.05) and only confirm signals when CMF clearly breaks through the buffer.

4.4 Typical Trading Strategies

  1. Zero-Line Crossover Strategy: Buy when CMF crosses above zero, sell when it crosses below zero
  2. Strength Filter Strategy: Only go long when CMF > +0.10 and short when CMF < -0.10 (filtering weak signals)
  3. Trend Confirmation Strategy: Use CMF to confirm price trends — only enter when CMF direction aligns with the trend direction
  4. Multi-Timeframe Strategy: When daily CMF is positive, look for long opportunities on the hourly timeframe

V. Advantages, Disadvantages, and Use Cases

Advantages

AdvantageDescription
Bounded indicatorValues range within [1,+1][-1, +1], making it easy to set standardized thresholds and compare across instruments
Clear signalsAbove zero means buying pressure, below zero means selling pressure — judgment is intuitive
Combines price and volumeSimultaneously considers intraday price position and volume magnitude
Non-cumulativeUses a fixed window, does not grow indefinitely like the A/D Line, easier to analyze

Disadvantages

DisadvantageDescription
Window length sensitivityDifferent period parameters may produce different signals
Noisy during sideways marketsTends to generate frequent false zero-line crossovers in trendless markets
Ignores gapsLike the A/D Line, does not account for opening price and gap information
Extreme values are rareIn practice, it rarely reaches ±1\pm 1; most of the time it stays within ±0.3\pm 0.3

Use Cases

  • Best suited for: Medium-term trend confirmation; assessing capital flow direction before and after breakouts
  • Moderately suited for: Use alongside trend-following indicators to filter false breakouts
  • Not suited for: Short-term high-frequency trading (the 20-period window is relatively slow); narrow range-bound markets

Comparison with Similar Indicators

IndicatorCalculation MethodOutput RangeCharacteristics
CMFCLV-weighted period average[1,+1][-1, +1]Bounded, suitable for cross-instrument comparison
A/D LineCLV x Volume cumulativeUnboundedLong-term cumulative trend, absolute values are meaningless
MFITP-weighted RSI structure[0,100][0, 100]Has overbought/oversold zone concepts
OBVFull volume add/subtractUnboundedSimplest but crudest
Tip

Parameter Tuning Advice: The default 20-period (one month) is suitable for daily chart medium-term analysis. For more responsive signals, shorten to 10 periods, but be aware of increased noise. For weekly analysis, keep the 20-period unchanged (representing approximately 5 months). The zero-line crossover buffer threshold should be adjusted based on the instrument’s volatility — use ±0.08\pm 0.08 for highly volatile instruments and ±0.03\pm 0.03 for less volatile ones.