Keltner COG Channel Mutations Indicator[KCGMut] for ThinkOrSwim

samer800

Moderator - Expert
VIP
Lifetime
7CbxOCZ.png


* Added bar color option and option to choose manual step instead of auto.

Author Message:
Columns
For the channel-width-percent half of the value is used and for the COG-width-percent the whole to get a better image
By plotting the columns of the full width before those of the COG, in two series of positive and negative values, I created the illusion of a column with a different colored patch representing the COG (most are black) at the bottom where it points up (showing momentum is up), in the middle when the close is in the COG (no momentum) or at the top when the close is below the COG (showing momentum is down)

coloring drama
When nothing much happens, i.e. the channels keep the same width of shrink a bit, the columns get an unobtrusive color, black for the small COG patches and bluish gray for the channel columns pointing up or sideways, reddish gray when pointing down. If the COG increases (drama) the patches get colored lime (up), red (down) or orange (sideways, very seldom). If the channel increases, the columns get colored gold (up), maroon (down) or orange (sideways). Because the COG is derived from a Donchian channel, drama means a new high or low in the lookback period. Drama in the KeltCOG channel just means increase in volatility .

histogram showing volume spikes
Blue spikes indicate more then twice as much volume then recently normal, Maroon spikes indicate clear increases less then twice. To prevent the histogram from disappearing behind a column it is plotted first, spikes made longer then the column and also plotted both positive and negative. Single volume spikes don’t mean much, however if these occur in consecutive series and also come together with drama like new highs or increase in volatility , volume is worth noting. I regard such events as ‘voting’, the market ‘votes’ up or down. The REVE analyses these events to asses whether the volume stems from huge institutional traders (‘whales’) or large numbers of small traders (‘muppets’). This might be interesting too.

CODE: - Lower Study
CSS:
#// This source code is subject to the terms of the Mozilla Public License 2.0 at
#// © eykpunter
#https://www.tradingview.com/script/sZvBR1Vq-KCGmut/
#indicator("Keltner Center Of Gravity Channel Mutations Indicator", shorttitle="KCGMut")
# Converted and mod by Sam4COK@Samer800 - 10/2022
Declare lower;
input AutoStep = yes;
input ManualStep = 14;
input ColorBar = no;
input ShowVolumeEvent = yes;


def na = Double.NaN;
def h = high; def l = low; def v = volume; def c = close;
def bar = BarNumber();
def tf = GetAggregationPeriod();

def setper = if tf >= AggregationPeriod.WEEK then 14 else
             if tf >= AggregationPeriod.DAY then 21 else
             if tf >= AggregationPeriod.FOUR_HOURS then 28 else
             if tf >= AggregationPeriod.HOUR then 35 else
             if tf >= AggregationPeriod.FIFTEEN_MIN then 42 else
             if tf >= AggregationPeriod.THREE_MIN then 49 else
             if tf >= AggregationPeriod.MIN then 56 else 10;
def per = if AutoStep then setper else ManualStep;

#//KeltCOG RELEVANT CODE
#//Calculate channel
#//Calculate COG
def donhigh = Highest(h, per);
def donlow = Lowest(l, per);
def cent = (donhigh + donlow) / 2;
def donrange = donhigh - donlow;
def coglow = donlow + donrange * 0.382;
def coghigh = donlow + donrange * 0.618;

#//Calculate borders
#//calculate width (i.e. COG to border)
#//script adepts width to lookback period
def formula = round(2 + per/25 - 6/per, 1);
def varwidth = if(Bar<=1,2,formula);
def dis = atr(per);
def horizontal = if bar<= 1 then no else if coglow==coglow[1] then yes else no;
def outerhigh = if bar<= 1 then coghigh else if horizontal then
                   outerhigh[1] else coghigh + varwidth * dis;
def outerlow  = if bar<= 1 then coglow else if horizontal then
                   outerlow[1] else coglow - varwidth * dis;

#//CALCULATE VALUES FOR INDICATOR
#//define direction
def trendup   = c >  coghigh;
def trenddown = c <  coglow;
def trendside = c <= coghigh and c >= coglow;

#//define width percent of channel
def widchan    = outerhigh - outerlow;
def perchan    = if trendside then round(widchan/cent*25, 1) else round(widchan/cent*50, 1);
def negperchan = -perchan;

