• Get $40 off VIP by signing up for a free account! Sign Up

Broadening Formation Pattern for ThinkorSwim

MrDrB

New member
Hello All, I've spent several nights trying to re-create this without any success: http://www.patternsmart.com/cart/index.php?route=product/product&product_id=430&search=broadening

Perhaps I'm missing something obvious. I've tried applying techniques from mobius' scalper alerts and tried re-tooling the built-in zig-zag code. Any offers to help would be appreciated. I would've just paid for it if the site looked legit and at least had an SSL cert. If anyone knows if this is available for purchase from a reputable site, I would happy to know that as well. Thanks!

BTW, I've also went over this forum post multiple times (https://usethinkscript.com/threads/second-highest-lowest-high-low-in-same-range.2064/) as it is trying to do something fundamentally similar: find the two highest highs and two lowest lows in a range of bars.
 
Last edited by a moderator:
20:17 Vimes: Was browsing some old public thinkscript forums and came across a very old snippet from Robert Payne that looked interesting, I modified it to plot peak to peak and valley to valley moves together. Likely not practical yet for trading but perhaps an interesting snippet (at least for me:))

Code:
#Snippet only
#Peak2Peak_Valley2Valley
#idea taken from a public robert payne snippet on valley lines
#extended to plot valley to valley and peak to peak lines together
#and made lookback adjustable
#perhaps useful for broadening formation or other potential extensions of price action
#vimes
input len = 3;
input showBubble = no;

#valley section
def Valley = low < Lowest(low[1], len) and low < Lowest(low[-len], len);
plot ArrowUP = Valley;
ArrowUP.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
ArrowUP.SetDefaultColor(Color.WHITE);
ArrowUP.SetLineWeight(3);
plot line_v = if ArrowUP then low else Double.NaN;
line_v.EnableApproximation();
line_v.SetDefaultColor(Color.LIME);
line_v.SetLineWeight(2);
def run_v = if Valley then 1 else run_v[1] + 1;
def rise_v = if Valley then low - GetValue(low, run_v[1]) else Double.NaN;
def slope_v = rise_v / run_v[1];
AddChartBubble(showBubble and Valley, low, slope_v, if slope_v > 0 then Color.LIGHT_GREEN else Color.PINK);

def slopeV = if Valley then slope_v else slopeV[1];
def lineV = if Valley then low else lineV[1] + slopeV;
plot LineExtension_V = lineV;
LineExtension_V.SetDefaultColor(Color.CYAN);
LineExtension_V.SetPaintingStrategy(PaintingStrategy.POINTS);

#peak section
def Peak = high > highest(high[1], len) and high > highest(high[-len], len);
plot ArrowDN = Peak;
ArrowDN.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
ArrowDN.SetDefaultColor(Color.WHITE);
ArrowDN.SetLineWeight(3);

plot line_p = if ArrowDN then high else Double.NaN;
line_p.EnableApproximation();
line_p.SetDefaultColor(Color.LIME);
line_p.SetLineWeight(2);
def run_p = if Peak then 1 else run_p[1] + 1;
def rise_p = if Peak then high - GetValue(high, run_p[1]) else Double.NaN;
def slope_p = rise_p / run_p[1];
AddChartBubble(showBubble and Peak, high, slope_p, if slope_p > 0 then Color.LIGHT_GREEN else Color.PINK);
def slopeX_p = if Peak then slope_p else slopeX_p[1];
def lineX_p = if Peak then high else lineX_p[1] + slopeX_p;
plot LineExtension_p = lineX_p;
LineExtension_p.SetDefaultColor(Color.CYAN);
LineExtension_p.SetPaintingStrategy(PaintingStrategy.POINTS);

If I share a chart, will you guys look at it? I use triangles/broadening formations to find support and resistance and inside/outside bars to look for signals. Todays 3 min chart on the /ES will show you how using just that would have had you nailing all the big moves today.
 

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

@MrDrB I am new to thinkscript ( few weeks of experience but programmer by trade). I am also new to this forum. I made an initial attempt at this. Are you still interested in working on this? I can send the script over. I would appreciate someone else looking over and verifying my logic. I am not done with the alerts part. I am not familiar with the best practices on think scripts.

K43DKLd.png


@MrDrB
  • Nice, looking forward to working together
  • I think that scenario you are referring to is done. I took the approach of listing valleys/peaks and then using the last 2 valleys/peaks if present
  • Alerts are partially coded and I may get to it this weekend, they are partially coded and can't be relied on
  • toggle the debug flag input value for params etc. will give you my step by step decision-making process

