Page 1 of 3
The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code
Posted: Thu Aug 20, 2026 12:39 pm
by PTScalper
Hi scalpers. traders,
one of the biggest dilemmas in technical analysis is choosing a moving average length: short periods generate excessive false signals in choppy markets, while long periods lag too far behind when a breakout happens.Developed by Perry Kaufman in 1995, Kaufman’s Adaptive Moving Average (KAMA) solves this problem dynamically. Instead of sticking to a fixed speed, KAMA continuously tracks market noise and automatically speeds up during strong trends and slows down during consolidation.How KAMA Adapts to VolatilityKAMA uses an Efficiency Ratio ($ER$) that measures the ratio of directional price change relative to total market volatility over a set period $n$ (default is 10):
$$ER_t = \frac{\vert{}\text{Price}_t - \text{Price}_{t-n}\vert{}}{\sum_{i=0}^{n-1} \vert{}\text{Price}_{t-i} - \text{Price}_{t-i-1}\vert{}}$$
Trending Market ($ER \approx 1$): Price moves directly in one direction with minimal pullbacks. KAMA speeds up and acts like a fast 2-period EMA.Noisy / Choppy Market ($ER \approx 0$): Price whipsaws sideways with little net progress. KAMA slows down and acts like a slow 30-period EMA.The calculated $ER$ is then converted into a dynamic Smoothing Constant ($SC$):
$$SC_t = \left[ ER_t \cdot \left( \frac{2}{\text{Fast}+1} - \frac{2}{\text{Slow}+1} \right) + \frac{2}{\text{Slow}+1} \right]^2
$$$$KAMA_t = KAMA_{t-1} + SC_t \cdot (\text{Price}_t - KAMA_{t-1})$$
Practical Ways to Trade KAMA
Trend Slope Filter: When KAMA has a clear upward slope, favor long trades; when sloping downward, favor shorts.
The Flat-Line Pause: When KAMA turns completely horizontal, the market is ranging. Use this as a direct signal to avoid breakout entries.
Dynamic Trailing Stop: Use the KAMA line as a trailing stop-loss level that tightens automatically when the trend accelerates and widens during pullbacks.
MT4 (MQL4) Implementation
Code: Select all
//+------------------------------------------------------------------+
//| KAMA.mq4 |
//| Kaufman Adaptive Moving Average for MetaTrader|
//+------------------------------------------------------------------+
#property copyright "Forum Community"
#property link ""
#property version "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 clrDarkOrange
#property indicator_width1 2
input int InpPeriodER = 10; // Efficiency Ratio Period
input int InpFastPeriod = 2; // Fast EMA Period
input int InpSlowPeriod = 30; // Slow EMA Period
double KAMABuffer[];
int OnInit() {
SetIndexBuffer(0, KAMABuffer);
SetIndexStyle(0, DRAW_LINE);
SetIndexLabel(0, "KAMA(" + IntegerToString(InpPeriodER) + ")");
return(INIT_SUCCEEDED);
}
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[]) {
if(rates_total <= InpPeriodER) return(0);
int limit = rates_total - prev_calculated;
if(prev_calculated == 0) limit = rates_total - InpPeriodER - 1;
if(prev_calculated > 0) limit++;
double fastSC = 2.0 / (InpFastPeriod + 1.0);
double slowSC = 2.0 / (InpSlowPeriod + 1.0);
for(int i = limit; i >= 0; i--) {
if(i >= rates_total - InpPeriodER) {
KAMABuffer[i] = close[i];
continue;
}
double change = MathAbs(close[i] - close[i + InpPeriodER]);
double volatility = 0.0;
for(int j = 0; j < InpPeriodER; j++) {
volatility += MathAbs(close[i + j] - close[i + j + 1]);
}
double er = (volatility > 0.0) ? (change / volatility) : 0.0;
double sc = MathPow(er * (fastSC - slowSC) + slowSC, 2);
double prevKAMA = (i + 1 < rates_total) ? KAMABuffer[i + 1] : close[i];
KAMABuffer[i] = prevKAMA + sc * (close[i] - prevKAMA);
}
return(rates_total);
}
Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code
Posted: Thu Aug 20, 2026 12:39 pm
by PTScalper
And here it is for forex scalpers in MT5:
MT5 (MQL5) Implementation
Code: Select all
//+------------------------------------------------------------------+
//| KAMA.mq5 |
//| Kaufman Adaptive Moving Average for MetaTrader|
//+------------------------------------------------------------------+
#property copyright "Forum Community"
#property link ""
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDarkOrange
#property indicator_width1 2
input int InpPeriodER = 10; // Efficiency Ratio Period
input int InpFastPeriod = 2; // Fast EMA Period
input int InpSlowPeriod = 30; // Slow EMA Period
double KAMABuffer[];
int OnInit() {
SetIndexBuffer(0, KAMABuffer, INDICATOR_DATA);
PlotIndexSetString(0, PLOT_LABEL, "KAMA(" + IntegerToString(InpPeriodER) + ")");
return(INIT_SUCCEEDED);
}
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[]) {
if(rates_total <= InpPeriodER) return(0);
int start = (prev_calculated > 0) ? prev_calculated - 1 : 0;
double fastSC = 2.0 / (InpFastPeriod + 1.0);
double slowSC = 2.0 / (InpSlowPeriod + 1.0);
for(int i = start; i < rates_total; i++) {
if(i < InpPeriodER) {
KAMABuffer[i] = close[i];
continue;
}
double change = MathAbs(close[i] - close[i - InpPeriodER]);
double volatility = 0.0;
for(int j = 0; j < InpPeriodER; j++) {
volatility += MathAbs(close[i - j] - close[i - j - 1]);
}
double er = (volatility > 0.0) ? (change / volatility) : 0.0;
double sc = MathPow(er * (fastSC - slowSC) + slowSC, 2);
double prevKAMA = (i > 0) ? KAMABuffer[i - 1] : close[i];
KAMABuffer[i] = prevKAMA + sc * (close[i] - prevKAMA);
}
return(rates_total);
}
Would you like an added feature in the code, such as automatic line color changes when the KAMA slope turns up or down?
Please let me know, if it was usefull for you

