RedK Momentum Bars for ThinkOrSwim

samer800

Moderator - Expert
VIP
Lifetime
RMnGBn7.png

Added divergence identifier.
Creator Message:
Momentum Bars (Mo_Bars) offers a different way to visualize (relative) momentum - and uses some simple TA concepts to provide a different perspective into how we read momentum changes and incorporate that in our trading.

The idea here (and the script itself) is really super simple, and is (very loosely) inspired by Elder's Impulse System ( EIS ) - then evolved to leverage some other concepts, and to become less cluttering and "easier to read".
  • Using Mo_Bars
    ----------------------------
  • at a very broad level, we can use Mo_Bars similar to how we use a MACD - both are centered and unrestricted oscillators - note the difference that Mo_Bars is based on 3 MA's rather than 2.

  • the Mo_Bar bar length reflects the distance between the main MA and the signal MA - plotted relative to the baseline (filter line) - that means that the length of the bar represents the relative momentum between the 2 MA's - The Mo_Bars are then colored in a way that reflects increase or decrease in the value of that momentum (the visual here may have been inspired by another indicator recently published by one of our esteemed wizards - it worked perfectly - so due credits here :)

    -- in simple terms, if the main MA is below the signal MA, the bar is red - and when the main MA is above the signal MA, the bar is green - a white bar usually shows up when there's a detected change of relative momentum direction (note that this is not the same as the trend direction - and that's what helps show and exploit convergence and divergence - similar to a MACD )
CODE - Updated, MTF, Bar Color and signal style option.

CSS:
#// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
#// © RedKTrader
#indicator('[dev]RedK Momentum Bars', shorttitle='RedK MoBars v3.0', explicit_plot_zorder = true, timeframe='', timeframe_gaps=false)
#// A trading system composed of 2 short Lazy Lines (preferably one open and one close - 2-3 bars apart) and a WMA long filter
#// loosely inspired by Edler Impulse
#// v2.0 cleaned up code and added MA options to be able to mix and match, and experiment with various setups
#// default values (my personal preference) remain the same as in v1.0
#// for example, some traders will consider "bear territory" only below SMA50, others will use EMA30 .. and so on.
#// ---------------------------------------------------------------------------------------------------------------
#// MoBars v3.0:
#// updated defaults to match the most common 3x MA cross-over set-up of SMA (10, 20, 50)
#// updated visuals to push the 0 line to the background of the plot (using the explcit_plot_zorder param)
#// and added alerts for crossing up, down and swing around the 0 line (the Bullish/Bearish Filter MA)
#//==============================================================================
# Converted and mod by Sam4Cok@Samer800 - 12/2022
# added option for signal style, MTF and Bar Color - 06/2024
declare lower;

input colorBars = yes;
input timeframe = {Default "Chart", "Manual"};
input manualTimeframe = AggregationPeriod.FIFTEEN_MIN;
input source = {Default "HLCC4", "OHLC4", "CLOSE", "HLC3", "HL2"};
input Fast_Length = 10;        # 'Fast Length'
input Fast_Type   = {"RSS_WMA", "WMA", "EMA", default "SMA", "HMA"};
input Slow_Length = 20;        # 'Slow Length'
input Slow_Type   = {"RSS_WMA", "WMA", "EMA", default "SMA", "HMA"};
input Slow_Delay  = 3;
input Filter_Length  = 50;     # 'Filter MA Length'
input Filter_Type    =  {"RSS_WMA", "WMA", "EMA", default "SMA", "HMA"};

def na = Double.NaN;

def hi; def lo; def cl; def op;
Switch (timeframe) {
Case "Manual" :
    op = open(Period = manualTimeframe);
    hi = high(Period = manualTimeframe);
    lo = low(Period = manualTimeframe);
    cl = close(Period = manualTimeframe);
Default :
    op = open;
    hi = high;
    lo = low;
    cl = close;
}
def src;
Switch (source) {
Case "OHLC4" : src = (hi + lo + cl + op) / 4;
Case "CLOSE" : src = cl;
Case "HLC3" : src = (hi + lo + cl) / 3;
Case "HL2" : src = (hi + lo) / 2;
Default : src = (hi + lo + 2 * cl) / 4;
}
#def src = if source==source."OHLC4" then ohlc else hlcc;
#f_LazyLine(_data, _length) =>
script f_LazyLine {
    input _data = close;
    input _length = 10;
    def w1;
    def w2;
    def w3;
    def L1;
    def L2;
    def L3;
    def w = _length / 3;
    if _length > 2 {
        w2 = Round(w, 0);
        w1 = Round((_length - w2) / 2, 0);
        w3 = Floor((_length - w2) / 2);
        L1 = WMA(_data, w1);
        L2 = WMA(L1, w2);
        L3 = WMA(L2, w3);
    } else {
        w2 = 0;
        w1 = 0;
        w3 = 0;
        L1 = 0;
        L2 = 0;
        L3 = _data;
    }
    plot return = L3;
}
#//====================================
#f_getMA(source, length, type) =>
script f_getMA {
    input source = close;
    input length = 10;
    input type = "SMA";
    def ma = if type == "SMA" then Average(source, length) else
             if type == "EMA" then ExpAverage(source, length) else
             if type == "WMA" then WMA(source, length) else
             if type == "HMA" then HullMovingAvg(source, length) else
              f_LazyLine(source, length);
    plot return = ma;
}

