Peaks Valleys Bar Questions

TNTrader5159

Active member
How would I call the BarNumber of a condition in its most recent occurrence prior to either the current bar or counting from x number of bars back? All I saw in the tutorial is that BarNumber() calls up the current bar. I do not understand what that means.

Let's say I want to call up the most recent occurrence of the Low being less than a defined reference in number of bars back, eg Low < Lowest(Low, 34)[1]. Thanks!
 
How would you determine-express-code the number of bars back any price level was within a bar's range or price match? The 2nd most recent such match? 3rd most recent etc?

this will calculate a number, that is an offset , to the desired bar.

on every bar, look back at previous bars,
and find the xth bar that is within some price range,
based on the current bar.

prev_cnt , is equal to the count, the offset

pick which multiple to look for.
default is 3, find the offset, to the 3rd bar, that is within a range.

can pick the range type,
. within_high_low
. percent_of_close, above and below
. within_dollars_of_close, above and below

qty_bubbles , can turn on bubbles that show the count for each bar.

test_rng_lines , testing,
last_bar_offset , can choose an offset number, to define a bar before the last bar.
can show 2 horizontal lines, drawn from a chosen bar, to visually verify the bars are in the range.


Ruby:
# recent_price_match_00

# https://usethinkscript.com/threads/determining-the-most-recent-price-match.12784/#post-108919
# find the number of bars back,
#  any price level was within a bar's range or price match? The 2nd most recent such match? 3rd most recent etc?

#-------------------------------
# ref this study
#  https://usethinkscript.com/threads/find-engulfing-bars-while-allowing-x-number-of-breakouts-in-the-series-for-thinkorswim.12792/
# engulfing , with x breakouts
#-------------------------------


def bn = BarNumber();
def na = Double.NaN;

#def lastbn = highestall(if(!isnan(close), bn, 0));
input match_quantity = 3;
input match_type = { default within_high_low , percent_of_close, within_dollars_of_close };

input percent_of_close = 0.1;
def cls_per = close * (percent_of_close/100);

input within_dollars_of_close = 0.02;
input lines_from_lastbar = yes;

# ---------------------

def rng_hi;
def rng_lo;
def mtype;
switch (match_type) {
case within_high_low:
  rng_hi = high;
  rng_lo = low;
  mtype = 1;
case percent_of_close:
  rng_hi = close + (cls_per);
  rng_lo = close - (cls_per);
  mtype = 2;
case within_dollars_of_close:
  rng_hi = close + (within_dollars_of_close);
  rng_lo = close - (within_dollars_of_close);
  mtype = 3;
}

def rng = rng_hi - rng_lo;

# ---------------------------

addlabel(1, "match_quantity:  " + match_quantity , color.yellow);
addlabel(1, " ", color.black);
addlabel(1, "match type:  " + match_type , color.yellow);
addlabel(1, " ", color.black);
addlabel(mtype == 2, "cls_per:  " + cls_per , color.yellow);
addlabel(1, " ", color.black);
addlabel(mtype == 3, "within_dollars_of_close " + within_dollars_of_close , color.yellow);


def maxnum = 200;
#addlabel(1, "max bars back " + maxnum, color.yellow);
def n = match_quantity;

def prev_cnt2 = fold j = 1 to maxnum
  with p
  while p <= n
    do p + ( if p == n then j - (n+0) else
    if (getvalue(rng_hi, j) >= low) and (getvalue(rng_lo, j) <= high) then 1 else 0 );

# this is the offset, back to the bar, that is the 'match_quantity'th price match
def prev_cnt = prev_cnt2-1;


#------------------------------------
#------------------------------------
# test stuff

# bubble with quantity of prev bars
input qty_bubbles = yes;
addchartbubble(qty_bubbles, low*0.999,
#bn + "\n" +
prev_cnt + "\n"
, Color.YELLOW, no);