Code:
#Broadening Pattern
#Multiple Sources
# Fun with thinkscript: https://researchtrade.com/forum/read.php?7,2258,page=31
# UseThinkScript: https://usethinkscript.com/threads/create-column-based-on-peak-and-valley-indicator.901/
# https://funwiththinkscript.com/count-the-number-of-bars-between-successive-highs/
# Idea source: https://www.patternsmart.com/cart/index.php?route=product/product&product_id=430&search=broadening

# 20201019 Raj B, initial code upto calculating peaks/valleys, getting barNumbers , checking if broadening pattern conditions exist
# 20201020 Raj B. Added ability for separate left/right threshold to allow independent values
# 20201020 Raj B. Added initial column/watchlist alerts, needs testing
# TODO complete alert part
# 20210803 Raj B. Cay7man identified a bug, removed logic that depends on isAlertSetup yes/no https://usethinkscript.com/threads/broadening-formation-pattern-for-thinkorswim.2732/post-71684  re

# Inputs

input LeftBarsThreshold = 5;
input RightBarsThreshold = 5;
#input isAlertSetup = no;
input debug = no;

# Setup
def bn = BarNumber();

# Calculate values for peaks
def peak = high > Highest(high[1], LeftBarsThreshold) and high >= Highest(high[-RightBarsThreshold], RightBarsThreshold);
plot peakBoolean = peak;

def peakValue = if peak then high else peakValue[1];
def peakBar = if peak then BarNumber() else Double.NaN;

# Calculate barNumbers for previous 2 peaks

def lastPeakBarNumber = HighestAll(if peak then bn else 0);
def prevPeakBarNumber = HighestAll(if peak and bn < lastPeakBarNumber then bn else 0);

# Get values for previous 2 peaks
def lastPeakValue = GetValue(high, bn - HighestAll(peakBar));
def prevPeakValue = GetValue(peakValue[1], bn - HighestAll(peakBar));

#  Calculate values for valleys/low points
def valley = low < Lowest(low[1], LeftBarsThreshold) and low <= Lowest(low[-RightBarsThreshold], RightBarsThreshold);
plot valleyBoolean = valley;

def valleyValue = if valley then low else valleyValue[1];
def valleyBar = if valley then BarNumber() else Double.NaN;

# Get barNumbers for previous 2 valleys
def lastValleyBarNumber = HighestAll(if valley then bn else 0);
def prevValleyBarNumber = HighestAll(if valley and bn < lastValleyBarNumber then bn else 0);

# Get values for previous 2 valleys
def lastValleyValue = GetValue(low, bn - HighestAll(valleyBar));
def prevValleyValue = GetValue(valleyValue[1], bn - HighestAll(valleyBar));

# Do we have valid values for peaks/valleys and
# are they  increasing peaks and decreasing valleys
def areLast2PeaksIncreasing =  !IsNaN(lastPeakValue) and !IsNaN(prevPeakValue) and lastPeakValue > prevPeakValue;
def areLast2ValleysDecreasing = !IsNaN(lastValleyValue) and !IsNaN(prevValleyValue) and lastValleyValue < prevValleyValue;

# Do we have interlaced peaks/valleys
def peaksValleysInterlaced = (prevValleyBarNumber > prevPeakBarNumber and prevValleyBarNumber < lastPeakBarNumber)
                                or
                              (prevPeakBarNumber > prevValleyBarNumber and prevPeakBarNumber < lastValleyBarNumber);

def  inBroadeningPattern = areLast2PeaksIncreasing and areLast2ValleysDecreasing and peaksValleysInterlaced;

# if we have a broadening pattern, get last 2 values and draw a line with extension


# get scaling factor for high side, low side
# initial line is drawn using last 2 peaks/valleys
# However, after those 2 points, we need to use scaling factors to extend the line y=mx+c
# Thank you to my middle school math teachers in India :)
# Expect valleyScalePerBar to be negative number

def peakScalePerBar = (lastPeakValue - prevPeakValue) / (lastPeakBarNumber - prevPeakBarNumber );
def valleyScalePerBar = (lastValleyValue - prevValleyValue) / (lastValleyBarNumber - prevValleyBarNumber );

def peakExtendedValue = lastPeakValue + (bn - lastPeakBarNumber) * peakScalePerBar;
def valleyExtendedValue = lastValleyValue + (bn - lastValleyBarNumber) * valleyScalePerBar;