#// -----Calculation
def Fast = f_getMA(Src, Fast_Length, Fast_Type);
def Slow = f_getMA(Src, Slow_Length, Slow_Type);
def Filter = f_getMA(Src, Filter_Length, Filter_Type);
def Fast_M  = Fast - Filter;
def Slow_M  = Slow - Filter;
def Rel_M   = WMA(Slow_M, Slow_Delay);

#// prep the Momentum bars
def o = Rel_M;
def c = Fast_M;
def h = Max(o, c);
def l = Min(o, c);
def momSrc = (h+l+c+o) / 4;
def rising = c > c[1];
def barup = c > o and rising;
def bardn = c < o and !rising;
def bardj = !barup and !bardn;
#/ ----Colors & Plots

plot zline = if IsNaN(close) then na else 0;
zline.SetDefaultColor(Color.GRAY);

AddChart(high = if barup then h else na , low = l , open = c,  close = o,
         type = ChartType.CANDLE, growcolor =  Color.GREEN);
AddChart(high = if bardn then h else na , low = l , open = o,  close = c,
         type = ChartType.CANDLE, growcolor =  Color.RED);
AddChart(high = if bardj then h else na , low = l , open = if rising then o else c,
         close = if rising then c else o,  type = ChartType.CANDLE, growcolor =  Color.WHITE);

#-- bar Color
def col = if barup then 1 else if bardn then -1 else 0;
AssignPriceColor(if !colorBars then Color.CURRENT else
                 if col>0 then Color.CYAN else if col<0 then Color.MAGENTA else COlor.GRAY);

#----Div-----------
input divSignalOptions = {Default "Bubbles", "Vertical Lines"};
input LookBackRight  = 5;           # "Pivot Lookback Right"
input LookBackLeft  = 5;           # "Pivot Lookback Left"
input MaxLookback = 60;   # "Max of Lookback Range"
input MinLookback = 5;    # "Min of Lookback Range"
input DivBull = yes;      # "Plot Bullish"
input DivBear = yes;      # "Plot Bearish"
input DivHiddenBull = no; # "Plot Hidden Bullish"
input DivHiddenBear = no; # "Plot Hidden Bearish"

def bubble = divSignalOptions==divSignalOptions."Bubbles";
def divSrc = momSrc;

script FindPivots {
    input dat = close; # default data or study being evaluated
    input HL  = 0;    # default high or low pivot designation, -1 low, +1 high
    input lbL  = 5;    # default Pivot Lookback Left
    input lbR  = 1;    # default Pivot Lookback Right
    ##############
    def _nan;    # used for non-number returns
    def _BN;     # the current barnumber
    def _VStop;  # confirms that the lookforward period continues the pivot trend
    def _V;      # the Value at the actual pivot point
    ##############
    _BN  = BarNumber();
    _nan = Double.NaN;
    _VStop = if !isNaN(dat) and lbr > 0 and lbl > 0 then
                fold a = 1 to lbR + 1 with b=1 while b do
                    if HL > 0 then dat > GetValue(dat,-a) else dat < GetValue(dat,-a) else _nan;
   if (HL > 0) {
        _V = if _BN > lbL and dat == Highest(dat, lbL+1) and _VStop
            then dat else _nan;
    } else {
        _V = if _BN > lbL and dat == Lowest(dat, lbL+1) and _VStop
            then dat else _nan;
    }
    plot result = if !IsNaN(_V) and _VStop then _V else _nan;
}

