Bulkowski Double Bottom Pattern Indicator for ThinkorSwim



This indicator was created for ThinkorSwim based on Bulkowski's Double Bottom Setup. You can learn more about the pattern, examples, and how to trade it here.

The Bulkowski Double Bottom indicator highlights a few things on your chart:
  • First Pivot
  • Pivot Low
  • Double Bottom Price
  • Breakout Price

thinkScript Code

Rich (BB code):
# Bulkowski Double Bottom Pattern
# TASC Aril 2019
# Nube 3.30.19
# v 0.02, unsuccessfully trying to mark the first pivot of the pattern

    # INPUTS
input pivotLength = 4;
input maxDoubleBottomWidth = 24;
input tolerancePercentage = 1.5;
input ticksAboveDoubleBottomHigh = 1;

# Universal
def h = high;
def l = low;
def nan = Double.NaN;
def x = BarNumber();
def tick = TickSize();
# Study Specific
def lowPivotBar = if !GetMinValueOffset(l, pivotLength + 1) 
                  and GetMinValueOffset(l, pivotLength + 1)[-pivotLength + 1] ==
                      pivotLength - 1
                  then x 
                  else lowPivotBar[1];
def lowPivot = if x == lowPivotBar
               then x   
               else nan;
def lowPivotPrice = if x == lowPivotBar
                    then l
                    else lowPivotPrice[1];
def priorLowPivotBar = if lowPivotBar != lowPivotBar[1]
                       then lowPivotBar[1]
                       else priorLowPivotBar[1];
def priorLowPivotPrice = if x == lowPivotBar
                         then GetValue(l,  lowPivotBar - priorLowPivotBar)
                         else priorLowPivotPrice[1];
def hh = if x crosses above lowPivotBar
         then h
         else if h > hh[1]
              then h
              else hh[1];
def highBetweenPivots = if x == lowPivotBar
                        then hh
                        else highBetweenPivots[1];
# Checking for pivot lows being within tolerancePercentage
def doubleBottom = if Between(lowPivotPrice,
                              priorLowPivotPrice * (1 - tolerancePercentage * .01),
                              priorLowPivotPrice * (1 + tolerancePercentage * .01))
                   and lowPivotBar - priorLowPivotBar <= maxDoubleBottomWidth
                   then Min(lowPivotPrice,priorLowPivotPrice)
                   else nan;
# invalidating pattern when price breaks below the doubleBottom price
def valid = if IsNaN(doubleBottom[1])
            and !IsNaN(doubleBottom)
            then 1
            else if l crosses below doubleBottom
                 then 0
                 else valid[1];

    # Plots
PivotLow = x == lowPivotBar;

DoubleBottomPrice = if valid then doubleBottom else nan;

BreakoutPrice = if DoubleBottomPrice
                then highBetweenPivots + ticksAboveDoubleBottomHigh * tick
                else nan;

AddChartBubble(DoubleBottomPrice and IsNaN(DoubleBottomPrice[-1]),
               DoubleBottomPrice, DoubleBottomPrice+"
Bottomm Price
", Color.Red, 0);
AddChartBubble(BreakoutPrice and IsNaN(BreakoutPrice[-1]),
               BreakOutPrice, "Breakout Price
"+ BreakOutPrice, Color.Green);

# f/  Bulkowski Double Bottom Pattern from April 2019 TASC this section still incorrect. Attempting to mark first pivot
def untilDB = fold i = -maxDoubleBottomWidth + 1 to 0
              with u
              while IsNaN(doubleBottom)
              do u + GetValue(IsNaN(doubleBottom), i);
def firstPivot = !IsNaN(lowPivot) and
                 IsNaN(GetValue(doubleBottom, -untilDB)) and
                 Between(GetValue(doubleBottom, -untilDB -1),
                         l * (1 - tolerancePercentage * .01),
                         l * (1 + tolerancePercentage * .01));

AddChartBubble(firstPivot, l, "First Pivot", Color.Red, 0);

Shareable Link

Last edited:


New member
Hey, I think it works very well, and I'm able to convert it into a scan filter like I can do with other studies, but the scan filter isn't working as intended for my purposes, and I need tips.

Intention: It detects a double bottom immediately and after about 30 minutes, it should no longer show up in the scan. For example, it bottoms at 1.45 once, then it bottoms 1.45 the second time 5 hours later. It shows up in my scan immediately when that happens, which is good. However, it remains in the scan even after 3 days after the double bottom has formed (two peak lows). I don't want to be trading a stock that has already went up a ton after 3 days after the double bottom formation. I want it to be removed from the scan after a 30 minute bar or (30 1 minute bars) because I like to buy the double bottom immediately with a tight stop loss for high reward/risk ratio, like buying at 5.01 at a bottom of 5, stop loss at 4.99.

Any tips on how to restrict the scan to only show immediate double bottom formations, not double bottoms that formed a long while ago like 3 days ago?


New member
use within " x " days at the end of scan code
Hi I put within 1 bar at a few parts of the code, then several parts of the code, since putting it at the end didn't seem to work, but no luck. It still shows up the same number of results. For example, I modified the plot to this:

DoubleBottomPrice = (if valid then 1 else nan) within 1 bar;