If there’s one thing we know at forex-scalping.com, it’s that traditional moving averages are broken. By the time your SMA or EMA crosses, the move is already half over. RSI keeps you trapped in "overbought" zones during massive trends, and MACD just lags you to death.
For the past few months, I've been digging through institutional quantitative papers, trying to find an indicator that adapts to price before the move accelerates. I wanted something that doesn't just average the past, but mathematically attempts to predict the next tick while actively filtering out market noise.
I am excited to release something I’m calling the Quantum Adaptive Kalman-Hilbert Filter (QAKHF). I genuinely believe this might be the most mathematically complicated indicator ever written for the MT4 platform.
Here is the breakdown of how it works and the open-source code so you can run it yourself.
The Math: Aerospace Meets Digital Signal Processing
To eliminate lag while keeping the line smooth, this indicator merges two highly advanced mathematical concepts:
The Kalman Filter [4]: Originally developed in the 1960s by Rudolf Kálmán and used by NASA to calculate the trajectory of spacecraft, a Kalman Filter uses a two-step "predict and update" loop. It literally predicts where the price should be on the next tick, measures the actual price, and corrects its trajectory. It gives you a smooth line with practically zero lag [4].
The Ehlers Hilbert Transform [1]: Developed by signal-processing legend John Ehlers, this math decomposes market cycles into their complex number components: the In-Phase and Quadrature components [1]. It identifies the exact phase of the current market cycle.
What I did: I wrote an algorithm that calculates the instantaneous phase of the market using the Hilbert Transform [1]. The indicator then takes that cycle data and feeds it into the Kalman Filter [4] as a Dynamic Entropy K-Factor.
The Result? When the market is chopping sideways, the filter mathematically increases its noise reduction. The second the market breaks into a trend, the cycle phase shifts, and the filter aggressively snaps to the price action.
How to Trade It
Because this is a scalping community, I optimized the default variables for the M1 and M5 timeframes.
Aqua Line (Velocity > 0): The algorithmic trajectory is upward. Look for long entries on pullbacks.
Magenta Line (Velocity < 0): The algorithmic trajectory is downward. Look for short entries on retracements.
Best Setup: Wait for the Asian session chop to end. The moment London or New York opens, wait for the first color change on the QAKHF. Enter in the direction of the color change, placing your stop loss exactly 1 pip above/below the previous swing high/low.
The MQL4 Source Code
Instructions: Open MetaEditor in your MT4 terminal, create a new Custom Indicator, name it Quantum_Kalman_Hilbert, paste the code below over everything, and hit Compile.
Code snippet
Code: Select all
//+------------------------------------------------------------------+
//| Quantum_Kalman_Hilbert.mq4 |
//| Copyright 2026, Forex-Scalping.com |
//| https://forex-scalping.com |
//+------------------------------------------------------------------+
#property copyright "Forex-Scalping.com"
#property link "https://forex-scalping.com"
#property version "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 clrAqua
#property indicator_color2 clrMagenta
#property indicator_width1 2
#property indicator_width2 2
//--- Inputs
input double BaseK = 1.0; // Kalman Base Filter Multiplier
input double Sharpness = 1.0; // Extrapolation Sharpness
input int HilbertPeriod = 7; // Hilbert Transform Cycle Period
//--- Buffers
double UpBuffer[];
double DnBuffer[];
double inPhase[];
double quad[];
//--- Global Variables
double pred, velo, smooth;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Indicator buffers mapping
SetIndexBuffer(0, UpBuffer);
SetIndexBuffer(1, DnBuffer);
SetIndexBuffer(2, inPhase);
SetIndexBuffer(3, quad);
//--- Visual settings
SetIndexStyle(0, DRAW_LINE);
SetIndexStyle(1, DRAW_LINE);
SetIndexStyle(2, DRAW_NONE); // Hidden calculation buffer
SetIndexStyle(3, DRAW_NONE); // Hidden calculation buffer
SetIndexEmptyValue(0, 0.0);
SetIndexEmptyValue(1, 0.0);
IndicatorShortName("Quantum Kalman-Hilbert (" + DoubleToString(BaseK, 1) + ")");
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[])
{
// Require enough bars to calculate the cycle
if (rates_total < HilbertPeriod + 10) return(0);
int limit = rates_total - prev_calculated;
// Initialization on first run
if (prev_calculated == 0)
{
limit = rates_total - HilbertPeriod - 2;
pred = close[limit];
velo = 0.0;
}
for (int i = limit; i >= 0; i--)
{
double price = (high[i] + low[i]) / 2.0;
// Ehlers Hilbert Transform Phase decomposition
inPhase[i] = price - close[i + HilbertPeriod/2];
quad[i] = price - close[i + HilbertPeriod];
// Calculate Instantaneous Phase
double phase = 0.0;
if (inPhase[i] != 0.0)
{
phase = MathArctan(quad[i] / inPhase[i]);
}
// Dynamic Filter Matrix (Kalman K-Factor modulated by Cycle Phase)
double dynamicK = BaseK + MathAbs(MathSin(phase));
// Kalman Filtering Prediction & Update Loop
double k_scaled = (dynamicK / 10000.0) * 2.0;
smooth = pred + (price - pred) * MathSqrt(k_scaled) * Sharpness;
velo = velo + ((dynamicK / 10000.0) * (price - pred));
pred = smooth + velo;
double kf = pred;
// Velocity-based dynamic coloring
if (velo > 0.0)
{
UpBuffer[i] = kf;
DnBuffer[i] = EMPTY_VALUE;
// Bridge the gap for a continuous visual line
if (i < rates_total - 1 && DnBuffer[i+1] != EMPTY_VALUE)
{
UpBuffer[i+1] = DnBuffer[i+1];
}
}
else
{
DnBuffer[i] = kf;
UpBuffer[i] = EMPTY_VALUE;
// Bridge the gap for a continuous visual line
if (i < rates_total - 1 && UpBuffer[i+1] != EMPTY_VALUE)
{
DnBuffer[i+1] = UpBuffer[i+1];
}
}
}
return(rates_total);
}
//+------------------------------------------------------------------+Even with aerospace-grade math [4], there is no such thing as a 100% win-rate Holy Grail. This indicator is incredibly responsive, but it is a tool, not an automated ATM machine. Do not run this blindly. Combine the color shifts with pure price action, support/resistance, and proper risk management.
Load it up on your demo accounts, slap it on the EUR/USD M1 chart, and let me know what you guys think of the zero-lag dynamic coloring. Happy scalping!