#_inRange(cond) =>
script _inRange {
    input cond = yes;
    input rangeUpper = 60;
    input rangeLower = 5;
        def bars = if cond then 0 else bars[1] + 1;
        def inrange =  (rangeLower <= bars) and (bars <= rangeUpper);
plot retrun = inRange;
}
def pl = findpivots(divSrc,-1, LookBackLeft, LookBackRight);
def ph = findpivots(divSrc, 1, LookBackLeft, LookBackRight);

def plFound = if !isNaN(pl) then 1 else 0;
def phFound = if !isNaN(ph) then 1 else 0;
def vlFound0 = if plFound then divSrc else vlFound0[1];
def vhFound0 = if phFound then divSrc else vhFound0[1];
def plPrice0 = if plFound then lo else plPrice0[1];
def phPrice0 = if phFound then hi else phPrice0[1];

def vlFound = if vlFound0!=vlFound0[1] then vlFound0[1] else vlFound[1];
def vhFound = if vhFound0!=vhFound0[1] then vhFound0[1] else vhFound[1];

def plPrice = if plPrice0!=plPrice0[1] then plPrice0[1] else plPrice[1];
def phPrice = if phPrice0!=phPrice0[1] then phPrice0[1] else phPrice[1];

#// Regular Bullish
def oscHL = divSrc > vlFound and  _inRange(plFound[1],MaxLookback,MinLookback);
def priceLL = lo < plPrice;
def bullCond = DivBull and plFound and oscHL and priceLL;
#// Hidden Bullish
def oscLL = divSrc < vlFound and  _inRange(plFound[1],MaxLookback,MinLookback);
def priceHL = lo > plPrice;
def hiddenBullCond = DivHiddenBull and plFound and oscLL and priceHL;

#// Regular Bearish
def oscLH   = divSrc < vhFound and  _inRange(phFound[1],MaxLookback,MinLookback);
def priceHH = hi > phPrice;
def bearCond = DivBear and phFound and oscLH and priceHH;
#// Hidden Bearish
def oscHH = divSrc > vhFound and  _inRange(phFound[1],MaxLookback,MinLookback);
def priceLH = hi < phPrice;
def hiddenBearCond = DivHiddenBear and phFound and oscHH and priceLH;

#------ Bubbles
addchartbubble(bubble and bullCond, l, "R", Color.CYAN, no);
addchartbubble(bubble and bearCond, h, "R", Color.MAGENTA, yes);
addchartbubble(bubble and hiddenBullCond, l, "H", color.DARK_GREEN, no);
addchartbubble(bubble and hiddenBearCond, h, "H", color.DARK_RED, yes);
#-- Vertica lines
AddVerticalLine(!bubble and bullCond, "Regular", Color.CYAN);
AddVerticalLine(!bubble and bearCond, "Regular", Color.MAGENTA);
AddVerticalLine(!bubble and hiddenBullCond, "Hidden", Color.DARK_GREEN);
AddVerticalLine(!bubble and hiddenBearCond, "Hidden", Color.DARK_RED);

#-- ENd Code

CODE:

CSS:
#// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
#// © RedKTrader
#indicator('[dev]RedK Momentum Bars', shorttitle='RedK MoBars v3.0', explicit_plot_zorder = true, timeframe='', timeframe_gaps=false)
#// A trading system composed of 2 short Lazy Lines (preferably one open and one close - 2-3 bars apart) and a WMA long filter
#// loosely inspired by Edler Impulse
#// v2.0 cleaned up code and added MA options to be able to mix and match, and experiment with various setups
#// default values (my personal preference) remain the same as in v1.0
#// for example, some traders will consider "bear territory" only below SMA50, others will use EMA30 .. and so on.
#// ---------------------------------------------------------------------------------------------------------------
#// MoBars v3.0:
#// updated defaults to match the most common 3x MA cross-over set-up of SMA (10, 20, 50)
#// updated visuals to push the 0 line to the background of the plot (using the explcit_plot_zorder param)
#// and added alerts for crossing up, down and swing around the 0 line (the Bullish/Bearish Filter MA)
#//==============================================================================
# Converted and mod by Sam4Cok@Samer800 - 12/2022
declare lower;
#f_LazyLine(_data, _length) =>
script f_LazyLine {
    input _data = close;
    input _length = 10;
    def w1;
    def w2;
    def w3;
    def L1;
    def L2;
    def L3;
    def w = _length / 3;
    if _length > 2 {
        w2 = Round(w, 0);
        w1 = Round((_length - w2) / 2, 0);
        w3 = Floor((_length - w2) / 2);
        L1 = WMA(_data, w1);
        L2 = WMA(L1, w2);
        L3 = WMA(L2, w3);
    } else {
        w2 = 0;
        w1 = 0;
        w3 = 0;
        L1 = 0;
        L2 = 0;
        L3 = _data;
    }
    plot return = L3;
}
#//====================================
#f_getMA(source, length, type) =>
script f_getMA {
    input source = close;
    input length = 10;
    input type = "SMA";
    def ma = if type == "SMA" then SimpleMovingAvg(source, length) else
             if type == "EMA" then ExpAverage(source, length) else
             if type == "WMA" then WMA(source, length) else
             if type == "HMA" then HullMovingAvg(source, length) else
              f_LazyLine(source, length);
    plot return = ma;
}
input Fast_Length = 10;        # 'Fast Length'
input Fast_Type   = {"RSS_WMA", "WMA", "EMA", default "SMA", "HMA"};
input Slow_Length = 20;        # 'Slow Length'
input Slow_Type   = {"RSS_WMA", "WMA", "EMA", default "SMA", "HMA"};
input Slow_Delay  = 3;
input Filter_Length  = 50;     # 'Filter MA Length'
input Filter_Type    =  {"RSS_WMA", "WMA", "EMA", default "SMA", "HMA"};

