Skip to main content
BTC / USDTCRYPTO107,400+2.19%ETH / USDTCRYPTO3,840+2.13%SOL / USDTCRYPTO182.40−1.99%BNB / USDTCRYPTO652.30+0.66%XRP / USDTCRYPTO2.2150+1.61%DOGE / USDTCRYPTO0.3850−1.79%TON / USDTCRYPTO5.240+2.34%AVAX / USDTCRYPTO42.60−2.07%LINK / USDTCRYPTO22.40+2.28%ADA / USDTCRYPTO1.0520−1.68%TRX / USDTCRYPTO0.3300+0.92%DOT / USDTCRYPTO8.420+2.93%BTC / USDTCRYPTO107,400+2.19%ETH / USDTCRYPTO3,840+2.13%SOL / USDTCRYPTO182.40−1.99%BNB / USDTCRYPTO652.30+0.66%XRP / USDTCRYPTO2.2150+1.61%DOGE / USDTCRYPTO0.3850−1.79%TON / USDTCRYPTO5.240+2.34%AVAX / USDTCRYPTO42.60−2.07%LINK / USDTCRYPTO22.40+2.28%ADA / USDTCRYPTO1.0520−1.68%TRX / USDTCRYPTO0.3300+0.92%DOT / USDTCRYPTO8.420+2.93%
Preise

Keltner Channel

ATR-based envelope around an EMA — MT4, MT5, TradingView, TradeStation and MetaStock code.

A Keltner Channel is an envelope around an EMA basis, with upper and lower bands set a multiple of Average True Range away. Because it uses ATR rather than standard deviation the channel reacts smoothly to volatility; breaks outside the bands signal continuation while the basis acts as dynamic support and resistance. Copy the version for your platform.

Pine Script
//@version=5
indicator("Keltner Channel", overlay=true)
length = input.int(20, "Length")
mult = input.float(2.0, "ATR Mult")
basis = ta.ema(close, length)
rangema = ta.atr(length)
upper = basis + mult * rangema
lower = basis - mult * rangema
plot(basis, title="Basis", color=color.orange)
plot(upper, title="Upper", color=color.blue)
plot(lower, title="Lower", color=color.blue)
MQL4 · KeltnerChannel.mq4
#property indicator_chart_window
#property indicator_buffers 3

extern int KC_Period = 20;
extern double KC_Mult = 2.0;
double BasisBuf[], UpperBuf[], LowerBuf[];

int OnInit() {
  SetIndexBuffer(0, BasisBuf);
  SetIndexBuffer(1, UpperBuf);
  SetIndexBuffer(2, LowerBuf);
  return 0;
}

int OnCalculate(const int rates_total, const int prev_calculated, const double &close[]) {
  for (int i = prev_calculated; i < rates_total; i++) {
    double basis = iMA(NULL, 0, KC_Period, 0, MODE_EMA, PRICE_CLOSE, i);
    double rng = iATR(NULL, 0, KC_Period, i);
    BasisBuf[i] = basis;
    UpperBuf[i] = basis + KC_Mult * rng;
    LowerBuf[i] = basis - KC_Mult * rng;
  }
  return rates_total;
}
MQL5 · KeltnerChannel.mq5
#property indicator_chart_window
#property indicator_buffers 3

input int KC_Period = 20;
input double KC_Mult = 2.0;
double BasisBuf[], UpperBuf[], LowerBuf[];

int OnInit() {
  SetIndexBuffer(0, BasisBuf);
  SetIndexBuffer(1, UpperBuf);
  SetIndexBuffer(2, LowerBuf);
  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[]) {
  for (int i = prev_calculated; i < rates_total; i++) {
    double basis = iMA(NULL, 0, KC_Period, 0, MODE_EMA, PRICE_CLOSE, i);
    double rng = iATR(NULL, 0, KC_Period, i);
    BasisBuf[i] = basis;
    UpperBuf[i] = basis + KC_Mult * rng;
    LowerBuf[i] = basis - KC_Mult * rng;
  }
  return rates_total;
}
EasyLanguage
inputs: Length(20), Mult(2.0);
variables: Basis(0), Upper(0), Lower(0);
Basis = XAverage(Close, Length);
Upper = Basis + Mult * AvgTrueRange(Length);
Lower = Basis - Mult * AvgTrueRange(Length);
Plot1(Basis, "Basis");
Plot2(Upper, "Upper");
Plot3(Lower, "Lower");
MetaStock
{Keltner Channel - EMA basis +/- 2*ATR}
basis := Mov(C, 20, E);
rng := ATR(20);
upper := basis + 2 * rng;
lower := basis - 2 * rng;
basis

To use it inside dtcharts, paste any version into the Script Converter and it becomes a native indicator on your chart.