Take a care and have lot of good trades.
Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code
Posted: Fri Sep 11, 2026 9:15 pm
by LondonScalper
PTScalper wrote:one of the biggest dilemmas in technical analysis is choosing a moving average length: short periods generate excessive false signals in choppy markets, while long periods lag too far behind when a breakout happens.
That dilemma is real on London M1/M5 — fixed-period MAs either chatter through the open or arrive late when EURUSD actually starts walking.
I have used KAMA on and off for years as a
regime hint, not as an entry trigger. When the Efficiency Ratio collapses into Asia chop, KAMA flattening is useful: it stops me forcing mean-reversion fades that look “clean” on a fast EMA. When ER rises into a cash-session impulse, the line catching up is confirmation that I am not inventing trend from noise.
Desk caveat: adaptive averages still lag the
first leg. I size smaller on the initial KAMA turn and only add if structure (prior swing / session VWAP) agrees. Code is fine; the edge is knowing when to ignore the line entirely.
Do you mainly use KAMA as a filter against the London open, or as a cross-for-entry signal on the majors?
Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code
Posted: Sun Sep 20, 2026 3:01 pm
by PropScalpDesk
KAMA as regime hint, not entry siren
Adaptive averages try to solve the eternal length problem. Kaufman-style efficiency ratio logic is interesting for deciding when a market is trending enough to trust pullbacks. On M1 scalps I still treat any MA as secondary.
How it could fit a Frankfurt playbook without taking over:
- Slow/chaotic reading → stand aside or mean-revert protocols only with hard stops
- Efficient trend reading → allow pullback continuations I already defined in price
- Never enter solely because price crossed KAMA
Code on the forum is useful for experimentation. Live money waits until you measure the filter’s effect on expectancy after costs. An adaptive line that whips in the London open is just a fancy way to overtrade.
On gold I am even stricter: adaptive averages can look brilliant in a trend segment and then chop you to death when the rate channel turns two-sided. Pair filter, not master signal.
If you already run KAMA on EURUSD, which efficiency threshold actually reduced your false pullbacks — and did win rate rise enough to pay the extra decisions?
Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code
Posted: Sat Sep 26, 2026 10:14 am
by PTScalper
PropScalpDesk wrote: Sun Sep 20, 2026 3:01 pm
KAMA as regime hint, not entry siren
Adaptive averages try to solve the eternal length problem. Kaufman-style efficiency ratio logic is interesting for deciding when a market is trending enough to trust pullbacks. On M1 scalps I still treat any MA as secondary.
How it could fit a Frankfurt playbook without taking over:
- Slow/chaotic reading → stand aside or mean-revert protocols only with hard stops
- Efficient trend reading → allow pullback continuations I already defined in price
- Never enter solely because price crossed KAMA
Code on the forum is useful for experimentation. Live money waits until you measure the filter’s effect on expectancy after costs. An adaptive line that whips in the London open is just a fancy way to overtrade.
On gold I am even stricter: adaptive averages can look brilliant in a trend segment and then chop you to death when the rate channel turns two-sided. Pair filter, not master signal.
If you already run KAMA on EURUSD, which efficiency threshold actually reduced your false pullbacks — and did win rate rise enough to pay the extra decisions?
Hi PropScalpDesk,
On EURUSD lower timeframes, an Efficiency Ratio (ER) threshold between 0.30 and 0.40 is typically where KAMA transitions from a lagging distraction into a legitimate regime filter. Treating Kaufman’s logic strictly as a permissive switch—rather than an entry trigger—is exactly how systematic traders use it to survive intraday noise.
The Expectancy Math: Did it pay off?
The short answer is yes, but the mechanism is counterintuitive. When strictly filtering with an ER > 0.35, the win rate on the taken trades usually only bumps by a marginal 3% to 5%.
The real mathematical edge comes from trade suppression. By standing aside during the sub-0.30 chop, you eliminate the cluster of consecutive paper-cuts that destroy the profit factor. You aren't necessarily picking vastly superior winning setups; you are simply stopping the account from bleeding spread and commission costs during the tail-end of the Asian session or the midday lull. The expectancy rises because the denominator (total trades taken) shrinks by cutting out the garbage.
The Frankfurt and London Open Trap
Your observation about the London whip is the Achilles' heel of adaptive averages. During the Frankfurt transition and the London open, KAMA is highly vulnerable to "volume-induced ER spikes."
A sudden injection of liquidity causes a rapid price displacement, artificially inflating the "Direction" component of the ER formula. The ER flashes > 0.40, signaling an efficient trend, but it's just the initial volume vacuum being filled. If you run KAMA during this window, it requires a time-of-day block or must be paired with a hard volume threshold to prevent the filter from baiting you into an overtrading whip.
Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code
Posted: Sat Sep 26, 2026 10:15 am
by PTScalper
Gold (XAUUSD) vs. KAMA
Your strictness on Gold is entirely justified. Gold’s intraday structure frequently features violent, symmetric volatility expansions. Because the ER calculates net direction over total volatility, a sharp 30-pip spike followed immediately by a 25-pip drop creates enough gross volatility to confuse the smoothing constant. KAMA on Gold can look brilliant in a sustained macro move, but in an M1 two-sided channel, the adaptive line will flatten just late enough to ensure you get chopped to death on every fake-out.
Key insight: If you are using KAMA on a 1-minute chart, the standard 10-period lookback for the ER is nearly useless—it only measures 10 minutes of data, which is pure noise. You need to pull the ER lookback out to at least 30 to 60 periods on M1 to measure the actual session's efficiency.
Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code
Posted: Sat Sep 26, 2026 10:16 am
by PTScalper
Optimizing the Efficiency Ratio (ER) lookback on intraday timeframes requires abandoning default retail settings (like 10 or 14 periods) and anchoring the calculation directly to market microstructure cycles. If the lookback is too short, the ER reacts to isolated block trades; if it's too long, you are mathematically forced to trade the tail-end of the move.
Here is how to structure the lookback to balance responsiveness with noise reduction on lower timeframes:
1. Anchor to Session Time, Not Arbitrary Bars
On an M1 or M5 chart, a bar count is meaningless unless it represents a significant window of institutional order flow.
M1 Chart (30 to 45 periods): A standard 10-period lookback measures just 10 minutes of order flow, which is pure noise in a high-frequency environment. Pushing the lookback to 30–45 periods captures a half-hour to 45 minutes of market action. This is the minimum time required for a structural trend to prove itself after a liquidity sweep without lagging into the next session phase.
M5 Chart (12 to 18 periods): This translates to 1 to 1.5 hours of data. It is long enough to filter out the localized chaos of a session transition (like the first 30 minutes of Frankfurt) while remaining highly responsive to the sustained London trend.
Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code
Posted: Sat Sep 26, 2026 10:16 am
by PTScalper
2. Match the Pullback Cycle Duration
Because your core strategy relies on trading structural pullbacks, the ER lookback must be tuned to the average duration of those pullbacks to prevent the filter from breaking during the retracement.
If a typical mid-trend pullback on EURUSD M1 lasts 15 to 20 minutes, your ER lookback should be slightly larger than this window (e.g., 25–30 periods).
The Edge: This ensures the localized "inefficiency" of the pullback itself doesn't crash the ER below your threshold (e.g., 0.35). The adaptive line stays flat, acting as a structural barrier, rather than curving aggressively into the price action and generating a false exit or trend-change signal.
3. Multi-Timeframe ER Integration (The Lag Killer)
The most mathematically sound way to get a clean regime hint on M1 without the lag of a massive 60-period calculation is to decouple the ER's calculation timeframe from your execution timeframe.
The Setup: Calculate a fast ER (e.g., 8 to 10 periods) on the M15 chart, but read that value dynamically as a boolean filter on your M1 chart.
Why it works: An M15 ER requires serious, sustained participation to cross an efficiency threshold. By the time it does, the macro trend is established. However, because you are executing on the M1 chart via price action, you avoid the heavy entry lag of waiting for an M15 candle to close. You get higher-timeframe structural validation with lower-timeframe execution speed.
Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code
Posted: Sat Sep 26, 2026 10:16 am
by PTScalper
4. The Gold (XAUUSD) Exception
As you noted, Gold requires much stricter handling. Because Gold moves in violent, expansionary bursts followed by immediate consolidations, a longer lookback (like 45 periods on M1) will lag severely—by the time it registers efficiency, the move is already exhausting.
For Gold, the optimization logic flips: shrink the lookback, but raise the threshold.
Use a fast 15 to 20-period lookback on M1 so it reacts immediately to the volatility expansion, but demand a much higher ER threshold (e.g., > 0.50 or 0.60) to confirm the move isn't just a two-sided liquidity sweep.
Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code
Posted: Sat Sep 26, 2026 10:17 am
by PTScalper
This Pine Script v5 implementation builds the Multi-Timeframe (MTF) Efficiency Ratio exactly as a structural regime filter. It decouples the ER calculation from your execution timeframe and includes a strict non-repainting toggle.
Code: Select all
//@version=5
indicator("MTF Efficiency Ratio (Regime Filter)", shorttitle="MTF ER", overlay=false)
// =========================================================================
// INPUTS
// =========================================================================
grp_main = "MTF Configuration"
i_lookback = input.int(10, title="ER Lookback", minval=1, group=grp_main, tooltip="Recommended: 8-10 for M15 HTF.")
i_htf = input.timeframe("15", title="Higher Timeframe (HTF)", group=grp_main)
grp_logic = "Execution Logic"
i_thresh = input.float(0.35, title="Efficiency Threshold", step=0.05, group=grp_logic, tooltip="0.35 for EURUSD. 0.50+ for XAUUSD.")
i_safe_mtf = input.bool(true, title="Strict Non-Repainting", group=grp_logic, tooltip="Fetches the ER of the last FULLY CLOSED HTF candle. Prevents real-time repainting on the executing chart.")
// =========================================================================
// CALCULATIONS
// =========================================================================
// Kaufman's Efficiency Ratio formula
f_er(len) =>
net_change = math.abs(close - close[len])
volatility = math.sum(math.abs(close - close[1]), len)
volatility == 0 ? 0 : net_change / volatility
// Core MTF Request
// Combining [1] with lookahead_on is the standard workaround to fetch strictly closed historical data without repainting the current bar.
htf_er = request.security(syminfo.tickerid, i_htf, i_safe_mtf ? f_er(i_lookback)[1] : f_er(i_lookback), lookahead = i_safe_mtf ? barmerge.lookahead_on : barmerge.lookahead_off)
// =========================================================================
// VISUALS & PLOTTING
// =========================================================================
// State Check
is_efficient = htf_er >= i_thresh
// Colors
c_trend = color.new(#00E676, 20) // Green for clean regime
c_chop = color.new(#787B86, 70) // Gray for stand-aside / mean-revert
// Plot the ER as a histogram in a lower pane
plot(htf_er, title="HTF ER", color=is_efficient ? c_trend : c_chop, style=plot.style_columns)
// Hard threshold line
hline(i_thresh, title="Threshold", color=color.new(#FF5252, 0), linestyle=hline.style_dashed)
// Paint the main chart background when the regime is efficient
bgcolor(is_efficient ? color.new(#00E676, 92) : na, title="Efficient Regime Highlight")