Running Count of Non-Overlapping Bar Bodies For ThinkOrSwim

armybender

Active member
I have absolutely no idea what to call this indicator, but here's the idea. Rather than counting things like up bars or down bars, or trying to measure line breaks, etc., I thought about trying to visualize the structure of the market in a different way.

This indicator counts anytime 2 bars do NOT have overlapping bodies, either up or down and keeps a running total. I don't quite know how to use it yet, but have noticed it does a really good job of highlighting divergence between market moves (i.e. price move) and the strength of the moves (i.e. gaps on the way up/down).

Again, I'm not quite sure how this will be or could be used, but it is super interesting to note that the structure can be visualized this way.

1693591272543.png



Ruby:
#DECLARATIONS
declare lower;


#USER INPUTS
input plotThickness = 2;
input colorBars = {default Off, By_Inst_Trend, By_Gap_Count};
input allowDojis = no;
input barsBack = 1000;
input skipBarsLevel = 2;
input showChannel = no;
input showCloud = yes;
input showLastPeaks = no;
input channelLength = 50;

input alpha = 0.07;    # 0.07 is default
input smoothLength = 3;
input colorPctMin = 3;


#GLOBAL COLOR DEFINITIONS
DefineGlobalColor("Faded Green", CreateColor(75, 155, 75));           #original 0, 155, 0 / 4B9B4B
DefineGlobalColor("Faded Red", CreateColor(224, 117, 117));           #original 255, 105, 105 / E07575
DefineGlobalColor("Green", CreateColor(75, 155, 75));           #original 0, 155, 0 / 4B9B4B
DefineGlobalColor("Red", CreateColor(224, 117, 117));           #original 255, 105, 105 / E07575
DefineGlobalColor("Gray", CreateColor(181, 181, 181));          #original 181, 181, 181


#DEFINITIONS AND CALCULATIONS
## Body Gaps Calculations
def isUp = close > open;
def isDown = close < open;
def isDoji = close == open;
def isLastBar = !IsNaN(close) and IsNaN(close[-1]);

def bodyHigh = Max(open, close);
def bodyLow = Min(open, close);

def isUpGap = bodyLow >= bodyHigh[1] and (isUp or (allowDojis and isDoji));
def isDownGap = bodyHigh <= bodyLow[1] and (isDown or (allowDojis and isDoji));
def gapCount = if isUpGap then gapCount[1] + 1 else if isDownGap then gapCount[1] - 1 else gapCount[1];

def lastBN = if isLastBar[-1] then BarNumber() + 1 else lastBN[1];
def lastBNValue = if isNaN(close[-barsBack]) then lastBN[-barsBack - 1] else Double.NaN;

def barColor = if gapCount > gapCount[1] then 1 else if gapCount < gapCount[1] then -1 else barColor[1];

def colorMethod;
switch(colorBars){
    case Off:
        colorMethod = 0;
    case By_Inst_Trend:
        colorMethod = 1;
    case By_Gap_Count:
        colorMethod = 2;
};

def lastLevel = if isLastBar then gapCount else lastLevel[1];
def lastLevelValue = if isNaN(gapCount[-barsBack]) then lastLevel[-barsBack] else Double.NaN;

def levelLine = 
    if IsNaN(close) or BarNumber() % skipBarsLevel <> 0
    then Double.NaN
    else lastLevelValue
;

def isHighPeak = gapCount > lastLevelValue and gapCount[1] < gapCount;
def trailHighPeaks = if isHighPeak then gapCount else trailHighPeaks[1];
def lastHighPeakOffset = if isLastBar[-1] then GetMaxValueOffset(isHighPeak, barsBack) + 1 else lastHighPeakOffset[1];
def highPeakBarOffset = if isNaN(close[-barsBack]) then lastHighPeakOffset[-barsBack - 1] else Double.NaN;
def isLastHighPeak = BarNumber() == lastBNValue - highPeakBarOffset;
def countHigh = BarNumber() >= lastBNValue - highPeakBarOffset;
def lastHighPeakValue = if !countHigh then Double.NaN else if isLastHighPeak then gapCount else lastHighPeakValue[1];

def isLowPeak = gapCount < lastLevelValue and gapCount[1] > gapCount;
def trailLowPeaks = if isLowPeak then gapCount else trailLowPeaks[1];
def lastLowPeakOffset = if isLastBar[-1] then GetMaxValueOffset(isLowPeak, barsBack) + 1 else lastLowPeakOffset[1];
def lowPeakBarOffset = if isNaN(close[-barsBack]) then lastLowPeakOffset[-barsBack - 1] else Double.NaN;
def isLastLowPeak = BarNumber() == lastBNValue - lowPeakBarOffset;
def countLow = BarNumber() >= lastBNValue - lowPeakBarOffset;
def lastLowPeakValue = if !countLow then Double.NaN else if isLastLowPeak then gapCount else lastLowPeakValue[1];


