# Bulkowski Double Bottom Indicator for ThinkorSwim

#### BenTen

Staff member
Staff
VIP
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

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;

# VARIABLES
# 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
plot
PivotLow = x == lowPivotBar;
PivotLow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_WEDGE_DOWN);
PivotLow.SetDefaultColor(Color.Red);

plot
DoubleBottomPrice = if valid then doubleBottom else nan;
DoubleBottomPrice.SetDefaultColor(Color.Red);
DoubleBottomPrice.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);

plot
BreakoutPrice = if DoubleBottomPrice
then highBetweenPivots + ticksAboveDoubleBottomHigh * tick
else nan;
BreakoutPrice.SetDefaultColor(Color.Green);
BreakoutPrice.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);

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);``````

https://tos.mx/7678EI

Last edited:

##### New member
Hello, i'm just new here, and just want to know if there is any script for double top/bottom candles, thanks a lot guys !

Last edited by a moderator:

#### BenTen

Staff member
Staff
VIP
Welcome. Unfortunately there is nothing like that at the moment. I'm afraid you will have to identify the candlestick pattern yourself.

Last edited:

##### New member
@BenTen Thanks man, I will !

Last edited:

#### CreativiTimothy

##### 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?

#### horserider

##### Well-known member
VIP
use within " x " days at the end of scan code

#### CreativiTimothy

##### 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:

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

#### iamgshankar

##### New member
Friends,

Can someone please help me to use the above script to scan within the last few bars??

@BenTen I am not seeing the Break out price and other labels in my chart when i use the sharable link.. Am i missing something?

Thanks.

##### Active member
2019 Donor
VIP
There are errors in the label code.

#### Thinkprofits

##### New member
2019 Donor
Hi,
Does anyone have a scanner for Double Tops and Double Bottoms?

#### hoojsn

##### New member
Hi Ben,
There is 2 Error Code:

Staff member
Staff
VIP

VIP

#### CreativiTimothy

##### New member
@Cleartarget Sure. I basically just commented all the other plots out except the "DoubleBottomPrice" plot. That's the only plot you need for the scan (scans only allow one plot) that determines whether a double bottom exists in a stock or not.

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 = 1;
input maxDoubleBottomWidth = 24;
input tolerancePercentage = 1.5;
input ticksAboveDoubleBottomHigh = 1;

# VARIABLES
## 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
#plot
#PivotLow = x == lowPivotBar;
#PivotLow.SetPaintingStrategy(PaintingStrategy.BOOLEAN_WEDGE_DOWN);
#PivotLow.SetDefaultColor(Color.Red);

plot
DoubleBottomPrice = if valid then doubleBottom else nan;
DoubleBottomPrice.SetDefaultColor(Color.Red);
DoubleBottomPrice.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);

#plot
#BreakoutPrice = if DoubleBottomPrice
#                then highBetweenPivots + ticksAboveDoubleBottomHigh * tick
#                else nan;
#BreakoutPrice.SetDefaultColor(Color.Green);
#BreakoutPrice.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);

DoubleBottomPrice, DoubleBottomPrice+"\nBottomm Price\n", Color.Red, 0);
#               BreakOutPrice, "Breakout Price\n"+ 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);``````

#### Cleartarget

##### New member
VIP
Great thank for the information and help.

#### RBO

##### New member
VIP
How we do a scanner for double bottom ?

#### RBO

##### New member
VIP
Is there any indicator to find double bottom pattern in chart

#### CLICKANDGRAB808

##### New member
VIP
looks great thanks

#### johnatasjmo

##### New member
Thanks, works well.

#### dmillz

##### Member
VIP
Does anyone know how to plot the higher double bottom for a scan using this script.

Code:
``````# Double Bottom

# Mobius

input Percent_A_to_B = 2;

input Percent_A_to_C = .1;

input nP = 13;

input ShowValues = yes;

input ShowLines = yes;

def AB = Percent_A_to_B / 100;

def AC = Percent_A_to_C / 100;

def h = high;

def l = low;

def bar = BarNumber();

def Ps = 1 + AC;

def Ns = 1 - AC;

def ll = fold j = 1 to nP + 1

with q = 1

while q

do l < GetValue(low, -j);

def PivotL = if (bar > nP and

l == Lowest(l, nP) and

ll)

then l

else Double.NaN;

def PL1 = if !isNaN(PivotL)

then l

else PL1[1];

def PL1Bar = if !IsNaN(PivotL)

then bar

else PL1Bar[1];

def PL2 = if PL1 != PL1[1]

then PL1[1]

else PL2[1];

def PL2Bar = if PL1Bar != PL1Bar[1]

then Pl1Bar[1]

else PL2Bar[1];

def Check1 = if between(PL2, PL1 * Ns, PL1 * Ps)

then 1

else 0;

plot Cond1 = HighestAll(if Check1

then PL2

else double.nan);

def PL3 = if PL2 != PL2[1]

then PL2[1]

else PL3[1];

def PL3Bar = if PL2Bar != PL2Bar[1]

then Pl2Bar[1]

else PL3Bar[1];

def Check2 = if between(PL3, PL2 * Ns, PL2 * Ps)

then 1

else 0;

def PL4 = if PL3 != PL3[1]

then PL3[1]

else PL4[1];

def PL4Bar = if PL3Bar != PL3Bar[1]

then PL3Bar[1]

else PL4Bar[1];

def Check3 = if between(PL4, PL3 * Ns, PL3 * Ps)

then 1

else 0;

def PL5 = if PL4 != PL4[1]

then PL4[1]

else PL5[1];

def PL5Bar = if PL4Bar != PL4Bar[1]

then PL4Bar[1]

else PL5Bar[1];

def Check4 = if between(PL5, PL4 * Ns, PL4 * Ps)

then 1

else double.nan;

plot pivotLow = PivotL;

pivotLow.SetDefaultColor(Color.Yellow);

pivotLow.SetPaintingStrategy(PaintingStrategy.VALUES_BELOW);

pivotLow.SetHiding(!ShowValues);

plot PivotDot = PivotL;

PivotDot.SetDefaultColor(Color.Gray);

PivotDot.SetPaintingStrategy(PaintingStrategy.POINTS);

PivotDot.SetLineWeight(3);

# End Code``````