TickAtlas
Guide 11 min read · March 28, 2026

Volume Analysis with OBV and MFI: A Developer's Guide

How to use On-Balance Volume and Money Flow Index to confirm trends and spot reversals. Includes API integration examples and practical trading signals.

CG
By the TickAtlas team

Why Volume Matters

Price tells you what happened. Volume tells you how much conviction was behind it. A breakout on high volume is far more likely to sustain than one on thin volume. Volume indicators quantify this relationship, giving your algorithms an additional confirmation layer.

The TickAtlas API provides two key volume indicators: On-Balance Volume (OBV) for cumulative volume flow, and Money Flow Index (MFI) for a volume-weighted momentum oscillator.

On-Balance Volume (OBV)

OBV was introduced by Joe Granville in 1963. The logic is simple: on up days, the full volume is added to a running total. On down days, the full volume is subtracted. The direction of OBV, not its absolute value, is what matters.

If Close > Previous Close:
    OBV = Previous OBV + Volume
If Close < Previous Close:
    OBV = Previous OBV - Volume
If Close == Previous Close:
    OBV = Previous OBV

OBV Rising + Price Rising

Healthy uptrend confirmed by volume. Stay long.

OBV Falling + Price Rising

Bearish divergence. The rally lacks conviction and may reverse.

Fetching OBV via API

curl -H "X-API-Key: YOUR_API_KEY" \
  "https://tickatlas.com/v1/indicator?symbol=XAUUSD&indicator=OBV&timeframe=H4"

Response:

json
{
  "success": true,
  "data": {
    "symbol": "XAUUSD",
    "timeframe": "H4",
    "indicator": "OBV",
    "values": {
      "obv": 1548230
    },
    "ohlcv": {
      "open": 2185.40,
      "high": 2192.80,
      "low": 2181.20,
      "close": 2190.50,
      "volume": 28450
    },
    "timestamp": "2026-03-28T12:00:00Z"
  }
}

Money Flow Index (MFI)

MFI is often called the "volume-weighted RSI." It uses both price and volume to measure buying and selling pressure. Like RSI, it oscillates between 0 and 100, with readings above 80 indicating overbought conditions and below 20 indicating oversold.

Typical Price = (High + Low + Close) / 3
Raw Money Flow = Typical Price * Volume

If Typical Price > Previous Typical Price:
    Positive Money Flow += Raw Money Flow
Else:
    Negative Money Flow += Raw Money Flow

Money Flow Ratio = Positive MF / Negative MF  (over 14 periods)
MFI = 100 - (100 / (1 + Money Flow Ratio))
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://tickatlas.com/v1/indicator?symbol=XAUUSD&indicator=MFI_14&timeframe=H4"
json
{
  "success": true,
  "data": {
    "symbol": "XAUUSD",
    "timeframe": "H4",
    "indicator": "MFI_14",
    "values": {
      "mfi": 72.34
    },
    "signal": "neutral",
    "timestamp": "2026-03-28T12:00:00Z"
  }
}

Python: Volume Confirmation System

Here is a complete system that uses OBV trend direction and MFI levels to confirm or reject trade signals from other indicators:

python
import requests
from typing import Optional

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://tickatlas.com/v1"

def fetch_indicator(symbol: str, indicator: str, timeframe: str) -> dict:
    resp = requests.get(
        f"{BASE_URL}/indicator",
        headers={"X-API-Key": API_KEY},
        params={"symbol": symbol, "indicator": indicator, "timeframe": timeframe},
    )
    resp.raise_for_status()
    return resp.json()["data"]

def volume_confirmation(
    symbol: str, timeframe: str, proposed_direction: str
) -> dict:
    """Check if volume supports a proposed trade direction."""
    obv_data = fetch_indicator(symbol, "OBV", timeframe)
    mfi_data = fetch_indicator(symbol, "MFI_14", timeframe)

    obv = obv_data["values"]["obv"]
    mfi = mfi_data["values"]["mfi"]

    # For a real system, compare OBV to its own moving average
    # Here we use the MFI level as primary and OBV as secondary
    confirms = False
    reasons = []

    if proposed_direction == "long":
        if mfi < 80:
            confirms = True
            reasons.append(f"MFI at {mfi:.1f} — not overbought")
        else:
            reasons.append(f"MFI at {mfi:.1f} — OVERBOUGHT, caution")

        if mfi < 30:
            reasons.append("MFI oversold — strong buy signal from volume")

    elif proposed_direction == "short":
        if mfi > 20:
            confirms = True
            reasons.append(f"MFI at {mfi:.1f} — not oversold")
        else:
            reasons.append(f"MFI at {mfi:.1f} — OVERSOLD, caution")

        if mfi > 80:
            reasons.append("MFI overbought — strong sell signal from volume")

    return {
        "symbol": symbol,
        "direction": proposed_direction,
        "volume_confirms": confirms,
        "mfi": mfi,
        "obv": obv,
        "reasons": reasons,
    }

# Example: check if a long signal on XAUUSD has volume support
result = volume_confirmation("XAUUSD", "H4", "long")
print(f"Volume confirms: {result['volume_confirms']}")
for reason in result["reasons"]:
    print(f"  - {reason}")

OBV vs MFI: When to Use Each

Use OBV for trend confirmation

OBV is best at confirming whether a trend has genuine buying or selling pressure behind it. Compare OBV direction with price direction to spot divergences.

Use MFI for overbought/oversold

MFI works like RSI but includes volume weighting. It is better at identifying exhaustion points where buying or selling pressure is running out.

Use both together for confluence

When OBV confirms the trend direction and MFI is not at an extreme, you have strong volume confluence for a continuation trade.

Related Reading

Try this with live data

Every account gets $2.50 in free PAYG credits. No card required — paste your API key and run the code above against live broker data.