#------------------------------------
# ref...
# draw a horz line at some close level, to visually look for prev bar crossings
# https://usethinkscript.com/threads/current-price-line-indicator-for-thinkorswim.8793/
input test_rng_lines = yes;
input last_bar_offset = 1;
def barsBack = 200;
def x = !IsNaN(close[-last_bar_offset]) and IsNaN(close[-(1+last_bar_offset)]);
def noline = IsNaN(close[-(0+last_bar_offset)]);

# hi
def c = if x
        then rng_hi
        else c[1];
def d = if test_rng_lines and isNaN(close[-barsBack])
            then c[-barsBack]
            else Double.NaN;
plot line = if noline then na else d;
line.SetLineWeight(1);
line.SetDefaultColor(Color.LIME);
line.SetStyle(Curve.MEDIUM_DASH);


# lo
def c2 = if x
        then rng_lo
        else c2[1];
def d2 = if test_rng_lines and isNaN(close[-barsBack])
            then c2[-barsBack]
            else Double.NaN;
plot line2 = if noline then na else d2;
line2.SetLineWeight(1);
line2.SetDefaultColor(Color.LIME);
line2.SetStyle(Curve.MEDIUM_DASH);

plot y = if test_rng_lines and x then high*1.0004 else na;
y.SetPaintingStrategy(PaintingStrategy.POINTS);
y.SetDefaultColor(Color.cyan);
y.setlineweight(3);
y.hidebubble();

plot off = if test_rng_lines and x then last_bar_offset else na;
off.SetPaintingStrategy(PaintingStrategy.values_above);
off.SetDefaultColor(Color.white);
off.hidebubble();

addverticalline(test_rng_lines and x, "-", color.magenta);
#

input last_bar_offset = , was set to some number, to choose a bar, before the last bar. (where the horizontal lines end)

this is looking for the 3rd bar, within a price range , from the current bar
the circled bubble has a number 9. 9 bars back is the 3rd bar that is within the price range

fqtsvi9.jpg
 
Last edited:

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

declare lower;

def EngulfedHigh = Highest(high, fold ihigh = 3 to 1380
with counthigh = 3 while GetValue(high, -counthigh) < high do counthigh + 1);
# Number or prior highs less than the current high up to a maximum of 1380 (a day's session length in minutes)

def EngulfedLow = Lowest(low, fold ilow = 3 to 1380 with countlow = 3 while GetValue(low, -countlow) > low do countlow + 1);
# Number of prior lows greater than the current low up to a maximum of 1380 (a day's session length in minutes)

def EngulfedRange = if EngulfedHigh - EngulfedLow > ExpAverage(high - low, 987) then 1 else 0;
# Confirms the range of bars engulfed by the current bar is big enough to be worth trading as compared with the expressed average range of a single bar

plot Engulfed3 = if EngulfedHigh >= 3 && EngulfedLow >= 3 then 1 else 0;
# Confirms the current bar engulfs at least 3 bars and returns 1 if so
 
declare lower;

def EngulfedHigh = Highest(high, fold ihigh = 3 to 1380
with counthigh = 3 while GetValue(high, -counthigh) < high do counthigh + 1);
# Number or prior highs less than the current high up to a maximum of 1380 (a day's session length in minutes)

def EngulfedLow = Lowest(low, fold ilow = 3 to 1380 with countlow = 3 while GetValue(low, -countlow) > low do countlow + 1);
# Number of prior lows greater than the current low up to a maximum of 1380 (a day's session length in minutes)

def EngulfedRange = if EngulfedHigh - EngulfedLow > ExpAverage(high - low, 987) then 1 else 0;
# Confirms the range of bars engulfed by the current bar is big enough to be worth trading as compared with the expressed average range of a single bar

plot Engulfed3 = if EngulfedHigh >= 3 && EngulfedLow >= 3 then 1 else 0;
# Confirms the current bar engulfs at least 3 bars and returns 1 if so

you are comparing highs separately from the lows. need to combine them into 1 formula. just because a high is engulfed, doesn't mean the low on that bar will be engulfed.

