I made this indicator some time ago based on the FW_MOBO code. After doing a few changes recently, I thought I might share it here. It is similar to Raghee Horner's GRaB indicator, but uses keltner channels instead of offset 34 EMAs. I feel it is best for showing trends in the market.
Code:
# MomentumKeltnerChannels
# Pensar
# 06/06/2020
# Based on the FW_MOBO code by TOS user davidinc (aka Firstwave, aka David Elliott)
# Modified code to use Keltner Channels, changed code structure.
# Added colored price and user-adjustable global colors.
#Inputs
input length = 34;
input factor = 0.5;
input displace = 0;
input price = close;
input type = AverageType.SIMPLE;
input pricecolor = yes;
input fill = yes;
input arrows = yes;
input alerts = yes;
input sound = {default "Ding", "Bell", "Chimes", "NoSound", "Ring"};
#Variables
def nan = double.nan;
def shift = factor * MovingAverage(type, TrueRange(high, close, low), length);
def avg = MovingAverage(type, price, length);
def line1 = avg[-displace] - shift[-displace];
def line2 = avg[-displace] + shift[-displace];
def Chg = if(close > line2, 1, if(close < line1, -1, 0));
def Hold = CompoundValue(1,if(Hold[1] == Chg or Chg == 0, Hold[1], if(Chg == 1, 1, -1)), 0);
def ArUp = if !arrows or Hold[0] == Hold[1] then nan else if Hold[0] == 1 then line1 else nan;
def ArDn = if !arrows or Hold[0] == Hold[1] then nan else if Hold[0] == -1 then line2 else nan;
def LBUp = if fill and Hold[0] == 1 then line2 else nan;
def UBUp = if fill and Hold[0] == 1 then line1 else nan;
def LBDn = if fill and Hold[0] == -1 then line2 else nan;
def UBDn = if fill and Hold[0] == -1 then line1 else nan;
def AlertUp = alerts and Hold[1] == 1 and (Hold[1] <> Hold[2]);
def AlertDn = alerts and Hold[1] == -1 and (Hold[1] <> Hold[2]);
#Colors
DefineGlobalColor("Cloud Up", color.dark_green);
DefineGlobalColor("Cloud Dn", color.dark_red);
DefineGlobalColor("Channel Up", color.green);
DefineGlobalColor("Channel Down", color.red);
DefineGlobalColor("Price Up", color.green);
DefineGlobalColor("Price Neutral", color.gray);
DefineGlobalColor("Price Down", color.red);
#Plots
plot UB = line1;
UB.SetLineWeight(1);
UB.AssignValueColor(if Hold[0] == 1 then GlobalColor("Channel Up")
else GlobalColor("Channel Down"));
plot LB = line2;
LB.SetLineWeight(1);
LB.AssignValueColor(if Hold[0] == 1 then GlobalColor("Channel Up")
else GlobalColor("Channel Down"));
plot BOA = ArUp;
BOA.SetPaintingStrategy(PaintingStrategy.Arrow_Up);
BOA.SetDefaultColor(color.green);
BOA.SetLineWeight(2);
plot BDA = ArDn;
BDA.SetPaintingStrategy(PaintingStrategy.Arrow_Down);
BDA.SetDefaultColor(color.red);
BDA.SetLineWeight(2);
#Clouds
AddCloud(LBUp, UBUp, GlobalColor("Cloud Up"), GlobalColor("Cloud Dn"));
AddCloud(LBDn, UBDn, GlobalColor("Cloud Dn"), GlobalColor("Cloud Up"));
#Price Color
AssignPriceColor(if pricecolor then if close > line2 then GlobalColor("Price Up")
else if close < line1 then GlobalColor("Price Down")
else GlobalColor("Price Neutral")
else color.current);
#Alerts
Alert(AlertUp, "BREAKOUT!", Alert.Bar, Sound);
Alert(AlertDn, "BREAKDOWN!", Alert.Bar, Sound);
# --- End code ---