Mahalanobis Distance Outlier Oscillator (MDOO) – Find the Hidden Extremes
Posted: Tue Aug 11, 2026 9:23 pm
Hey fellow scalpers,
We all use standard deviation (like Bollinger Bands) or ATR to measure volatility. But standard deviation only looks at one variable in a vacuum. What if we want to know when the relationship between a candle's body size and its total range goes completely out of whack?Enter the Mahalanobis Distance Outlier Oscillator (MDOO).What is Mahalanobis Distance?Originally developed by an Indian statistician in 1936, Mahalanobis Distance measures how far a point is from the center of a data distribution, taking into account the correlation of the dataset.In formal math, the distance $D_M$ from a vector $x$ to a distribution with mean $\mu$ and covariance matrix $S$ is calculated as:$$D_M = \sqrt{(x - \mu)^T S^{-1} (x - \mu)}$$In plain scalping terms: It doesn't just measure if a candle is big.
It measures if a candle is acting weird based on recent market behavior.For this MT4 indicator, I've plotted Mahalanobis Distance across two dimensions:Candle Body (Close - Open)Candle Range (High - Low)How to Scalp with the MDOOBecause Mahalanobis Distance is absolute, the oscillator rests near 0 and spikes upwards when an outlier occurs.The Exhaustion Fade: Watch for a massive spike in the oscillator (usually > 2.5 or 3.0) hitting simultaneously with major Support/Resistance. This usually indicates an exhaustion candle (a "blow-off top" or "capitulation bottom") where the body/range relationship is completely abnormal.The Breakout Confirmation: If price has been in a tight consolidation box and you see the MDOO spike hard exactly as price breaches the box, it confirms real, statistically significant volume/momentum has entered the market. Don't fade it—ride it.
The MT4 Code (MQL4)
Here is the source code.
Open your MetaEditor, create a new Custom Indicator named MahalanobisOscillator, paste this in, and hit compile.
Tips for use:
Lookback Period: The default is 20. For sub-5-minute scalping, you might want to drop this to 14 to make it more sensitive to micro-structure changes.
Pairing: Don't use this blindly! Pair it with a momentum oscillator like RSI or a volume indicator. It tells you when something strange is happening, but you still need your price action skills to tell you what direction to trade it.
Give it a spin on your demo accounts and post some screenshots of how it lines up with your setups. Happy pip hunting!
We all use standard deviation (like Bollinger Bands) or ATR to measure volatility. But standard deviation only looks at one variable in a vacuum. What if we want to know when the relationship between a candle's body size and its total range goes completely out of whack?Enter the Mahalanobis Distance Outlier Oscillator (MDOO).What is Mahalanobis Distance?Originally developed by an Indian statistician in 1936, Mahalanobis Distance measures how far a point is from the center of a data distribution, taking into account the correlation of the dataset.In formal math, the distance $D_M$ from a vector $x$ to a distribution with mean $\mu$ and covariance matrix $S$ is calculated as:$$D_M = \sqrt{(x - \mu)^T S^{-1} (x - \mu)}$$In plain scalping terms: It doesn't just measure if a candle is big.
It measures if a candle is acting weird based on recent market behavior.For this MT4 indicator, I've plotted Mahalanobis Distance across two dimensions:Candle Body (Close - Open)Candle Range (High - Low)How to Scalp with the MDOOBecause Mahalanobis Distance is absolute, the oscillator rests near 0 and spikes upwards when an outlier occurs.The Exhaustion Fade: Watch for a massive spike in the oscillator (usually > 2.5 or 3.0) hitting simultaneously with major Support/Resistance. This usually indicates an exhaustion candle (a "blow-off top" or "capitulation bottom") where the body/range relationship is completely abnormal.The Breakout Confirmation: If price has been in a tight consolidation box and you see the MDOO spike hard exactly as price breaches the box, it confirms real, statistically significant volume/momentum has entered the market. Don't fade it—ride it.
The MT4 Code (MQL4)
Here is the source code.
Open your MetaEditor, create a new Custom Indicator named MahalanobisOscillator, paste this in, and hit compile.
Code: Select all
//+------------------------------------------------------------------+
//| MahalanobisOscillator.mq4 |
//| |
//+------------------------------------------------------------------+
#property strict
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 clrDodgerBlue
#property indicator_width1 2
//--- input parameters
input int LookbackPeriod = 20; // Period for Means and Covariance
//--- indicator buffers
double MDBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
SetIndexBuffer(0, MDBuffer);
SetIndexStyle(0, DRAW_LINE);
IndicatorShortName("Mahalanobis Dist (" + IntegerToString(LookbackPeriod) + ")");
// Optional: Add horizontal levels to easily spot outliers
IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, 2.0);
IndicatorSetDouble(INDICATOR_LEVELVALUE, 1, 3.0);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
// Ensure we have enough bars to calculate
if(rates_total < LookbackPeriod) return(0);
int limit = rates_total - prev_calculated;
if(limit > rates_total - LookbackPeriod)
limit = rates_total - LookbackPeriod;
for(int i = limit; i >= 0; i--)
{
// 1. Calculate Means for X (Body) and Y (Range)
double sumX = 0, sumY = 0;
for(int k = 0; k < LookbackPeriod; k++)
{
sumX += (close[i+k] - open[i+k]);
sumY += (high[i+k] - low[i+k]);
}
double meanX = sumX / LookbackPeriod;
double meanY = sumY / LookbackPeriod;
// 2. Calculate Variances and Covariance
double varX = 0, varY = 0, covXY = 0;
for(int k = 0; k < LookbackPeriod; k++)
{
double dx = (close[i+k] - open[i+k]) - meanX;
double dy = (high[i+k] - low[i+k]) - meanY;
varX += dx * dx;
varY += dy * dy;
covXY += dx * dy;
}
varX /= LookbackPeriod;
varY /= LookbackPeriod;
covXY /= LookbackPeriod;
// 3. Calculate Determinant of the Covariance Matrix
double det = varX * varY - covXY * covXY;
// 4. Calculate Mahalanobis Distance for current candle
if(det == 0) // Prevent division by zero in dead markets
{
MDBuffer[i] = 0;
}
else
{
double currentX = close[i] - open[i];
double currentY = high[i] - low[i];
double dx = currentX - meanX;
double dy = currentY - meanY;
// Explicit 2D inverse covariance matrix applied to dx, dy
double md_sq = (varY * dx * dx - 2 * covXY * dx * dy + varX * dy * dy) / det;
if(md_sq > 0)
MDBuffer[i] = MathSqrt(md_sq);
else
MDBuffer[i] = 0;
}
}
return(rates_total);
}
//+------------------------------------------------------------------+Tips for use:
Lookback Period: The default is 20. For sub-5-minute scalping, you might want to drop this to 14 to make it more sensitive to micro-structure changes.
Pairing: Don't use this blindly! Pair it with a momentum oscillator like RSI or a volume indicator. It tells you when something strange is happening, but you still need your price action skills to tell you what direction to trade it.
Give it a spin on your demo accounts and post some screenshots of how it lines up with your setups. Happy pip hunting!