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:
Solution
@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/
#...
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.
 
@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
 
Last edited:
@RajB sure, i also have something similar completed but without logic that deals with some scenarios like when a prior lower-hi/higher-low can't be found, etc. If you've dealt with some of those cases, let me know, would love to work together!
 
@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:
Solution
@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:
  • loaded the script from above, just in case my version had any differences
  • I could load the chart but don't see the issue manifesting locally. I used the same stock and time frame
  • I tried to add some lower charts and reduce the vertical space. In all cases, I was able to see broadening formation properly
  • I am curious as to why the issue is occurring. If possible, please enable debug flag and paste the results back.


ekPFYEv.png
 
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:
  • it would be a great help if you discussed your system/strategy in a new thread, as it will help a newbie like me
  • especially other indicators?
  • Do you review only a few charts or run a scan using this?


A couple of months ago, another member had posted a strategy based on this formation. If you draw a horizontal line from the first price where it starts, for example, DIS would be around 183.5 and it crosses above the price, then expect a sharp rise in that direction. Those posts seem to be deleted now and I am speaking from memory.

It's called #TheStrat if you'd like to learn more (self-plug) you can head to my website resources section https://alexsoptions.com/resources where there's tons of free content to sift through.

Cheers!
 
@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.
 

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