an example of engulfing study, that finds how many consecutive, engulfed bars are before the current bar.
look at the while formula.
https://usethinkscript.com/threads/...st-65-most-recent-days.7483/page-2#post-72474
 
yes, it is a different concept to understand (code runs on each bar). but when you do, it will help you to think about offsets, and which bar your formulas should reference from.

here is another fold example. this one uses while.
...while the condition is true, it processes the do formula.
...when while become false, the loop stops.
this study looks for an engulfing bar, a big bar that had several small bars before it.
when it finds one, it draws a bubble under the bar, with the count of previous small bars.

Ruby:
# Engulfing bar
# look back in time, to find bars smaller than the current bar

input minimum_engulfed_bars = 2;
def show_bubbles = yes;
def na = double.nan;
def barup = (close > open);

input lookback = 40;
# if while is used, fold loops as long as while statement is true
# when while becomes false, the loop stops, even if fold hasn't reached the highest count value
def bigbarcnt = fold k = 1 to lookback
with p
while (high > getvalue(high, k) and low < getvalue(low, k))
do p + 1;

addchartbubble((show_bubbles and bigbarcnt > minimum_engulfed_bars),(low * 0.999), bigbarcnt, if bigbarcnt == 0 then color.dark_gray else if barup then color.green else color.red, no);
#
hal_fold hal_engulf
In the getvalue function, the k starts its count one bar behind the current bar, right? And if it's a negative value, it starts its count one bar ahead of the current bar? So no brackets, eg [1], needed there?
 
you are comparing highs separately from the lows. need to combine them into 1 formula. just because a high is engulfed, doesn't mean the low on that bar will be engulfed.

an example of engulfing study, that finds how many consecutive, engulfed bars are before the current bar.
look at the while formula.
https://usethinkscript.com/threads/...st-65-most-recent-days.7483/page-2#post-72474
I may have followed up in the wrong thread a minute ago. Sorry.
<p>
So in the getvalue function using the counted value k, its count begins one bar behind the current bar to count backward? And if it's a negative value, it begins its count one bar ahead of the current bar to count forward? I understand the count stops in the fold loop at the point either or both conditions are no longer true.
 
I may have followed up in the wrong thread a minute ago. Sorry.
<p>
So in the getvalue function using the counted value k, its count begins one bar behind the current bar to count backward? And if it's a negative value, it begins its count one bar ahead of the current bar to count forward? I understand the count stops in the fold loop at the point either or both conditions are no longer true.
And did you put (low * 0.999) in the addchartbubble function to avoid some kind of rounding error? Why not just (low)?
 
I may have followed up in the wrong thread a minute ago. Sorry.
<p>
So in the getvalue function using the counted value k, its count begins one bar behind the current bar to count backward? And if it's a negative value, it begins its count one bar ahead of the current bar to count forward? I understand the count stops in the fold loop at the point either or both conditions are no longer true.

your fold loop starts with 1 , for the offset , k , so the first time through, getvalue will look back 1 bar.

yes, negative offsets, look at future bars.


def bigbarcnt = fold k = 1 to lookback
with p
while (high > getvalue(high, k) and low < getvalue(low, k))
do p + 1;


that's ok.. similar topics, offsets
https://usethinkscript.com/threads/...he-last-65-most-recent-days.7483/page-2#posts
 
Last edited:
And did you put (low * 0.999) in the addchartbubble function to avoid some kind of rounding error? Why not just (low)?

it's just a visual thing.
i don't like arrows and shapes touching candles. i want them separate. moving shapes away helps them to stick out and are easier for me to see.
 
In the getvalue function, the k starts its count one bar behind the current bar, right? And if it's a negative value, it starts its count one bar ahead of the current bar? So no brackets, eg [1], needed there?

yes... but i would say before and after.
previous bars are before the current bar and read with positive offsets.

future bars are after the current bar and read with negative offsets.

when using getvalue() , no brackets needed.
https://tlc.thinkorswim.com/center/reference/thinkScript/Functions/Others/GetValue
 
