Advanced Keltner Channel/Oscillator [MyTradingCoder] for ThinkOrSwim

samer800

Moderator - Expert
VIP
Lifetime
8pCnaoD.png


Author Message:

This indicator combines a traditional Keltner Channel overlay with an oscillator, providing a comprehensive view of price action, trend, and momentum. The core of this indicator is its advanced ATR calculation, which uses statistical methods to provide a more robust measure of volatility.

Upper Study :

CSS:
#// Indicator For TOS
#// © MyTradingCoder
#indicator("Advanced Keltner Channel/Oscillator [MyTradingCoder]")
# Converted by Sam4Cok@Samer800    - 0/2024


input source = close; #, "Source", group = filter_group)
input length = 20; #, "Length", step = 0.5, minval = 2, group = filter_group)
input Q = 0.50;#, "Q", step = 0.125, minval = 0.125, group = filter_group)
input Multiplier = 2.0; #, "Multiplier", minval = 0, step = 0.25, group = atr_group)
input atrPeriod = 50; #, "Length", minval = 1, group = atr_group)
input atr_smoothing = yes; #(true, "Smoothing", group = atr_group) ? 2 : 1

def na = Double.NaN;

#-- Color
DefineGlobalColor("up", CreateColor(8, 153, 129));
DefineGlobalColor("dn", CreateColor(242, 54, 69));

#// filter {
script biquad_lpf {
    input source = close;
    input length = 10;
    input Q = 0.5;
    def na = Double.NaN;
    def pi = Double.Pi;
    def isfirst = BarNumber() <= 1;
    def fc = Min(0.5, 1 / length);
    def omega = 2 * pi * fc;
    def cos_omega = Cos(omega);
    def alpha = Sin(omega) / (2 * Q);
    def a0 = 1 / (1 + alpha);
    def b = 1 - cos_omega;
    def a1;
    def a2;
    def b0;
    def b1;
    def b2;
    if isfirst {
        a1 = -2 * cos_omega * a0;
        a2 = (1 - alpha) * a0;
        b0 = b / 2 * a0;
        b1 = b * a0;
        b2 = b0;
    } else {
        a1 = if !a1[1] then na else a1[1];
        a2 = if !a2[1] then na else a2[1];
        b0 = if !b0[1] then na else b0[1];
        b1 = if !b1[1] then na else b1[1];
        b2 = if !b2[1] then na else b2[1];
    }
    def biquad;
    def prQuad = CompoundValue(1, if !biquad[1] then source else biquad[1], source);
    def x = if source then source else x[1];
    def x1 = CompoundValue(1, if source[1] then source[1] else x, source);
    def x2 = CompoundValue(1, if source[2] then source[2] else x1, x1);
    def y1 = CompoundValue(1, if prQuad then prQuad else x, x);
    def y2 = CompoundValue(1, if prQuad[1] then prQuad[1] else y1, y1);
    biquad = b0 * x + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
    plot out = if isfirst then source else biquad;
}
script advanced_atr {
input period = 50;
    def tr = high - low;
    def sumTr = Sum(Sqr(tr), period);
    def rms = Sqrt(sumTr / Max(1, period -1));
    def z = tr / rms;
    def clamped_z = Min(z, 10);
    def rounded_z = Round(clamped_z, 2);
    def zidx = Floor(rounded_z * 100);
    def z_idx = if isNaN(zidx) then 0 else zidx;
    def lookback = 1001;
    def rang_observations = if z_idx != 0 then z_idx else rang_observations[1];
    def mode = (if period<=1 then 100 else 56) / 100 * rms;
    def average = Average(rang_observations + 1, lookback) / 100 * rms;
    plot avg = average;
    plot mod = mode;
}
script smoothing {
    input source = close;
    input smoothing = yes;
    def length = if smoothing then 2 else 1;
    def wma = WMA(source, length);
    def smooth = Average(wma, length);
    plot out = smooth;
}
script normal_delta_scale {
    input source = close;
    input atr = 1;
    input degree = 2;
    def pi = Double.Pi;
    def delta = (source - source[degree]) / atr;
    def todegrees = ATan(delta) * 180 / pi;
    def color_scale = (todegrees + 90) / 180;
    plot out = color_scale;
}