def na = Double.NaN;
def Src = (high + low + close + close) / 4;
#// -----Calculation
def Fast = f_getMA(Src, Fast_Length, Fast_Type);
def Slow = f_getMA(Src, Slow_Length, Slow_Type);
def Filter = f_getMA(Src, Filter_Length, Filter_Type);
def Fast_M  = Fast - Filter;
def Slow_M  = Slow - Filter;
def Rel_M   = WMA(Slow_M, Slow_Delay);

#// prep the Momentum bars
def o = Rel_M;
def c = Fast_M;
def h = Max(o, c);
def l = Min(o, c);

def rising = c > c[1];
def barup = c > o and rising;
def bardn = c < o and !rising;
def bardj = !barup and !bardn;
#/ ----Colors & Plots

plot zline = if IsNaN(close) then na else 0;
zline.SetDefaultColor(Color.GRAY);

AddChart(high = if barup then h else na , low = l , open = c,  close = o,
         type = ChartType.CANDLE, growcolor =  Color.GREEN);
AddChart(high = if bardn then h else na , low = l , open = o,  close = c,
         type = ChartType.CANDLE, growcolor =  Color.RED);
AddChart(high = if bardj then h else na , low = l , open = if rising then o else c,
         close = if rising then c else o,  type = ChartType.CANDLE, growcolor =  Color.WHITE);

#----Div-----------
input LookBackRight  = 5;           # "Pivot Lookback Right"
input LookBackLeft  = 5;           # "Pivot Lookback Left"
input MaxLookback = 60;   # "Max of Lookback Range"
input MinLookback = 5;    # "Min of Lookback Range"
input DivBull = yes;      # "Plot Bullish"
input DivBear = yes;      # "Plot Bearish"
input DivHiddenBull = no; # "Plot Hidden Bullish"
input DivHiddenBear = no; # "Plot Hidden Bearish"

def momSrc = (h+l+c+o) / 4;
def divSrc = momSrc;

def hi = high;
def lo = low;

script FindPivots {
    input dat = close; # default data or study being evaluated
    input HL  = 0;    # default high or low pivot designation, -1 low, +1 high
    input lbL  = 5;    # default Pivot Lookback Left
    input lbR  = 1;    # default Pivot Lookback Right
    ##############
    def _nan;    # used for non-number returns
    def _BN;     # the current barnumber
    def _VStop;  # confirms that the lookforward period continues the pivot trend
    def _V;      # the Value at the actual pivot point
    ##############
    _BN  = BarNumber();
    _nan = Double.NaN;
    _VStop = if !isNaN(dat) and lbr > 0 and lbl > 0 then
                fold a = 1 to lbR + 1 with b=1 while b do
                    if HL > 0 then dat > GetValue(dat,-a) else dat < GetValue(dat,-a) else _nan;
   if (HL > 0) {
        _V = if _BN > lbL and dat == Highest(dat, lbL+1) and _VStop
            then dat else _nan;
    } else {
        _V = if _BN > lbL and dat == Lowest(dat, lbL+1) and _VStop
            then dat else _nan;
    }
    plot result = if !IsNaN(_V) and _VStop then _V else _nan;
}
#valuewhen (Cond, source, lbr, occurrence)
script valuewhen {
  input cond = 0;
  input src = close;
  input MinLookback = 5;
  input MaxLookback = 60;
  input occurrence = 0;
  def n = occurrence + 1;
  def offset = fold j = MinLookback to MaxLookback + 1 with p=1 while p < n + 1
    do p + ( if p == n then j - n else if cond[j]==yes then 1 else 0 );
  plot price = GetValue(src, offset-1);
}
#_inRange(cond) =>
script _inRange {
    input cond = yes;
    input rangeUpper = 60;
    input rangeLower = 5;
        def bars = if cond then 0 else bars[1] + 1;
        def inrange =  (rangeLower <= bars) and (bars <= rangeUpper);
plot retrun = inRange;
}
def pl = findpivots(divSrc,-1, LookBackLeft, LookBackRight);
def ph = findpivots(divSrc, 1, LookBackLeft, LookBackRight);

