Advertisement IC Markets

The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Optimize MetaTrader 4, MetaTrader 5, cTrader, and TradingView for speed. Discuss Level II Market Depth (DOM), custom hotkeys, and volume indicators.
Post Reply
PTScalper
Site Admin
Posts: 1643
Joined: Mon Jul 20, 2026 1:28 pm

The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Post 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);
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Recommended broker for automated trading & scalping IC Markets
PTScalper
Site Admin
Posts: 1643
Joined: Mon Jul 20, 2026 1:28 pm

Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Post 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.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
LondonScalper
Posts: 203
Joined: Sat Sep 05, 2026 7:54 am

Re: The Self-Adjusting Trendline: Kaufman’s Adaptive Moving Average (KAMA) + MT4/MT5 Code

Post 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?
Post Reply