## Ehlers Instantaneous Trend Calculations
def alpha2 = Power(alpha, 2);
def it =
    Compoundvalue( 6,
        ( alpha - ( ( alpha2 ) / 4.0 ) )
        * gapCount + 0.5 * alpha2 * gapCount[1] -
        ( alpha - 0.75 * alpha2 ) * gapCount[2] +
        2 * ( 1 - alpha ) *
        ( if IsNaN( it[1] ) then ( ( gapCount + 2 * gapCount[1] + gapCount[2] ) / 4.0 ) else it[1] ) -
        ( 1 - alpha ) * ( 1 - alpha ) *
        ( if IsNaN( it[2] ) then ( ( gapCount + 2 * gapCount[1] + gapCount[2] ) / 4.0 ) else it[2] )
        , (gapCount + 2 * gapCount[1] + gapCount[2] ) / 4
    );
def lag = 2.0 * it - if IsNaN(it[2]) then 0 else it[2];
def itSmooth = ExpAverage(it, smoothLength);
def lagSmooth = ExpAverage(lag, smoothLength);


#PLOTS
plot GapCountPlot = gapCount;

plot LastLevelLine = levelLine;

plot InstTrend = itSmooth;

plot LastH = Highest(gapCount, channelLength) + 1;
plot LastL = Lowest(gapCount, channelLength) - 1;

plot LastHighPeak = if IsNaN(close) then Double.NaN else lastHighPeakValue;
plot LastLowPeak = if IsNaN(close) then Double.NaN else lastLowPeakValue;


#BAR COLORING
AssignPriceColor(
    if colorMethod == 0 then
        Color.CURRENT
    else if colorMethod == 1 then
        if gapCount >= itSmooth then GlobalColor("Green")
        else GlobalColor("Red")
    else if colorMethod == 2 then
        if barColor == 1 then GlobalColor("Green")
        else if barColor == -1 then GlobalColor("Red")
        else GlobalColor("Gray")
    else Color.CURRENT
);


#CLOUDS
AddCloud(if showCloud then GapCountPlot else Double.NaN, InstTrend, GlobalColor("Faded Green"), GlobalColor("Faded Red"));


#FORMATTING
GapCountPlot.AssignValueColor(if isLastBar then Color.YELLOW else if barColor == 1 then GlobalColor("Green") else if barColor == -1 then GlobalColor("Red") else GlobalColor("Gray"));
GapCountPlot.SetLineWeight(plotThickness);
GapCountPlot.HideBubble();
GapCountPlot.HideTitle();

LastLevelLine.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
LastLevelLine.AssignValueColor(GlobalColor("Gray"));
LastLevelLine.HideTitle();
LastLevelLine.HideBubble();

InstTrend.AssignValueColor(
    if it > it[1] then GlobalColor("Green")
    else if it < it[1] then GlobalColor("Red")
    else GlobalColor("Gray")
);
InstTrend.HideTitle();
InstTrend.HideBubble();
InstTrend.SetLineWeight(1);

InstTrend.AssignValueColor(
    if it > it[1] then GlobalColor("Green")
    else if it < it[1] then GlobalColor("Red")
    else GlobalColor("Gray")
);
InstTrend.HideTitle();
InstTrend.HideBubble();
InstTrend.SetLineWeight(1);

LastH.AssignValueColor(GlobalColor("Red"));
LastH.SetHiding(!showChannel);
LastH.HideTitle();
LastH.HideBubble();

LastL.AssignValueColor(GlobalColor("Green"));
LastL.SetHiding(!showChannel);
LastL.HideTitle();
LastL.HideBubble();

LastHighPeak.AssignValueColor(GlobalColor("Red"));
LastHighPeak.SetPaintingStrategy(PaintingStrategy.DASHES);
LastHighPeak.SetHiding(!showLastPeaks);
LastHighPeak.HideTitle();
LastHighPeak.HideBubble();

LastLowPeak.AssignValueColor(GlobalColor("Green"));
LastLowPeak.SetPaintingStrategy(PaintingStrategy.DASHES);
LastLowPeak.SetHiding(!showLastPeaks);
LastLowPeak.HideTitle();
LastLowPeak.HideBubble();
 
Last edited:
I've made a few tweaks and updated the original post I made here. There is now an option to show a channel of the last X bars highs and lows, as well as a last high and low line for the indicator.

1694092913435.png
 
Ok, a couple more updates. I keep messing with this study because as I explore how to use it I'm finding it very helpful to spot changes in market structure. It really highlights when trends are ending quite well, and it does some interesting things in ranges I'm still working on.

I don't know if it works well on time-based or range charts (guessing not at all on range), but it works very well for /ES on a tick-based chart.

I've added 2 different coloring options. One is colored based on the current direction of the GapCount plot, and the other is colored based on the difference between the GapCount and the Ehler's Instantaneous Trend line of the GapCount.

I've also added a cloud that you can turn on or off.

1694138230763.png
 

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