Stochastic Money Flow Index

Parameters: stoch_k_length = 14 | stoch_k_smooth = 3 | stoch_d_smooth = 3 | mfi_length = 14

Overview

Stochastic Money Flow Index begins with a money flow style measure that combines price movement and traded volume, then normalizes that series through a stochastic window and smooths it into a K and D pair. The result behaves like an oscillator, but it retains the volume-awareness of the underlying money flow calculation rather than treating price alone as the only input.

In VectorTA the indicator accepts either explicit source and volume slices or candle data, supports a streaming state machine for bar-by-bar updates, and exposes batch sweeps across the stochastic K length, both smoothing stages, and the base MFI lookback. That makes it practical for testing how much volume sensitivity you want in short-term oscillator work.

Defaults: `stoch_k_length = 14`, `stoch_k_smooth = 3`, `stoch_d_smooth = 3`, and `mfi_length = 14`.

Implementation Examples

Compute stochastic money flow from explicit source and volume slices or from candle data.

use vector_ta::indicators::stochastic_money_flow_index::{
    stochastic_money_flow_index,
    StochasticMoneyFlowIndexInput,
    StochasticMoneyFlowIndexParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};

let direct = stochastic_money_flow_index(&StochasticMoneyFlowIndexInput::from_slices(
    &close,
    &volume,
    StochasticMoneyFlowIndexParams {
        stoch_k_length: Some(14),
        stoch_k_smooth: Some(3),
        stoch_d_smooth: Some(3),
        mfi_length: Some(14),
    },
))?;

let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let from_candles = stochastic_money_flow_index(
    &StochasticMoneyFlowIndexInput::with_default_candles(&candles),
)?;

println!("latest k = {:?}", direct.k.last());
println!("latest d = {:?}", direct.d.last());
println!("candle d = {:?}", from_candles.d.last());

API Reference

Input Methods
StochasticMoneyFlowIndexInput::from_candles(&Candles, "close", StochasticMoneyFlowIndexParams)
    -> StochasticMoneyFlowIndexInput

StochasticMoneyFlowIndexInput::from_slices(&[f64], &[f64], StochasticMoneyFlowIndexParams)
    -> StochasticMoneyFlowIndexInput

StochasticMoneyFlowIndexInput::with_default_candles(&Candles)
    -> StochasticMoneyFlowIndexInput
Parameters Structure
pub struct StochasticMoneyFlowIndexParams {
    pub stoch_k_length: Option<usize>,  // default 14
    pub stoch_k_smooth: Option<usize>,  // default 3
    pub stoch_d_smooth: Option<usize>,  // default 3
    pub mfi_length: Option<usize>,      // default 14
}
Output Structure
pub struct StochasticMoneyFlowIndexOutput {
    pub k: Vec<f64>,
    pub d: Vec<f64>,
}
Validation, Lengths & NaNs
  • The source and volume slices must have matching lengths and contain enough valid values for the resolved stochastic and money-flow windows.
  • stoch_k_length, stoch_k_smooth, stoch_d_smooth, and mfi_length are validated independently against the usable data length.
  • Direct evaluation rejects empty input, mismatched source and volume arrays, and all-NaN input.
  • The stream returns None until enough valid source and volume bars accumulate to form both K and D.
  • Output buffers must match the source length or the indicator returns the documented output-length mismatch error.
  • Batch mode validates all sweep ranges and rejects non-batch kernels.
Builder, Streaming & Batch APIs
StochasticMoneyFlowIndexBuilder::new()
    .stoch_k_length(usize)
    .stoch_k_smooth(usize)
    .stoch_d_smooth(usize)
    .mfi_length(usize)
    .kernel(Kernel)
    .apply(&Candles)
    .apply_slices(&[f64], &[f64])
    .into_stream()

StochasticMoneyFlowIndexStream::try_new(params)
stream.update(source, volume) -> Option<(f64, f64)>

StochasticMoneyFlowIndexBatchBuilder::new()
    .stoch_k_length_range((start, end, step))
    .stoch_k_smooth_range((start, end, step))
    .stoch_d_smooth_range((start, end, step))
    .mfi_length_range((start, end, step))
    .kernel(Kernel)
    .apply_slices(&[f64], &[f64])
    .apply_candles(&Candles, "close")

Python Bindings

Python exposes a direct function, a stream class, and a batch helper that returns K and D matrices plus the resolved stochastic and money-flow axes.

from vector_ta import (
    stochastic_money_flow_index,
    stochastic_money_flow_index_batch,
    StochasticMoneyFlowIndexStream,
)

k, d = stochastic_money_flow_index(
    close,
    volume,
    stoch_k_length=14,
    stoch_k_smooth=3,
    stoch_d_smooth=3,
    mfi_length=14,
)

stream = StochasticMoneyFlowIndexStream(
    stoch_k_length=14,
    stoch_k_smooth=3,
    stoch_d_smooth=3,
    mfi_length=14,
)
point = stream.update(close[-1], volume[-1])

batch = stochastic_money_flow_index_batch(
    close,
    volume,
    stoch_k_length_range=(10, 14, 2),
    stoch_k_smooth_range=(3, 5, 1),
    stoch_d_smooth_range=(3, 5, 1),
    mfi_length_range=(10, 18, 4),
)

print(batch["k"].shape)
print(batch["mfi_lengths"])

JavaScript/WASM Bindings

The WASM layer exposes a direct indicator call, a batch helper, and low-level into-buffer functions for memory-sensitive consumers.

import init, {
  stochastic_money_flow_index_js,
  stochastic_money_flow_index_batch_js,
  stochastic_money_flow_index_alloc,
  stochastic_money_flow_index_free,
  stochastic_money_flow_index_into,
  stochastic_money_flow_index_batch_into,
} from "vector-ta-wasm";

await init();

const single = stochastic_money_flow_index_js(close, volume, 14, 3, 3, 14);
console.log(single.k, single.d);

const batch = stochastic_money_flow_index_batch_js(close, volume, {
  stoch_k_length_range: [10, 14, 2],
  stoch_k_smooth_range: [3, 5, 1],
  stoch_d_smooth_range: [3, 5, 1],
  mfi_length_range: [10, 18, 4],
});

const ptrIn = stochastic_money_flow_index_alloc(close.length * 2);
const ptrOut = stochastic_money_flow_index_alloc(close.length * 2);
stochastic_money_flow_index_into(close, volume, ptrOut, close.length, 14, 3, 3, 14);
stochastic_money_flow_index_free(ptrIn, close.length * 2);
stochastic_money_flow_index_free(ptrOut, close.length * 2);

CUDA Bindings (Rust)

Additional details for the CUDA bindings can be found inside the VectorTA repository.

Performance Analysis

Comparison:
View:
Placeholder data (no recorded benchmarks for this indicator)

Across sizes, Rust CPU runs about 1.14× faster than Tulip C in this benchmark.

Loading chart...

AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU)

Related Indicators