#Draw UpperLine, initial with 2 points, then extend with scaling factor
plot upperLine = if inBroadeningPattern and bn > lastPeakBarNumber
                 then peakExtendedValue
                 else if inBroadeningPattern and peak and bn >= prevPeakBarNumber
                 then high
                 else Double.NaN;
upperLine.EnableApproximation();
upperLine.SetDefaultColor(Color.LIME);
upperLine.SetLineWeight(2);

plot lowerLine = if inBroadeningPattern and bn > lastValleyBarNumber
                 then valleyExtendedValue
                 else if inBroadeningPattern and valley and bn >= prevValleyBarNumber
                 then low
                 else Double.NaN;

lowerLine.EnableApproximation();
lowerLine.SetDefaultColor(Color.PLUM);
lowerLine.SetLineWeight(2);

# alert when crosses over/above line?

#get highestPrice after last peak

#def highValueAfterLastPeak = Highest(high[-(bn-lastPeakBarNumber)], RightBarsThreshold);

# scantype=1; for price cross above upper line
#def scantype_1 = inBroadeningPattern and high >

# scantype=2; for price cross below lower line
# scantype=3; for price is below lower line
def scantype_3 = inBroadeningPattern and high > peakExtendedValue;
# scantype=4; for price is above upper line
def scantype_4 = inBroadeningPattern and low < valleyExtendedValue;
# scantype=5; for price is inside two lines.
def scantype_5 = inBroadeningPattern and high < peakExtendedValue
                                     and low  > valleyExtendedValue;

# getDisplayValue for alerts/scans


AddLabel(scantype_3, "Above BF", Color.CYAN);
AddLabel(scantype_4, "Below BF", Color.CYAN);
AddLabel(scantype_5, "Between BF", Color.CYAN);




AddLabel(debug, "BarNumber:" + bn, Color.WHITE);
AddLabel(debug, "lastpeakbar:" + lastPeakBarNumber, Color.WHITE);
AddLabel(debug, "prevPeakGetValue:" + prevPeakBarNumber, Color.WHITE);
AddLabel(debug, "lastpeakvalue:" + lastPeakValue, Color.WHITE);
AddLabel(debug, "previouspeakvalue:" + prevPeakValue, Color.WHITE);

AddLabel(debug, "lastvalleybar:" + lastValleyBarNumber, Color.YELLOW);
AddLabel(debug, "prevValleyGetValue:" + prevValleyBarNumber, Color.YELLOW);
AddLabel(debug, "lastvalleyvalue:" + lastValleyValue, Color.YELLOW);
AddLabel(debug, "previousvalleyvalue:" + prevValleyValue, Color.YELLOW);

AddLabel(debug, "IncPeaks?:" + areLast2PeaksIncreasing, Color.WHITE);
AddLabel(debug, "DecPeaks?:" + areLast2ValleysDecreasing, Color.WHITE);
AddLabel(debug, "ValuesInterlaced?:" + peaksValleysInterlaced, Color.WHITE);
AddLabel(inBroadeningPattern, "BroadPattern?:" + inBroadeningPattern, if inBroadeningPattern then Color.LIGHT_GREEN else Color.LIGHT_RED);

AddLabel(debug, "peakSideScaleFactor:" + peakScalePerBar, Color.YELLOW);
AddLabel(debug, "valleySideScaleFactor:" + valleyScalePerBar, Color.YELLOW);

AddLabel(debug, "peakExtendedValue:" + peakExtendedValue, Color.YELLOW);
AddLabel(debug, "valleyExtendedValue:" + valleyExtendedValue, Color.YELLOW);
###End Code
 
Last edited:
@RajB looks good so far. i'll take a fuller look tonight. it looks like we've gotten about as far as each other on this except i never intended on coding alerts. we can continue iterating from your code...any specific issues/features that i can help look into?
 
@MrDrB Sounds good.
  • If you can sanity check my logic that would be great.
  • also, any do's/don't on TS coding would be appreciated, I am still relatively new to this space
  • I had performed limited testing and things seem to work. Did you have any edge/test cases that you have used before?
  • wanted to share this with the rest of the community as part of the effort
 
