CMF in Python — Coding It from Scratch (pandas)

Money flow multiplier, money flow volume, and the windowed sum

CMF computed in Python
CMF computed in Python

Chaikin Money Flow is three clean steps in pandas — a multiplier, a volume weight, and a normalized rolling sum, as the explainer covered. Here it is, with the flat-bar guard that most implementations forget.

What you’ll need

  • Python 3.9+, pandas/numpy
  • high, low, close, volume series.

From scratch

import numpy as np
import pandas as pd


def cmf(high, low, close, volume, period: int = 20):
    rng = (high - low).replace(0, np.nan)                 # guard flat bars
    mfm = ((close - low) - (high - close)) / rng          # money flow multiplier
    mfm = mfm.fillna(0.0)                                  # flat bar -> neutral

    mfv = mfm * volume                                     # money flow volume
    return (mfv.rolling(period).sum()
            / volume.rolling(period).sum()).rename("cmf")

mfm is the close-location value (+1 at the high, −1 at the low), mfv weights it by volume, and dividing the rolling sums normalizes CMF into its bounded, zero- centered range — the oscillator from the output chart.

A confirmation filter

CMF earns its keep confirming price:

c = cmf(df["high"], df["low"], df["close"], df["volume"])
df["accum"] = c > 0.05      # meaningful buying pressure
df["distrib"] = c < -0.05   # meaningful selling pressure
# e.g. only take long entries while accumulation is present:
df["long_ok"] = df["accum"]

Use long_ok to gate another entry signal and test whether it helps in AlgoGen.

Gotchas

  • Flat-bar guard. When high == low, the multiplier divides by zero. replace(0, np.nan) then fillna(0.0) sets those bars neutral — the standard fix.
  • Sum, then divide. CMF divides the sum of money flow volume by the sum of volume over the window — not the average of per-bar ratios. Order matters.
  • Gap blindness. The multiplier only sees inside each bar’s range, so overnight gaps don’t register. Know this limitation; don’t expect CMF to catch gap moves.

The lazy one-liner

import pandas_ta as ta
df["cmf20"] = ta.cmf(df["high"], df["low"], df["close"], df["volume"], length=20)

Same indicator elsewhere: MQL5, Pine Script, EasyLanguage, NinjaScript.


This post is educational, not financial advice. Indicators describe the past; they don’t predict the future. Backtest anything before you risk real money on it.

Sources and further reading

  1. Windowing operations (pandas documentation)

Historical research from the Algogen archive. Not investment advice.

Blog

Have a strategy idea?

Describe it in plain English, preview where your rules fire, then decide whether the evidence is worth a backtest.

Keep me postedHow it works