Is it not possible to use a variable for the number of periods in determining the highest (or lowest) price of that number of periods such as the following?...

def high_value = highest(high, <variable>);

def low_value = lowest(low, <variable>);
 
Let's say you find all prior low pivots with a lesser side minimum of 3 bars with higher lows on either side. Once that low pivot point is broken by bars that completely clear it, how would you count the number of bars that progressively break cleanly below it until it reaches the number of its lesser side bars? And how would you take that dynamic number of bars cleanly below the pivot point and multiply each bar by 0.5 until such time as the number of lesser side bars in the pivot is matched? (Bars straddling the low pivot point are skipped.)

The strength of the pivot would start at its lesser side number of bars and be diminished as up to that many bars break cleanly below it. It is an example of support becoming resistance but then only at half the strength it was as support.

def lowpivotpoint = <definition>;
def LowPivotBarsLesserSide = <number of bars>;

I think I might see how to do this, but I'm very tired tonight and must call it quits till tomorrow. So is anyone understanding my explanation above wanting to take a shot at it?
 
Gonna need some type of illustration to follow your logic. Trying to picture it while reading your post and...just can't..
And I did err in my previous post stating how the strength of the pivot point is diminished as it is broken on the low side (it works the same way for a high pivot). The correct way is shown and described in the illustration. Sorry about that.
 
@TNTrader5159 Biggest issue here is that this screams {array} which thinkscript doesn't really do.
But, you could do an input of a low pivot bar time and value to manually test that specific pivot point as price approaches it.

The logic would be to first 'flag' the low and high pivot bars.

Then define two counters.
- One counter to start at the input time pivot bar and count to the next 'flagged' high pivot bar. Once a high pivot bar is reached then hold that count as long as a new high pivot bar is not 'flagged', if so, then count to the new high pivot bar.

- Second counter to count back to the prior high pivot bar.

-If price moves back below the low pivot then use a third counter to stat at the lower of the two original counters and decrease the counter by .5 for every bar below the initial input low pivot until reaching half of the original value.

Maybe, you could use a FOLD statement to look ahead from every bar to the current close and choose which low pivot point to test based on proximity to current close instead of inputting a specific time and value.

What would the count do if price moved below, then straddled the pivot again?
Or move back above the low pivot before reaching half the lesser side?

I'll have to think about this some more and test some things out.
 
@TNTrader5159 Biggest issue here is that this screams {array} which thinkscript doesn't really do.
But, you could do an input of a low pivot bar time and value to manually test that specific pivot point as price approaches it.

The logic would be to first 'flag' the low and high pivot bars.

Then define two counters.
- One counter to start at the input time pivot bar and count to the next 'flagged' high pivot bar. Once a high pivot bar is reached then hold that count as long as a new high pivot bar is not 'flagged', if so, then count to the new high pivot bar.

- Second counter to count back to the prior high pivot bar.

-If price moves back below the low pivot then use a third counter to stat at the lower of the two original counters and decrease the counter by .5 for every bar below the initial input low pivot until reaching half of the original value.

Maybe, you could use a FOLD statement to look ahead from every bar to the current close and choose which low pivot point to test based on proximity to current close instead of inputting a specific time and value.

What would the count do if price moved below, then straddled the pivot again?
Or move back above the low pivot before reaching half the lesser side?

I'll have to think about this some more and test some things out.
Thanks for all the thought you put into this. The system works beautifully just gotta figure how to get the point across to TOS! It seems like you said a FOLD from each identified bar that would check for all pivots back a bar at a time to the beginning of loaded data and forward a bar at a time to the present would be the way to go. It would update (if necessary) the impedance value of each pivot dynamically going forward until such time they may go "off the board" as enough trading volume (measured in bars) takes place on each side of it to invalidate it as both support and resistance. Untouched support that is fully penetrated on the downside would undermine its support value by half its overall strength. Then, as traders often say, it becomes a point of resistance to any future return upward price movement. And research says it really does. But in such cases, it should only be, as resistance, worth half its former support value, since half the volume of any bar is purchase and half is sale.

