Money Flow Index (MFI)
period = 14 Overview
The Money Flow Index measures buying and selling pressure by incorporating both price and volume into an oscillator that ranges from 0 to 100. MFI calculates money flow as typical price multiplied by volume for each period, then classifies this flow as positive when price rises or negative when it falls, ultimately creating a ratio that reveals whether money is flowing into or out of an asset. Values above 80 suggest overbought conditions where selling pressure may emerge, while readings below 20 indicate oversold territory where buying interest could materialize. Traders often describe MFI as a volume weighted RSI because it applies the RSI formula to money flow data rather than just price, making it particularly valuable for confirming breakouts where volume validation is crucial. What distinguishes MFI from pure momentum oscillators is its ability to detect divergences between price action and actual money flow, exposing situations where price advances on weak volume or declines despite strong accumulation.
Implementation Examples
Compute MFI from slices or candles:
use vectorta::indicators::mfi::{mfi, MfiInput, MfiParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
// Using slices: typical price (HLC/3 recommended) and volume
let tp = vec![/* typical prices */];
let vol = vec![/* volumes */];
let params = MfiParams { period: Some(14) }; // default
let input = MfiInput::from_slices(&tp, &vol, params);
let result = mfi(&input)?;
// Using Candles with defaults: source="hlc3", period=14
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = MfiInput::with_default_candles(&candles);
let result = mfi(&input)?;
// Access values
for v in result.values { println!("MFI: {}", v); } API Reference
Input Methods ▼
// From slices (typical price and volume)
MfiInput::from_slices(&[f64], &[f64], MfiParams) -> MfiInput
// From candles with custom typical price source
MfiInput::from_candles(&Candles, &str, MfiParams) -> MfiInput
// From candles with defaults (source="hlc3", period=14)
MfiInput::with_default_candles(&Candles) -> MfiInput Parameters Structure ▼
pub struct MfiParams {
pub period: Option<usize>, // Default: 14
} Output Structure ▼
pub struct MfiOutput {
pub values: Vec<f64>, // MFI values (0..=100)
} Validation, Warmup & NaNs ▼
period > 0andperiod ≤ data_len; volume length must equal typical price length.- First valid output at
first_valid_idx + period − 1; all earlier indices areNaN. - If no finite pair exists:
MfiError::AllValuesNaN. If insufficient valid data after first finite:MfiError::NotEnoughValidData. - If denominator ≈ 0 (e.g., zero volume or flat price over the window), output is
0.0after warmup.
Error Handling ▼
#[derive(Debug, Error)]
pub enum MfiError {
#[error("mfi: Empty data provided.")]
EmptyData,
#[error("mfi: Invalid period: period = {period}, data length = {data_len}")]
InvalidPeriod { period: usize, data_len: usize },
#[error("mfi: Not enough valid data: needed = {needed}, valid = {valid}")]
NotEnoughValidData { needed: usize, valid: usize },
#[error("mfi: All values are NaN.")]
AllValuesNaN,
}
// Example handling
match mfi(&input) {
Ok(out) => use_values(out.values),
Err(MfiError::EmptyData) => eprintln!("empty data"),
Err(MfiError::InvalidPeriod { period, data_len }) => { /* fix params */ }
Err(MfiError::NotEnoughValidData { needed, valid }) => { /* ensure enough data */ }
Err(MfiError::AllValuesNaN) => { /* sanitize inputs */ }
} Python Bindings
Basic Usage ▼
Calculate MFI from NumPy arrays (defaults: period=14):
import numpy as np
from vectorta import mfi
# Typical price (HLC/3 recommended) and volume
tp = np.array([...], dtype=np.float64)
vol = np.array([...], dtype=np.float64)
# Default period
values = mfi(tp, vol, period=14)
# Specify kernel for performance
values = mfi(tp, vol, period=20, kernel="avx2")
print(values) # NumPy array Streaming Real-time Updates ▼
from vectorta import MfiStream
stream = MfiStream(period=14)
for tp_i, vol_i in zip(tp_stream, vol_stream):
val = stream.update(tp_i, vol_i)
if val is not None:
use(val) Batch Parameter Optimization ▼
import numpy as np
from vectorta import mfi_batch
tp = np.array([...], dtype=np.float64)
vol = np.array([...], dtype=np.float64)
# (start, end, step)
results = mfi_batch(tp, vol, period_range=(8, 24, 4), kernel="auto")
print(results["values"].shape) # (num_periods, len)
print(results["periods"]) # list of tested periods CUDA Acceleration ▼
CUDA support for MFI is currently under development. The API will follow the same pattern as other CUDA-enabled indicators.
# Coming soon: CUDA-accelerated MFI calculations
# Expected patterns mirror other indicators (batch sweeps and multi-series). JavaScript/WASM Bindings
Basic Usage ▼
Calculate MFI in JavaScript/TypeScript:
import { mfi_js } from 'vectorta-wasm';
const tp = new Float64Array([/* typical prices (hlc3) */]);
const vol = new Float64Array([/* volumes */]);
const values = mfi_js(tp, vol, 14);
console.log('MFI values:', values); Memory-Efficient Operations ▼
Use zero-copy buffers for large arrays:
import { mfi_alloc, mfi_free, mfi_into, memory } from 'vectorta-wasm';
const len = tp.length;
const tpPtr = mfi_alloc(len);
const volPtr = mfi_alloc(len);
const outPtr = mfi_alloc(len);
// Copy inputs into WASM memory
new Float64Array(memory.buffer, tpPtr, len).set(tp);
new Float64Array(memory.buffer, volPtr, len).set(vol);
// Compute into pre-allocated buffer
mfi_into(tpPtr, volPtr, outPtr, len, 14);
// Read results (copy out)
const mfiVals = new Float64Array(memory.buffer, outPtr, len).slice();
mfi_free(tpPtr, len);
mfi_free(volPtr, len);
mfi_free(outPtr, len); Batch Processing ▼
Sweep periods using the unified JS API:
import { mfi_batch } from 'vectorta-wasm';
const cfg = { period_range: [8, 24, 4] };
const res = mfi_batch(tp, vol, cfg);
// res: { values: Float64Array, combos: Array<{ period?: number }>, rows: number, cols: number }
console.log(res.rows, res.cols);
// Extract first combo's series
const firstRow = res.values.slice(0, res.cols); Performance Analysis
Across sizes, Rust CPU runs about 5.58× faster than Tulip C in this benchmark.
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05