def average = advanced_atr(atrPeriod).avg;
def mode    = advanced_atr(atrPeriod).mod;
def biquad  = biquad_lpf(source, length, Q);
def midline = smoothing(mode * Multiplier, atr_smoothing);
def maxline = smoothing(average * Multiplier, atr_smoothing);
def top_midline = biquad + midline;
def top_maxline = biquad + maxline;
def bottom_midline = biquad - midline;
def bottom_maxline = biquad - maxline;
def color_scale = normal_delta_scale(biquad, mode);
def delta_color = if IsNaN(color_scale) then 0 else
                  if color_scale > 1 then 255 else
                  if color_scale < 0 then 0 else color_scale * 255;

def top_mid_line = if top_midline then top_midline else na;
def bottom_mid_line = if bottom_midline then bottom_midline else na;

plot centerLine = if biquad then biquad else na;
plot top_max_line = if top_maxline then top_maxline else na;
plot bot_max_line = if bottom_maxline then bottom_maxline else na;
centerLine.SetLineWeight(2);
centerLine.AssignValueColor(CreateColor(255 - delta_color, delta_color, 72));
top_max_line.SetDefaultColor(GlobalColor("dn"));
bot_max_line.SetDefaultColor(GlobalColor("up"));

AddCloud(top_max_line, top_mid_line, Color.DARK_RED, Color.DARK_RED, yes);
AddCloud(bottom_mid_line, bot_max_line, Color.DARK_GREEN, Color.DARK_GREEN, yes);

#-- END of CODE

Lower Study:

CSS:
#// Indicator for TOS
#// © MyTradingCoder
#indicator("Advanced Keltner Channel/Oscillator [MyTradingCoder]")
# Converted by Sam4Cok@Samer800    - 08/2024
Declare lower;

input osc_source = close; #, "Source", group = osc_settings)
input SourceSmoothing = 3.0; #, "Source Smoothing", step = 0.5, minval = 0, group = osc_settings) + 1
input signalLinePeriod = 9; #, "Signal Period", minval = 1, group = osc_settings)
input NormalizeOscillator = yes; #(true, "Normalize Oscillator", group = osc_settings)
input source = close; #, "Source", group = filter_group)
input length = 20; #, "Length", step = 0.5, minval = 2, group = filter_group)
input Q = 0.50;#, "Q", step = 0.125, minval = 0.125, group = filter_group)
input Multiplier = 2.0; #, "Multiplier", minval = 0, step = 0.25, group = atr_group)
input atrPeriod = 50; #, "Length", minval = 1, group = atr_group)
input atr_smoothing = yes; #(true, "Smoothing", group = atr_group) ? 2 : 1

def na = Double.NaN;
def last  = isNaN(close);
def osc_length = SourceSmoothing + 1;
#-- Color
DefineGlobalColor("up", CreateColor(8,153,129));
DefineGlobalColor("dn", CreateColor(242,54,69));
#// osc {
Script make_osc {
input source = close;
input min = low;
input max = high;
input center = hl2;
input normalize = yes;
    def norm = -100 + (source - min) * 200 / (max - min);
    def make_osc = if normalize then norm else source - center;
    plot out = make_osc;
}
#// filter {
#// filter {
script biquad_lpf {
    input source = close;
    input length = 10;
    input Q = 0.5;
    def na = Double.NaN;
    def pi = Double.Pi;
    def isfirst = BarNumber() <= 1;
    def fc = Min(0.5, 1 / length);
    def omega = 2 * pi * fc;
    def cos_omega = Cos(omega);
    def alpha = Sin(omega) / (2 * Q);
    def a0 = 1 / (1 + alpha);
    def b = 1 - cos_omega;
    def a1;
    def a2;
    def b0;
    def b1;
    def b2;
    if isfirst {
        a1 = -2 * cos_omega * a0;
        a2 = (1 - alpha) * a0;
        b0 = b / 2 * a0;
        b1 = b * a0;
        b2 = b0;
    } else {
        a1 = if !a1[1] then na else a1[1];
        a2 = if !a2[1] then na else a2[1];
        b0 = if !b0[1] then na else b0[1];
        b1 = if !b1[1] then na else b1[1];
        b2 = if !b2[1] then na else b2[1];
    }
    def biquad;
    def prQuad = CompoundValue(1, if !biquad[1] then source else biquad[1], source);
    def x = if source then source else x[1];
    def x1 = CompoundValue(1, if source[1] then source[1] else x, source);
    def x2 = CompoundValue(1, if source[2] then source[2] else x1, x1);
    def y1 = CompoundValue(1, if prQuad then prQuad else x, x);
    def y2 = CompoundValue(1, if prQuad[1] then prQuad[1] else y1, y1);
    biquad = b0 * x + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
    plot out = if isfirst then source else biquad;
}
Script ema {
input source = close;
input length = 9;
    def bar = BarNumber();
    def prefilter = if bar < 2 then source else Average(source, 2);
    def alpha = 2 / (length + 1);
    def smoothed = CompoundValue(1, alpha * prefilter + (1 - alpha) * smoothed[1],alpha * prefilter);
    plot ema = if length > 1 then smoothed else source;
}
script advanced_atr {
input period = 50;
    def tr = high - low;
    def sumTr = Sum(Sqr(tr), period);
    def rms = Sqrt(sumTr / Max(1, period -1));
    def z = tr / rms;
    def clamped_z = Min(z, 10);
    def rounded_z = Round(clamped_z, 2);
    def zidx = Floor(rounded_z * 100);
    def z_idx = if isNaN(zidx) then 0 else zidx;
    def lookback = 1001;
    def rang_observations = if z_idx != 0 then z_idx else rang_observations[1];
    def mode = (if period<=1 then 100 else 56) / 100 * rms;
    def average = Average(rang_observations + 1, lookback) / 100 * rms;
    plot avg = average;
    plot mod = mode;
}
Script smoothing {
input source = close;
input smoothing = yes;
    def length = if smoothing then 2 else 1;
    def wma = wma(source, length);
    def smooth = Average(wma, length);
    plot out = smooth;
}
Script normal_delta_scale {
input source = close;
input atr = 1;
input degree = 2;
    def pi = Double.Pi;
    def delta = (source - source[degree]) / atr;
    def todegrees = atan(delta) * 180 / pi;
    def color_scale = (todegrees + 90) / 180;
    plot out = color_scale;
}