Let me know if you have any more thoughts, and thanks again.
 
Hello trader/coders!

Pivots are measured by the lesser side in number of bars to the highest price both before and after a pivot point looking backward and foreward to the first breach of the pivot point (lower for a low pivot or higher for a high pivot). I humped it to write this, which checks out as logical yet displays nothing. I am spent for the day, so a fresh mind and set of eyes to correct me here very much appreciated! I hope the intent as stated in the accompanying notes is clear.

([ThrustFactor] in the code is set to 0 as a place holder until this segment is corrected so the ThrustFactor segment can be added.)

Begin...

declare lower;

# shorten labels and hold a spot for the ThrustFactor to be added later
def BN = barnumber();
def NN = double.nan;
def ThrustFactor = 0;

# Is it a low pivot point with at least one completely higher bar on each side?
def LowPivotFinder = if low < low[1] && low < low[-1] then 1 else NN;

# Return the low price of the low pivot point if there is one
def LowPivotPrice = if LowPivotFinder == 1 then low else NN;

# Is it a high pivot point with at least one completely lower bar on_volume each side?
def HighPivotFinder = if high > high[1] && high > high[-1] then -1 else NN;

# Return the high price of the high pivot point if there is one
def HighPivotPrice = if HighPivotFinder == -1 then high else NN;

# Find the bar number of each low pivot price
def LowPivotLocation = if LowPivotFinder == 1 then getvalue(BN, LowPIvotLocation) else NN;

# Find the bar number of each high pivot price
def HighPivotLocation = if HighPivotFinder == -1 then getvalue(BN, HighPivotLocation) else NN;

# Count the number of bars left of the low pivot point with lows higher than the low pivot point. The bar count is strictly and necessarily limited to the number of remaining bars loaded on the chart from the starting low pivot point backward to then first loaded bar to prevent logic errors.
def LowPivotBarsLeft = if LowPivotFinder == 1 then fold lowleftcount = 1 to BN - LowPivotLocation with lowstartpointleft while getvalue(low, lowleftcount) > low do lowstartpointleft + 1 else 1;

# Count the number of bars right of the low pivot point with lows higher than the low pivot point. The bar count is strictly and necessarily limited to the number of remaining bars loaded on the chart from the starting low pivot point foreward to the current bar to prevent logic errors.
def LowPivotBarsRight = if LowPivotFinder == 1 then fold lowrightcount = LowPivotLocation to BN with lowstartpointright while getvalue(low, -lowrightcount) > low do lowstartpointright + 1 else 1;

# Find the highest price of LowPivotBarsLeft
def LowPivotBarsLeftHigh = highestall(LowPivotBarsLeft);

# Find the location of that highest price
def LowPivotBarsLeftHighLocation = BN - fold lowlefthighbar = 1 to BN - LowPivotLocation with lowstartpointlefttohighest while high < LowPivotBarsLeftHigh do lowstartpointlefttohighest + 1;

# Find the location of that lowest price
def LowPivotBarsRightHighLocation = BN - fold lowrighthighbar = 1 to BN - LowPivotLocation with lowstartpointrighttohighest while high < LowPivotBarsLeftHigh do lowstartpointrighttohighest + 1;

# Determine the number of bars left of the low pivot point to the highest price of all the bars backward that are completely higher than the low pivot point
def LowPivotLeftStrength = LowPivotLocation - LowPivotBarsLeftHighLocation;

# Determine the number of bars right of the low pivot point to the highest price of all the bars forward that are completely higher than the low pivot point
plot LowPivotRightStrength = LowPivotBarsRightHighLocation - LowPivotLocation;

# Determine the strength of the low pivot pivot based upon its lesser side in number of bars.
def LowPivotStrength = min(LowPivotLeftStrength, LowPivotRightStrength - ThrustFactor);
 

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
322 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