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: 246
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.
PTScalper
Site Admin
Posts: 246
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.
Post Reply