QQE
Download scriptThe Qualitative Quantitative Estimation (QQE) indicator is a sophisticated technical analysis tool designed to help traders identify trend directions and potential reversal points by analyzing price momentum. Rather than simply looking at raw price action, it combines several layers of mathematical smoothing to filter out "market noise" and highlight the underlying strength of a movement.
Core Analytical Logic
The logic follows a multi-step process to transform volatile market data into a smoother, more readable trend signal:
1. Momentum Foundation The indicator begins by calculating a standard Relative Strength Index (RSI). This provides a baseline for whether an asset is becoming overbought or oversold. However, because the RSI can be jumpy, the script immediately applies an Exponential Moving Average (EMA) to these values. This creates a smoother "trend line" of the momentum.
2. Volatility Measurement To understand how much the momentum is swinging, the tool calculates the absolute difference between consecutive points on that smoothed trend line. By measuring these changes, the indicator determines the current volatility—essentially tracking how fast or slow the price is reacting.
3. Dynamic Sensitivity Scaling The script then takes that volatility data and applies another layer of smoothing (using a specific "Wilder’s" period). This creates a dynamic "buffer" or "sensitivity range." Instead of using a fixed number to determine trend changes, the indicator uses this variable to adjust its reaction speed based on current market conditions.
4. The Trend Tracking Mechanism The final and most important step is the construction of the primary trend line (the "Slow Level"). This logic acts like a smart tracker:
- It monitors the current momentum against a previous "ceiling" or "floor."
- When the price pushes in a new direction with enough strength (exceeding the calculated volatility buffer), the indicator updates its position to follow that movement.
- If the momentum weakens and fails to break through that buffer, the indicator stays at its current level.
Summary for the Trader
In practical terms, this script creates a visual representation of "filtered" momentum. Instead of reacting to every minor price flicker, it waits for significant movements that exceed the current market's volatility. It produces a line that captures the core trend of the market, helping you identify when the "weight" of the market is shifting from one direction to another.
//+------------------------------------------------------------------+
//| Qualitative Quantitative Estimation Indicator for Metatrader 4 |
//| Copyright © 2006Roman Ignatov |
//| mailto:roman.ignatov@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 200 Roman Ignatov"
#property link "mailto:roman.ignatov@gmail.com"
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 Navy
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2
#property indicator_color2 Navy
#property indicator_style2 STYLE_DOT
extern int SF = 5;
int RSI_Period = 14;
int Wilders_Period;
int StartBar;
double TrLevelSlow[];
double AtrRsi[];
double MaAtrRsi[];
double Rsi[];
double RsiMa[];
int init()
{
Wilders_Period = RSI_Period * 2 - 1;
if (Wilders_Period < SF)
StartBar = SF;
else
StartBar = Wilders_Period;
IndicatorBuffers(6);
SetIndexBuffer(0, RsiMa);
SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 2);
SetIndexLabel(0, "Value 1");
SetIndexDrawBegin(0, StartBar);
SetIndexStyle(1, DRAW_LINE, STYLE_DOT);
SetIndexBuffer(1, TrLevelSlow);
SetIndexLabel(1, "Value 2");
SetIndexDrawBegin(1, StartBar);
SetIndexBuffer(2, AtrRsi);
SetIndexBuffer(3, MaAtrRsi);
SetIndexBuffer(4, Rsi);
IndicatorShortName(StringConcatenate("QQE(", SF, ")"));
return(0);
}
int start()
{
int counted, i;
double rsi0, rsi1, dar, tr, dv;
if(Bars <= StartBar)
return (0);
counted = IndicatorCounted();
if(counted < 1)
for(i = Bars - StartBar; i < Bars; i++)
{
TrLevelSlow[i] = 0.0;
AtrRsi[i] = 0.0;
MaAtrRsi[i] = 0.0;
Rsi[i] = 0.0;
RsiMa[i] = 0.0;
}
counted = Bars - counted - 1;
for (i = counted; i >= 0; i--)
Rsi[i] = iRSI(NULL, 0, RSI_Period, PRICE_CLOSE, i);
for (i = counted; i >= 0; i--)
{
RsiMa[i] = iMAOnArray(Rsi, 0, SF, 0, MODE_EMA, i);
AtrRsi[i] = MathAbs(RsiMa[i + 1] - RsiMa[i]);
}
for (i = counted; i >= 0; i--)
MaAtrRsi[i] = iMAOnArray(AtrRsi, 0, Wilders_Period, 0, MODE_EMA, i);
i = counted + 1;
tr = TrLevelSlow[i];
rsi1 = iMAOnArray(Rsi, 0, SF, 0, MODE_EMA, i);
while (i > 0)
{
i--;
rsi0 = iMAOnArray(Rsi, 0, SF, 0, MODE_EMA, i);
dar = iMAOnArray(MaAtrRsi, 0, Wilders_Period, 0, MODE_EMA, i) * 4.236;
dv = tr;
if (rsi0 < tr)
{
tr = rsi0 + dar;
if (rsi1 < dv)
if (tr > dv)
tr = dv;
}
else if (rsi0 > tr)
{
tr = rsi0 - dar;
if (rsi1 > dv)
if (tr < dv)
tr = dv;
}
TrLevelSlow[i] = tr;
rsi1 = rsi0;
}
return(0);
}
Comments