In common, formula is:
Keltner.High(i) = Smooth(Source) + Variation * Factor
Keltner.Low(i) = Smooth(Source) - Variation * Factor
There are many choices how to smooth the source and what is the variation.
The most common cases are:
Case 1). Smoothing is Moving Average, Source is Close, Variation is average of the differences between high and low:
Keltner.High = Avg(Close) + Avg(High - Low)
Keltner.Low = Avg(Close) - Avg(High - Low)
Case 2). Smoothing is Moving Average, the Source is Median and Variation is Average True Range
Keltner.High = Avg((High + Low + Close)/3) + ATR(Bar)
Keltner.Low = Avg((High + Low + Close)/3) - ATR(Bar)
The implementation here lets you customize the source, smoothing method and variation method.
Source can be:
a) Close Price
b) Median as (High + Low) / 2
c) Median as (High + Low + Close) / 3
Smoothing could be:
a) Simple Moving Average (MVA)
b) Exponential Moving Average (EMA)
c) Linear Weighted Moving Average (LWMA)
d) Smoothed Moving Average (SMMA)
e) Wilder's Moving Average (WMA)
Note If you would like to use SMMA and WMA, please download and install these indicators.
SMMA is available here. WMA is available here
Variation can be:
a) Smoothed difference between High and Low
b) Average True Range
You can also choose the numbers of period to smooth the base line, the numbers of period to smooth the variation and the factor which is used to multiply variation before applying it.
At the example below:
Left indicator:
Base: Moving Average of the last 10 periods of the Close
Variation: Moving Average of the last 10 periods of the difference between High and Low
Factor: 1
Right Indicator:
Base: Wilder's Smoothing of the last 50 periods of the Median (High + Low + Close) / 3
Variation: Average True Range of the Last 50 periods.
Factor: 3.5
The source code of the indicator is below
- Code: Select all
-- Indicator profile initialization routine
-- Defines indicator profile properties and indicator parameters
function Init()
indicator:name("Keltner Band");
indicator:description("No description");
indicator:requiredSource(core.Bar);
indicator:type(core.Indicator);
-- indicator parameters
indicator.parameters:addInteger("NM", "Number of the periods to smooth the center line", "", 50);
indicator.parameters:addInteger("NB", "Number of periods to smooth deviation", "", 50);
indicator.parameters:addDouble("F", "Factor which is used to apply the deviation", "", 1);
-- source method
indicator.parameters:addString("SRC", "The center line source", "", "C");
indicator.parameters:addStringAlternative("SRC", "Close", "", "C");
indicator.parameters:addStringAlternative("SRC", "Median (H+L)/2", "", "M1");
indicator.parameters:addStringAlternative("SRC", "Median (H+L+C)/3", "", "M2");
-- source smoothing method
indicator.parameters:addString("MS", "The center line smoothing method", "", "MVA");
indicator.parameters:addStringAlternative("MS", "MVA", "", "MVA");
indicator.parameters:addStringAlternative("MS", "EMA", "", "EMA");
indicator.parameters:addStringAlternative("MS", "LWMA", "", "LWMA");
indicator.parameters:addStringAlternative("MS", "SMMA", "", "SMMA");
indicator.parameters:addStringAlternative("MS", "Wilders", "", "WMA");
-- variation method
indicator.parameters:addString("MV", "Variation Method", "", "AHL");
indicator.parameters:addStringAlternative("MV", "Smoothed H-L", "", "AHL");
indicator.parameters:addStringAlternative("MV", "ATR of source", "", "ATR");
indicator.parameters:addColor("H_color", "Color of Upper Band Line", "", core.rgb(255, 0, 0));
indicator.parameters:addColor("M_color", "Color of Middle Band Line", "", core.rgb(0, 255, 255));
indicator.parameters:addColor("L_color", "Color of Lower Band Line", "", core.rgb(255, 0, 0));
end
-- Indicator instance initialization routine
-- Processes indicator parameters and creates output streams
-- TODO: Refine the first period calculation for each of the output streams.
-- TODO: Calculate all constants, create instances all subsequent indicators and load all required libraries
-- Parameters block
local NM;
local NB;
local MS;
local MV;
local SRC;
local F;
local first;
local source = nil;
-- Streams block
local H = nil;
local M = nil;
local L = nil;
local AS; -- alternative source
local MI; -- middle line smoothed
local VM1; -- the source stream for H-L variation method
local VMI; -- the indicator for smoothing H-L variation method
local ATR; -- ATR indicator for smoothing method
-- Routine
function Prepare()
NM = instance.parameters.NM;
NB = instance.parameters.NB;
SRC = instance.parameters.SRC;
F = instance.parameters.F;
MV = instance.parameters.MV;
MS = instance.parameters.MS;
source = instance.source;
local name = profile:id() .. "(" .. source:name() .. "." .. SRC .. ", "
-- preare the source
if SRC == "C" then
AS = source.close;
elseif SRC == "M1" or SRC == "M2" then
AS = instance:addInternalStream(source:first(), 0);
else
assert(false, "The source method is unknown");
end
-- create an indicator to calculate the middle line
name = name .. MS .. "(" .. NM .. "), "
MI = core.indicators:create(MS, AS, NM);
first = MI.DATA:first();
if MV == "AHL" then
name = name .. MS .. "(H-L, " .. NB .. "), "
VM1 = instance:addInternalStream(source:first(), 0);
VMI = core.indicators:create(MS, VM1, NB);
if VMI.DATA:first() > first then
first = MI.DATA:first();
end
elseif MV == "ATR" then
name = name .. "ATR(" .. NB .. "), "
ATR = core.indicators:create("ATR", source, NB);
if ATR.DATA:first() > first then
first = ATR.DATA:first();
end
else
assert(false, "The variation method is unknown");
end
name = name .. F;
name = name .. ")";
instance:name(name);
H = instance:addStream("H", core.Line, name .. ".H", "H", instance.parameters.H_color, first);
M = instance:addStream("M", core.Line, name .. ".M", "M", instance.parameters.M_color, first);
L = instance:addStream("L", core.Line, name .. ".L", "L", instance.parameters.L_color, first);
end
-- Indicator calculation routine
function Update(period, mode)
if period >= source:first() then
if SRC == "M1" then
AS[period] = (source.high[period] + source.low[period]) / 2;
elseif SRC == "M2" then
AS[period] = (source.high[period] + source.low[period] + source.close[period]) / 3;
end
-- update the source smoothing indicator
MI:update(mode);
if MV == "AHL" then
VM1[period] = source.high[period] - source.low[period];
VMI:update(mode);
elseif MV == "ATR" then
ATR:update(mode);
end
end
if period >= first then
local v;
M[period] = MI.DATA[period];
if MV == "AHL" then
VM1[period] = source.high[period] - source.low[period];
v = VMI.DATA[period];
elseif MV == "ATR" then
v = ATR.DATA[period];
end
H[period] = M[period] + v * F;
L[period] = M[period] - v * F;
end
end
Download the indicator
Updated May, 31 2010. A new parameter 'Show center line' is added.
This indicator provides Audio / Email Alerts, for Keltner indicator,
It is possible to define three separate signals.
Top/Bottom/Central Line Crossover Alert.
Compatibility issue fixed.
_Alert Helper is not longer needed.
MQ4 version of Keltner channel indicator can be found here.
viewtopic.php?f=38&t=20204&p=35520#p35520
Version with additional smoothing options.
https://fxcodebase.com/code/viewtopic.php?f=17&t=71126