def plFound = if !isNaN(pl) then 1 else 0;
def phFound = if !isNaN(ph) then 1 else 0;

def vlFound = valuewhen(plFound, divSrc, MinLookback, MaxLookback, 1);
def vhFound = valuewhen(phFound, divSrc, MinLookback, MaxLookback, 1);

def plPrice = valuewhen(plFound, lo, MinLookback, MaxLookback, 1);
def phPrice = valuewhen(phFound, hi, MinLookback, MaxLookback, 1);

#// Regular Bullish
def oscHL = divSrc > vlFound and  _inRange(plFound[1],MaxLookback,MinLookback);
def priceLL = lo < plPrice;
def bullCond = DivBull and plFound and oscHL and priceLL;
#// Hidden Bullish
def oscLL = divSrc < vlFound and  _inRange(plFound[1],MaxLookback,MinLookback);
def priceHL = lo > plPrice;
def hiddenBullCond = DivHiddenBull and plFound and oscLL and priceHL;

#// Regular Bearish
def oscLH   = divSrc < vhFound and  _inRange(phFound[1],MaxLookback,MinLookback);
def priceHH = hi > phPrice;
def bearCond = DivBear and phFound and oscLH and priceHH;
#// Hidden Bearish
def oscHH = divSrc > vhFound and  _inRange(phFound[1],MaxLookback,MinLookback);
def priceLH = hi < phPrice;
def hiddenBearCond = DivHiddenBear and phFound and oscHH and priceLH;

#------ Bubbles
addchartbubble(bullCond, divSrc, "R", color.GREEN, no);
addchartbubble(bearCond, divSrc, "R", CreateColor(156,39,176), yes);
addchartbubble(hiddenBullCond, divSrc, "H", color.DARK_green, no);
addchartbubble(hiddenBearCond, divSrc, "H", color.DARK_red, yes);


#-- ENd Code
 
Last edited:
Thanks for the indicator! Can you make the candlesticks change colors as the histogram does? Is It possible when the histogram changes to white when its below zero the candlestick turn green and if it changes to white above zero the candlestick changes to red?
 
Thanks for the indicator! Can you make the candlesticks change colors as the histogram does? Is It possible when the histogram changes to white when its below zero the candlestick turn green and if it changes to white above zero the candlestick changes to red?
add this at the end of the code:

CSS:
AssignPriceColor(if bardj and momSrc<0 then Color.CYAN else
                 if bardj and momSrc>0 then Color.MagENTA else Color.CURRENT);
 
Hi, Thank you for posting this. Is it possible to get any or all labels this indicator throws in the upper chart above the candle for bearish or below the candle for bullish moves? An option for sound alerts and also to move the label based on user choice for clearly visualizing the trend would be awesome. Currently the labels are displayed in the lower and has been easy to miss.
 
Hi, Thank you for posting this. Is it possible to get any or all labels this indicator throws in the upper chart above the candle for bearish or below the candle for bullish moves? An option for sound alerts and also to move the label based on user choice for clearly visualizing the trend would be awesome. Currently the labels are displayed in the lower and has been easy to miss.
updated the code in the original post. select the signal style between label or vertical lines. hope this helps.
 
updated the code in the original post. select the signal style between label or vertical lines. hope this helps.
@samer800, Thankyou for your quick response and highly appreciate all your work and inputs. I was hoping to achieve the following,

Labels to display in upper chart. I do not need the momentum candles in upper chart.
Sound alert option.
Ability to adjust label distance from candle.

I tried deactivating the ' declare lower' , did not work. I am not a coder and new to thinkscript. You estimate the complexity, Thanks in advance anyways.
 

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