#//define width percent of cog
def widcog    = coghigh-coglow;
def percog    = if trendside then round(widcog/cent*50, 1) else round(widcog/cent*100, 1);
def negpercog = -percog;

#//CALCULATE VOLUME EXPANSION EVENTS
#usual(src) =>
script usual {
input src = volume;
    def pick = sum(src,3) - highest(src,3) - lowest(src,3);
    def usual = (sum(pick,6) - highest(pick,6) - lowest(pick,6))/4;
plot return = usual;
}
#// end of function
#//finding volume events
def usuvol= usual(v);# //find something to compare present volume with
def relv = if v>usuvol then 100*(v - usuvol)/v else 0;
def eventbig = relv>50;
def event = relv>20 and relv<=50;
def evline = if eventbig then widchan/cent*60 else if event then widchan/cent*45 else 0;
def negevline = if eventbig then -widchan/cent*60 else if event then -widchan/cent*35 else 0;
def volcol = if eventbig then 1 else 0;

#//PRAPARE AND EXECUTE PLOTS
#//define swelling situations
def chanswellup   = widchan > widchan[1] and trendup;
def chanswelldown = widchan > widchan[1] and trenddown;
def chanswellside = widchan > widchan[1] and trendside;
def cogswellup    = widcog > widcog[1] and trendup;
def cogswelldown  = widcog > widcog[1] and trenddown;
def cogswellside  = widcog > widcog[1] and trendside;

#//second plots

plot PosChannel = if trenddown or trendside then negpercog else na; # "COGwidth as per neg"
PosChannel.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
PosChannel.AssignValueColor(if cogswellup then CreateColor(0,230,118) else
                            if cogswelldown then CreateColor(255,82,82) else
                            if cogswellside then CreateColor(255,152,0) else Color.BLACK);

plot NegChannel = if trenddown or trendside then negperchan else na; # "channelwidth as per neg"
NegChannel.AssignValueColor(if chanswellup then CreateColor(236, 177, 38) else
                            if chanswelldown then CreateColor(136,14,79) else
                            if chanswellside then CreateColor(245,124,0) else
                            if trenddown then CreateColor(210,140,185) else CreateColor(130,148,164));
NegChannel.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);

plot COGwidth = if trendup or trendside then percog else na; # "COGwidth as per of middle line"
COGwidth.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
COGwidth.AssignValueColor(if cogswellup then CreateColor(0,230,118) else
                          if cogswelldown then CreateColor(255,82,82) else
                          if cogswellside then CreateColor(255,152,0) else Color.BLACK);

plot channelwidth = if trendup or trendside then perchan else na; # "channelwidth as per of middle"
channelwidth.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
channelwidth.AssignValueColor(if chanswellup then CreateColor(236, 177, 38) else
                              if chanswelldown then CreateColor(136,14,79) else
                              if chanswellside then CreateColor(245,124,0) else
                              if trenddown then CreateColor(210,140,185) else CreateColor(130,148,164));
#//firstplots
plot NegVolHis = if ShowVolumeEvent then negevline else na;    # "volume event neg"
NegVolHis.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
NegVolHis.AssignValueColor(if volcol then CreateColor(33,150,243) else CreateColor(136,14,79));

plot PosVolHis = if ShowVolumeEvent then evline else na;      # "volume event pos"
PosVolHis.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
PosVolHis.AssignValueColor(if volcol then CreateColor(33,150,243) else CreateColor(136,14,79));

#----Bar Color
Def ExUp = chanswellup and cogswellup;
Def Up    = cogswellup;
Def WeakUp = trendup;
Def Dn    = cogswelldown;
Def ExDn = chanswelldown and cogswelldown;
def WeakDn = trenddown;
AssignPriceColor( if !ColorBar then Color.CURRENT else
                  if ExUp then CreateColor(1,255,0) else
                  if Up then CreateColor(4,181,4) else
                  if WeakUp then CreateColor(2,117,2) else
                  if ExDn then CreateColor(255,5,5) else
                  if Dn then CreateColor(184,6,6) else
                  if WeakDn then CreateColor(117,2,2) else Color.GRAY);
#----END