Last edited:
Here it is
[/QUOTE]
  • thank you
  • I looked at the debug information and everything seems to be calculated correctly from what I can tell (not a code calculation issue)
  • I am almost wondering if there is something to do with plotting volume bars and taking up some space that way and TOS reacting differently
  • My next step suggestion: Please run a separate new window/chart with the same time frame and ONLY broadening formation indicator. Can you please see if that issue happens at the same time on this other new chart/window?
  • sorry, I am unable to reproduce the issue locally, and for next month I am in non-US timezone is not making it easy either
  • If it helps, you can change the last 2 AddLabel lines from debug to inBroadeningPattern, and you can see those values on your screen

Code:
Replace From:
AddLabel(debug, "peakExtendedValue:" + peakExtendedValue, Color.YELLOW);
AddLabel(debug, "valleyExtendedValue:" + valleyExtendedValue, Color.YELLOW);

Replace with:

AddLabel(inBroadeningPattern, "peakExtendedValue:" + peakExtendedValue, Color.YELLOW);
AddLabel(inBroadeningPattern, "valleyExtendedValue:" + valleyExtendedValue, Color.YELLOW);
 
Last edited by a moderator:
@RajB, the BF's are not being drawn on most of my charts. The ones that are being draw are daily charts. For example, TDOC on the daily and 4hr is drawn but when I go down to any lower intraday charts, its not drawn. Here is an example of my 15min chart for TDOC today. Are you seeing a BF drawn on your side?
 
@greco26
Yes and that is expected. It ONLY draws the broadening formation when the right conditions exist. Thank you for sending the debug information. If you notice the “BroadPattern?” Value it only draws it when it is 1 and will not draw it when 0. Hope that helps. Also note, this is a repainting indicator and can go away when conditions no longer exist.
 
@greco26
Yes and that is expected. It ONLY draws the broadening formation when the right conditions exist. Thank you for sending the debug information. If you notice the “BroadPattern?” Value it only draws it when it is 1 and will not draw it when 0. Hope that helps. Also note, this is a repainting indicator and can go away when conditions no longer exist.
I wonder if there is a way to adjust the sensitivity of the conditions similar to how one can adjust chart patterns in tos. Unfortunately it doesn’t seem to pick up most BF’s on intraday charts which would be ideal for the Strat. I’m going to have a look into your code and see if I can understand the conditions.
 
I wonder if there is a way to adjust the sensitivity of the conditions similar to how one can adjust chart patterns in tos. Unfortunately it doesn’t seem to pick up most BF’s on intraday charts which would be ideal for the Strat. I’m going to have a look into your code and see if I can understand the conditions.

I've seen BF when there is a nice long outside bar on 30m and so on. Can you expand on what you have in mind?
 
@RajB, I don't know the root cause but it appears if I set "Is Alert Setup" to Yes then the lines don't extend to the right. I checked other settings and everything (Fit studies etc) is enabled.
  • you hit the nail on the head, sorry this was my first script and I made a mistake
  • I removed the reference to isAlertSetup now, alerts part is not working anyway
  • Please try this version and report the results back , you can load it from this shared link http://tos.mx/1VdAZlK , once you bless it, I will update the main post
 
I wonder if there is a way to adjust the sensitivity of the conditions similar to how one can adjust chart patterns in tos. Unfortunately it doesn’t seem to pick up most BF’s on intraday charts which would be ideal for the Strat. I’m going to have a look into your code and see if I can understand the conditions.
  • unlike other scripts where you can alter the sensitivity from 1 to 0.5 etc, this is different as it looks for interlaced peaks and valleys
  • the underlying conditions were taken from here:
https://www.patternsmart.com/cart/index.php?route=product/product&product_id=430&search=broadening
  • please also observe the comments and other links posted within the code
  • I am not sure if there is a sensitivity/depth that you can modify, but if you learn something, I would be happy to learn too
 
  • unlike other scripts where you can alter the sensitivity from 1 to 0.5 etc, this is different as it looks for interlaced peaks and valleys
  • the underlying conditions were taken from here:
https://www.patternsmart.com/cart/index.php?route=product/product&product_id=430&search=broadening
  • please also observe the comments and other links posted within the code
  • I am not sure if there is a sensitivity/depth that you can modify, but if you learn something, I would be happy to learn too
Hmmm…After reading the link you sent, it looks like there are sensitivity adjustments you already built in?

You can control the size of pattern you want to detect by changing the value of Input Strength: the number of bars on the left and right side of the swing high and low.


If we set Strength to 5, it means the high at A is higher than the highs of on both of its left and right side for 5 bars, same for point B. And the price low at C is lower than 5 bars on both left and right side, same for point D.

The larger value you set for "Strength" the bigger size of the pattern you will get.
 
Last edited by a moderator:

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

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