def average = advanced_atr(atrPeriod).avg;
def mode    = advanced_atr(atrPeriod).mod;
def biquad  = biquad_lpf(source, length, Q);
def midline = smoothing(mode * Multiplier, atr_smoothing);
def maxline = smoothing(average * Multiplier, atr_smoothing);
def top_midline = biquad + midline;
def top_maxline = biquad + maxline;
def bottom_midline = biquad - midline;
def bottom_maxline = biquad - maxline;
def color_scale = normal_delta_scale(biquad, mode);
def delta_color = if isNaN(color_scale) then 0 else
                  if color_scale>1 then 255 else
                  if color_scale<0 then 0 else color_scale * 255;

#// osc {
def osc_midline_top = make_osc(top_midline, bottom_maxline, top_maxline, biquad, NormalizeOscillator);
def osc_midline_bottom = make_osc(bottom_midline, bottom_maxline, top_maxline, biquad, NormalizeOscillator);
def osc_max_top = make_osc(top_maxline, bottom_maxline, top_maxline, biquad, no);
def osc_max_bot = make_osc(bottom_maxline, bottom_maxline, top_maxline, biquad, no);
def osc_maxline_top = if last then na else if NormalizeOscillator then 100 else osc_max_top;
def osc_maxline_bottom = if last then na else if NormalizeOscillator then -100 else osc_max_bot;
def osc_normal = make_osc(osc_source, bottom_maxline, top_maxline, biquad, NormalizeOscillator);
def osc_line   = ema(osc_normal, osc_length);
def osc_signal = ema(osc_line, signalLinePeriod);
def top_mid_line_osc = if osc_midline_top then osc_midline_top else na;
def bottom_mid_line_osc = if osc_midline_bottom then osc_midline_bottom else na;

plot Oscillator = if osc_line then osc_line else na;
plot Signal = if osc_signal then osc_signal else na;
plot top_max_line_osc = if osc_maxline_top then osc_maxline_top else na;
plot bottom_max_line_osc = if osc_maxline_bottom then osc_maxline_bottom else na;
plot zero = if last then na else 0;
Oscillator.SetDefaultColor(Color.CYAN);
Signal.SetDefaultColor(GetColor(8));
zero.AssignValueColor(CreateColor(255 - delta_color, delta_color, 72));
top_max_line_osc.SetDefaultColor(GlobalColor("dn"));
bottom_max_line_osc.SetDefaultColor(GlobalColor("up"));

AddCloud(top_max_line_osc, top_mid_line_osc, Color.DARK_RED, Color.DARK_RED, yes);
AddCloud(bottom_mid_line_osc, bottom_max_line_osc, Color.DARK_GREEN, Color.DARK_GREEN, yes);

#-- END of CODE
 

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
434 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top