CODE: - Upper Study
CSS:
#// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
#// © eykpunter
#indicator(title='Keltner Center Of Gravity Channel', shorttitle='KeltCOG', overlay=true)
# Converted and mod by Sam4COK@Samer800 - 04/2023
#/activate feedback labels
input ColorBar = no;
input showLookbackAndWidthLabel = yes;          # 'show #lookback and width feedback label on chart'
input showVolatilityAsPercentLabel = yes;       # 'show width of channel (volatility) as percent of price'
input AutoStep = yes;
input ManualStep = 14;
input automaticWidthMultiplier = yes;           # 'automatic width multiplier adjustment to lookback period'
input ManualWidthMultiplier = 2.00;             #  //initialize variable width
input showChannel = yes;
input supertrendMode = no;                      # "toggle channel mode (off) supertrend mode (on)"
#input showChannelAndSupertrend  = no;           # "show both channel and supertrend modes"
input ShowOuterZonesCombinedWithSupertrend = no;# "Show outer zones combined with supertrend"
#//activate extra lines
input showExtraKeltnerLineAboveChannel = no;    # 'show extra keltner line above channel'
input showExtraKeltnerLineBelowChannel = no;    # 'show extra keltner line below channel'
input showLast_20_Of_40_periodHullMovingAverage = no;    # 'show last 20 of 40 period Hull Moving Average'

def na = Double.NaN;
def jz = supertrendMode;
#def bz = showChannelAndSupertrend;
def zz = ShowOuterZonesCombinedWithSupertrend;
def feedbwish = showLookbackAndWidthLabel;
def centwish = showVolatilityAsPercentLabel;
def plushiwish = showExtraKeltnerLineAboveChannel;
def pluslowish = showExtraKeltnerLineBelowChannel;
def hmawish = showLast_20_Of_40_periodHullMovingAverage;
def setwish = automaticWidthMultiplier;
def variableWidth = ManualWidthMultiplier;

#--- Color
DefineGlobalColor("blue"    , CreateColor(0, 37, 139));
DefineGlobalColor("dblue"   , CreateColor(0, 27, 100));
DefineGlobalColor("dgreen"  , CreateColor(0, 89, 0));
DefineGlobalColor("yellow"  , CreateColor(108, 108, 0));
DefineGlobalColor("red"     , CreateColor(137, 0, 0));
DefineGlobalColor("dred"    , CreateColor(78, 0, 0));
DefineGlobalColor("green1"  , CreateColor(76, 175, 80));
DefineGlobalColor("red1"    , CreateColor(255, 82, 82));
DefineGlobalColor("superUp" , CreateColor(98, 89, 3));
DefineGlobalColor("superDn" , CreateColor(100, 10, 58));
DefineGlobalColor("hma"     , CreateColor(190, 123, 45));
DefineGlobalColor("pblue"   , CreateColor(0, 58, 220));
DefineGlobalColor("pgreen"  , CreateColor(53, 122, 56));
DefineGlobalColor("pred"    , CreateColor(255, 5, 5));
DefineGlobalColor("porange" , CreateColor(179, 106, 0));
DefineGlobalColor("extra"   , CreateColor(128,128,0));


def nzz = !zz;#                            //condition to ditch inner zones
def naz = if (jz or zz or showChannel) then yes else no;# //condition to show patches and nearby fib
def az  = if (zz or showChannel) then yes else if jz then no else yes;#  //condition to show standard channel

def h = high;
def l = low;
def v = volume;
def c = close;
def tf = GetAggregationPeriod();
def setper = if tf >= AggregationPeriod.WEEK then 14 else
             if tf >= AggregationPeriod.DAY then 21 else
             if tf >= AggregationPeriod.FOUR_HOURS then 28 else
             if tf >= AggregationPeriod.HOUR then 35 else
             if tf >= AggregationPeriod.FIFTEEN_MIN then 42 else
             if tf >= AggregationPeriod.THREE_MIN then 49 else
             if tf >= AggregationPeriod.MIN then 56 else 10;
def per = if AutoStep then setper else ManualStep;


def formula = Round(2 + per / 25 - 6 / per, 1);#  //Script uses this formula to adapt Width (i.e COG to border) to look back period
def varwidth = if setwish then formula else variableWidth;


