Index Adaptive Keltner Channels [DW]
"Index Adaptive Keltner Channels [DW]" by DonovanWall, MPL-2.0. Ported to FloScript by FloSignals; modifications under MPL-2.0. Original: Index Adaptive Keltner Channels [DW] (v5.0), read 2026-10-12T16:00:02.970Z; source language v4.
Licence: Mozilla Public License 2.0 (MPL-2.0) — full text. The source is published with it, modifications included, under the same licence.
Index Adaptive Keltner Channels [DW] by DonovanWall, ported from Pine v4. Overlay indicator with 5 plots, 2 fills, bar/background colouring and 12 inputs.
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © DonovanWall
//██████╗ ██╗ ██╗
//██╔══██╗██║ ██║
//██║ ██║██║ █╗ ██║
//██║ ██║██║███╗██║
//██████╔╝╚███╔███╔╝
//╚═════╝ ╚══╝╚══╝
// ------------------------------------------------------------------------------------------------
// Original author: DonovanWall
// Original title: Index Adaptive Keltner Channels [DW]
// Licence: MPL-2.0 (the header above is the original notice, kept verbatim)
// Pine version: 4
// Fetched: 2026-10-12
// Ported to FloScript by FloSignals; modifications under MPL-2.0.
// Converter: @flosignals/floscript 0.1.0, strict mode, score 100/100
// ------------------------------------------------------------------------------------------------
//@floscript=1
//@version=5
// Converted by the FloScript converter from a Pine-compatible v4 source.
indicator(title="Index Adaptive Keltner Channels [DW]", shorttitle="IAKC [DW]", overlay=true)
//by Donovan Wall
//This study is an experiment in adaptive filtering. The process in this study was inspired by KAMA and ZLEMA filtering techniques.
//First, data is given an optional modification for lag reduction.
//Then, an adaptive filter of your choice is calculated. There are 6 different adaptive filters to choose from in this study:
// -Commodity Channel Index Adaptive Moving Average (CCIAMA)
// -Relative Strength Index Adaptive Moving Average (RSIAMA)
// -%R Adaptive Moving Average (%RAMA)
// -Klinger Volume Oscillator Adaptive Moving Average (KVOAMA)
// -Money Flow Index Adaptive Moving Average (MFIAMA)
// -Correlation Coefficient Adaptive Moving Average (CCAMA)
//Next, ATR is calculated using the specified adaptive filter.
//A set of ranges is calculated by multiplying ATR by the square root of the sampling period, then dividing it by 2 and 4.
//And Finally, the ranges are added to and subtracted from the adaptive filter to generate the channels.
//Custom bar colors are included. The formula for the color scheme is based on filter direction and price.
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Updates:
//After analyzing the original code more in depth, I realized a few flaws with the method I previously used, so I decided to rebuild the whole thing from scratch.
//This version is significantly more versatile and adaptive to data.
//In this version, rather than using altered index data to operate the smoothing parameters, I've applied Kaufman's Efficiency Ratio to a handful of indices.
//The smoothing operators available in this script are:
// - Kaufman's Efficiency Ratio
// - Time Correlation Efficiency Ratio
// - Commodity Channel Index Efficiency Ratio
// - Relative Strength Index Efficiency Ratio
// - Klinger Volume Oscillator Efficiency Ratio
// - Money Flow Index Efficiency Ratio
// - Fisher Transform Efficiency Ratio
// - Average True Range Efficiency Ratio
// - Standard Deviation Efficiency Ratio
//I also added a Variable Moving Average option per user request, which dynamically changes its smoothing period based on the operator.
//Now you can choose between either an Adaptive Moving Average or Variable Moving Average as the calculation method.
//The high and low bands are generated by calculating ATR based on the averaging method, multiplying it by a user defined coefficient, then adding and subtracting it from the basis average.
//The smaller set of bands is generated by perfoming the same calculation with 78.6% ATR.
//The bar color scheme is still based on filter direction and price.
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Updates:
//I noticed the Variable Moving Average formula I used previously was an expanding model with a rather significant amount of overshoot, so I reverted to Tushar Chande's model.
//I removed ATR Efficiency from the list, as it is not nearly as effective for this type of calculation as the other indices.
//I've implemented some new methods for transforming operator data for different results:
// - Standard, which uses the default Efficiency Ratio calculations
// - Max Min Normalize, which normalizes the operator data based on maximum and minum values, resulting in a more sensitive response
// - Inverse Fisher Normalize, which performs an Inverse Fisher Transform to the operator, then performs Max Min Normalization
// - Gate, which changes all values below the gate to 0, resulting in a less sensitive response
//The secondary band percentage for the high and low zones is now adjustable. The default value is now 61.8%.
//The bar color scheme has been adjusted to highlight overbought and oversold conditions.
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Updates:
// -> Migrated script to v4.
// -> Reorganized script structure.
// -> Smoothing operator calculations are now expressed as functions.
// -> Added compression to the available smoothing operator modifications. Compression can be tuned by adjusting the threshold and intensity.
// -> When using KVOER or MFIER, volume will be automatically substituted with tick volume when volume is NaN.
// -> Corrected NaN values in initial states.
// -> Revamped color scheme.
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Functions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Efficiency Ratio
er(x, t) =>
dist = math.abs(x - nz(x[1]))
signal = math.abs(x - nz(x[t]))
noise = math.sum(dist, t)
er = noise != 0 ? signal / noise : 1
er
//Time Correlation Coefficient Function
tcc(x, t) =>
var bars = 0.0
bars := bars + 1
tcc = ta.correlation(x, bars, t)
tcc
//Klinger Volume Oscillator Function
kvo(x, v) =>
sv = x > nz(x[1]) ? v : x < nz(x[1]) ? -v : 0
kvo = ta.ema(sv, 34) - ta.ema(sv, 55)
kvo
//Money Flow Index Oscillator Function
mfi_(x, t, v) =>
mf = x * v
pmf = math.sum(x > nz(x[1]) ? mf : 0, t)
nmf = math.sum(x < nz(x[1]) ? mf : 0, t)
mfi_ = 100 * (pmf / (pmf + nmf))
mfi_
//Fisher Transform Function
fish(x, t) =>
highval = ta.highest(x, t)
lowval = ta.lowest(x, t)
val1 = 0.0
val1 := 0.66 * ((x - lowval) / math.max(highval - lowval, 0.001) - 0.5) + 0.67 * nz(val1[1], 0)
val2 = val1 > 0.99 ? 0.999 : val1 < -0.99 ? -0.999 : val1
fish = 0.0
fish := 0.5 * math.log((1 + val2) / math.max(1 - val2, 0.001)) + 0.5 * nz(fish[1], 0)
fish
//Inverse Fisher Transform Function
ifish(x, t) =>
val = 0.1 * x
wval = ta.wma(val, t)
ifish = (math.exp(2 * wval) - 1) / (math.exp(2 * wval) + 1)
ifish
//Feature Scaling Function
fs_norm(x, t) =>
ta.highest(x, t) != ta.lowest(x, t) ? (x - ta.lowest(x, t)) / (ta.highest(x, t) - ta.lowest(x, t)) : 0
//Compression Function
comp(x, knee, intensity) =>
x > knee ? x - intensity * (x - knee) / 100 : x
//AMA Function
ama(x, t, f, s, o) =>
fastalpha = 2 / (f + 1)
slowalpha = 2 / (s + 1)
sc = math.pow(o * (fastalpha - slowalpha) + slowalpha, 2)
ama = x
ama := na(ama[1]) ? x : nz(ama[1]) + sc * (x - nz(ama[1]))
ama
//VMA Function
vma(x, t, o) =>
vma = x
vma := na(vma[1]) ? x : (1 - 1 / t * o) * nz(vma[1]) + 1 / t * o * x
vma
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Inputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Source
src = input(defval=close, title="Source")
//Averaging Method
amode = input.string(title="Averaging Method", defval="AMA", options=["AMA", "VMA"])
//Smoothing Operator Mode
smode = input.string(title="Smoothing Operator", defval="KER", options=["KER", "TCER", "CCIER", "RSIER", "KVOER", "MFIER", "FTER", "SDER"])
//Smoothing Operator Modification
scomod = input.string(title="Smoothing Operator Modification", defval="Standard", options=["Standard", "Inverse Fisher Normalize", "Max Min Normalize", "Gate", "Compress"])
//Operator Gate Threshold
gatethreshold = input.float(defval=0.5, minval=0, maxval=1, title="Operator Gate Threshold")
//Operator Compression Inputs
comp_knee = input.float(defval=0.5, minval=0, maxval=1, title="Operator Compression Threshold")
comp_intensity = input.float(defval=80.0, minval=0, maxval=100, title="Compression Intensity (%)")
//Initial Sampling Period
per = input.int(defval=9, minval=1, title="Sampling Period")
//Smoothing Constant Parameters
fastper = input.int(defval=3, minval=1, title="AMA Fast Smoothing Period")
slowper = input.int(defval=30, minval=1, title="AMA Slow Smoothing Period")
//Band Range Multiplier
natr = input.int(defval=3, minval=0, title="Band Range Multiplier")
//Secondary Band Percentage
sbp = input.float(defval=61.8, minval=0, step=0.01, title="Secondary Band (% of Band Range)")
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Definitions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Tick Volume Substitution For NaN values
tick = syminfo.mintick
rng = close - open
tickrng = tick
tickrng := math.abs(rng) < tick ? nz(tickrng[1]) : rng
tickvol = math.abs(tickrng) / tick
vol = na(volume) ? tickvol : volume
//Kaufman's Efficiency Ratio
erdata = er(src, per)
//Time Correlation Coefficient Efficiency Ratio
tccdata = er(tcc(src, per), per)
//Commodity Channel Index Efficiency Ratio
ccidata = er(ta.cci(src, per), per)
//Relative Strength Index Efficiency Ratio
rsidata = er(ta.rsi(src, per), per)
//Klinger Volume Oscillator Efficiency Ratio
kvodata = er(kvo(src, vol), per)
//Money Flow Index Efficiency Ratio
mfidata = er(mfi_(src, per, vol), per)
//Fisher Transform Efficiency Ratio
fishdata = er(fish(src, per), per)
//Standard Deviation Efficiency Ratio
stdevdata = er(ta.stdev(src, per), per)
//Smoothing Constant Operator
oer = smode == "KER" ? erdata : smode == "TCER" ? tccdata : smode == "CCIER" ? ccidata : smode == "RSIER" ? rsidata : smode == "KVOER" ? kvodata : smode == "MFIER" ? mfidata : smode == "FTER" ? fishdata : stdevdata
sco = scomod == "Standard" ? math.abs(oer) : scomod == "Inverse Fisher Normalize" ? fs_norm(ifish(oer, per), per) : scomod == "Max Min Normalize" ? fs_norm(oer, per) : scomod == "Gate" ? (math.abs(oer) < gatethreshold ? 0 : math.abs(oer)) : comp(oer, comp_knee, comp_intensity)
//AMA
AMA = ama(src, per, fastper, slowper, sco)
//VMA
VMA = vma(src, per, sco)
//AMA / VMA Selection
ma = amode == "AMA" ? AMA : VMA
//AMATR / VMATR
ATR = amode == "AMA" ? ama(ta.tr(true), per, fastper, slowper, sco) : vma(ta.tr(true), per, sco)
//Filter Direction
var f_dir = 0.0
f_dir := ma > ma[1] ? 1 : ma < ma[1] ? -1 : f_dir
//Bands
hbandlg = ma + ATR * natr
hbandsm = ma + ATR * natr * (sbp / 100)
lbandsm = ma - ATR * natr * (sbp / 100)
lbandlg = ma - ATR * natr
color1 = #0aff68
color2 = #00752d
color3 = #ff0a5a
color4 = #990032
//Colors
barcolor = src > ma and src > src[1] and src < hbandsm ? #0aff68 : src > ma and src < src[1] and src < hbandsm ? #00752d : src > ma and src > src[1] and src >= hbandsm ? #00FF7F : src > ma and src < src[1] and src >= hbandsm ? #3CB371 : src < ma and src < src[1] and src > lbandsm ? #ff0a5a : src < ma and src > src[1] and src > lbandsm ? #990032 : src < ma and src < src[1] and src <= lbandsm ? #F08080 : src < ma and src > src[1] and src <= lbandsm ? #CD5C5C : #cccccc
macolor = f_dir == 1 ? #0aff68 : f_dir == -1 ? #ff0a5a : #cccccc
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Outputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Basis Moving Average Plot
maplot = plot(ma, color=macolor, title="Basis Moving Average")
//Band Plots
hbandlgplot = plot(hbandlg, color=#0aff68, title="High Band")
hbandsmplot = plot(hbandsm, color=#0aff68, title="78.6% High Band")
lbandsmplot = plot(lbandsm, color=#ff0a5a, title="78.6% Low Band")
lbandlgplot = plot(lbandlg, color=#ff0a5a, title="Low Band")
//Fills
fill(hbandlgplot, hbandsmplot, color=#0aff68, title="High Zone")
fill(lbandsmplot, lbandlgplot, color=#ff0a5a, title="Low Zone")
//Bar Color
barcolor(barcolor)
This file is under the Mozilla Public License 2.0; it is a port of the original by DonovanWall, with the original licence header kept and the changes made for FloScript noted in the file.
- v2
Library refresh 2026-10-14
- v1
Library refresh 2026-10-12
Disclaimer. Scripts are written and published by members, or ported by FloSignals from open-source originals, and are their authors' own work and opinion. FloSignals does not review them for correctness and nothing in a script is financial advice or a recommendation to buy or sell anything — read the Risk Disclaimer. Posting here is under the Community Rules; a script that is not the poster's to post can be reported as the Copyright & Takedowns page says.

Comments (0)
No comments yet. Members can leave one.