#//Calculate values for channel lines
def dis = ATR(LEngth = per);    # //Keltner channels have lines spaced by average true range
def donhigh = Highest(high, per);#  //COG calculated using values of Donchian channel
def donlow = Lowest(low, per);#
def cent = (donhigh + donlow) / 2;#  //center line not plotted, used calculation of widthpercent
def donrange = donhigh - donlow;#
def fiblow = donlow + donrange * 0.236;    # //Low fibonacci line
def L4 = donlow + donrange * 0.382;        # //L4=Coglow Actually a Center Low fibonacci line in my donchian fibonacci channel
def L3 = donlow + donrange * 0.618;        # //L3=Coghigh center high fibonacci
def fibhigh = donlow + donrange * 0.764;   # //high fibonacci line

def horizontal = if L4 == L4[1] then yes else no;
def L2 = fibhigh;
def L1 = if horizontal then L1[1] else L3 + varwidth * dis;
def outhighplus = if plushiwish then L1 + 2 * dis else na;
def L5 = fiblow;
def L6 = if horizontal then L6[1] else L4 - varwidth * dis;
def outlowplus = if pluslowish then L6 - 2 * dis else na;

#//values for extra HMA40
def hma40 = if hmawish then HullMovingAvg(close, 40) else na;#  //40 period Hull Moving Average calculated when wished for

#//define values for permanent lines (standard channel)
def outerhigh = if az then L1 else na;
def innerhigh = if az then L2 else na;
def coghigh   = if az and nzz then L3 else na;
def coglow   = if az and nzz then L4 else na;
def innerlow = if az then L5 else na;
def outerlow = if az then L6 else na;

#//define plots of permanent lines (channel mode)
plot pphi = outhighplus;   # 'extra high line'
plot pplo = outlowplus;    # 'extra low line'
def pohi = outerhigh;      # 'outerhigh'
def pihi = innerhigh;      # 'innerhigh'
def pchi = coghigh;        # 'coghigh'
def pclo = coglow;         # 'coglow'
def pilo = innerlow;       # 'innerlow'
def polo = outerlow;

pphi.SetDefaultColor(GlobalColor("extra"));
pplo.SetDefaultColor(GlobalColor("extra"));
#//define fills between permanent lines (area)
AddCloud(if !showChannel then na else if nzz then pohi else na,  pihi,  GlobalColor("blue"),  GlobalColor("blue"));    #'uptrend area'
AddCloud(if !showChannel then na else if !nzz then pohi else na, pihi, GlobalColor("dblue"), GlobalColor("dblue"), yes); #'uptrend area'
AddCloud(if !showChannel then na else pihi, pchi, GlobalColor("dgreen"), GlobalColor("dgreen"), yes);    # 'look up area'
AddCloud(if !showChannel then na else pchi, pclo, Color.DARK_GRAY);                                      # 'center area'
AddCloud(if !showChannel then na else pclo, pilo, GlobalColor("yellow"), GlobalColor("yellow"), yes);    # 'look down area'
AddCloud(if !showChannel then na else if nzz then pilo else na, polo, GlobalColor("red"), GlobalColor("red"), yes);    # 'downtrend area'
AddCloud(if !showChannel then na else if !nzz then pilo else na, polo, GlobalColor("dred"), GlobalColor("dred"), yes); # 'downtrend area'

#//define values for patch lines (super trend mode)
def CL1 = naz and high > L2;#                 //condition to show L1 as outhi
def CL2 = naz and high > L3 and low < L1;#    //condition to show L2 as inhi
def CL3 = naz and high > L4 and low < L2;#    //condition to show L3 as cogbase
def CL4 = naz and high > L5 and low < L3;#    //condition to show L4 as cogl
def CL5 = naz and high > L6 and low < L4;#    //condition to show L5 as inlow
def CL6 = naz and low < L5;#                  //condition to show L6 as outlow 

def outhi   = if CL1 then Min(L1, Max(high, Max(high[1], Max(high[2], Max(high[3], high[4]))))) else na;
def inhi    = if CL2 then L2 else na;
def coghi   = if CL3 then L3 else na;
def cogl    = if CL4 then L4 else na;
def inlow   = if CL5 then L5 else na;
def outlow  = if CL6 then Max(L6, Min(low, Min(low[1], Min(low[2], Min(low[3], low[4]))))) else na;
def support = if CL6 then L5 else if CL5 then L5 else if CL4 then L4 else
              if CL3 then L3 else if CL2 then L2 else if CL1 then L2 else na;#     //level for nearby supportive fib
def resist  = if CL1 then L2 else if CL2 then L2 else if CL3 then L3 else
              if CL4 then L4 else if CL5 then L5 else if CL6 then L5 else na;#     //level for nearby resistive fib

#/supertrend

def up;
def dn;
def mid = if supertrendMode then hl2 else na;    # //midle value of bar
def up_ = mid - (varwidth * dis);     # //same settings as channel used
def dn_ = mid + (varwidth * dis);

def up1 = if supertrendMode then
          if up[1] == 0 then up_ else up[1] else na;
def dn1 = if supertrendMode then
          if dn[1] == 0 then dn_ else dn[1] else na;

up = if supertrendMode then if close[1] > up1 then Max(up_, up1) else up_ else na;
dn = if supertrendMode then if close[1] < dn1 then Min(dn_, dn1) else dn_ else na;

def trend;# = 1
def trend_ = if trend[1] == 0 then 1 else trend[1];
trend = if trend_ == -1 and close > dn1 then 1 else
        if trend_ == 1  and close < up1 then -1 else trend_;

def supres = if supertrendMode then if trend == 1 then support else resist else na;

#//define plots for supertrend mode
plot upPlot = if trend == 1 then up else na;    # "Up Trend"
plot dnPlot = if trend == 1 then na else dn;    # "Down Trend"
def supresPlot = supres;                        # "Support/Resistance Level"
upPlot.SetDefaultColor(GlobalColor("green1"));
dnPlot.SetDefaultColor(GlobalColor("red1"));

upPlot.SetLineWeight(2);
dnPlot.SetLineWeight(2);

#//define fills between supertrend lines
AddCloud(supresPlot, upPlot, GlobalColor("superUp"),  GlobalColor("superUp"), yes);    # "uptrend highlighter"
AddCloud(dnPlot, supresPlot,  GlobalColor("superDn"), GlobalColor("superDn"), yes);    # "downtrend highlighter"

#//define plots of patch lines
def pohir = outhi;
def pihir = inhi;#
def pchir = coghi;
def pclor = cogl;
def pilor = inlow;
def polor = outlow;

#//define fills between patch lines (patches)
AddCloud(pohir, pihir, GlobalColor("pblue"));     # 'go up patch'
AddCloud(pihir, pchir, GlobalColor("pgreen"));    # 'look up patch'
AddCloud(pchir, pclor, Color.GRAY);               # 'doubt patch'
AddCloud(pclor, pilor, GlobalColor("porange"));   # 'look down patch'
AddCloud(pilor, polor, GlobalColor("pred"));      # 'go down patch'

#//extra HMA40
def plotHma = InertiaAll(hma40, 20);
plot hma = if !IsNaN(plotHma) then hma40 else na;    # 'HMA'
hma.SetDefaultColor(GlobalColor("hma"));
hma.SetLineWeight(2);
#//define width percent label
def wide = L1 - L6;#  //outerhigh-outerlow
def percent = Round(wide / cent * 100, 1);

AddLabel(centwish, "KeltCOG width (volatility measure): " + percent + "%", Color.WHITE);
AddLabel(feedbwish, if AutoStep then
                   "Auto: KeltCOG lookback = " + per + if setwish then
                   " , Auto: COG to border multiplier (with ATR)" + varwidth else
                   " , Manual: COG to border multiplier (with ATR)" + varwidth else
                   "Manual: KeltCOG lookback = " + per + if setwish then
                   " , Auto: COG to border multiplier (with ATR)" + varwidth else
                   " , Manual: COG to border multiplier (with ATR)" + varwidth, Color.WHITE);

#--- Bar Color
def CLR1 = high > L2;#                 //condition to show L1 as outhi
def CLR2 = high > L3 and low < L1;#    //condition to show L2 as inhi
def CLR3 = high > L4 and low < L2;#    //condition to show L3 as cogbase
def CLR4 = high > L5 and low < L3;#    //condition to show L4 as cogl
def CLR5 = high > L6 and low < L4;#    //condition to show L5 as inlow

AssignPriceColor(if !ColorBar then Color.CURRENT else
                 if CLR1 then GlobalColor("pblue") else
                 if CLR2 then GlobalColor("pgreen") else
                 if CLR3 then Color.GRAY else
                 if CLR4 then GlobalColor("porange") else
                 if CLR5 then GlobalColor("pred") else Color.GRAY);
#--- End of Code
 
Last edited:

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
520 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