Congestion Zone

Department

New member
Hello! I need help creating this indicator for highlighting congestion.

Idea: Take candle body [open to close] and extend those prices levels forward. If x number (say 3) candles open or close in that range create a grey box from initial candle. Then stop the grey box once the first candle does not open/close inside the grey box around. (Grey box is = open/close of initial candle)

Here is an image of what is envisioned - /ES on March 10th, 2022, at 11:25am to 11:45am
ES-mar-10-22-zone.png


Requested Inputs:
1. Number of candles inside zone to begin painting
2. Maximum range of body to count as an initial candle (AKA prevent large bodied candles from triggering this as they are likely to engulf many candles)
2.1 I predict this to be a function of ATR of the last 5/10 candles.

Issues I predict might happen:
1. A candle after the initial candle will fit the criteria and create another grey box leading to overlapping boxes. I have no idea how to prevent this...
 
Solution
@halcyonguy
i reread your rules and realize i what i made is just inside bars. not this ...open or close in that range...
I had missed that too.. lol..
Kept looking at @Department screencap, thinking 'that's not right'.

Anyway after seeing that, here is a rough start, I've not been able to give this much attention yet.


fLPmenc.png

Ruby:
input rangeMin = 3;

#idk if defining these variables makes the code less intensive?
def upBoxOpen = open;
def upBoxClose = close;
def downBoxOpen = open;
def downBoxClose = close;

#green start - Checks if the future open/close are between the Open/close of initial bar.
def gct1 = if Between(close[-1], upBoxOpen, upBoxClose) or Between(open[-1], upBoxOpen, upBoxClose) then 1 else 0...
Its been done.
I've been trying to tinker with that code for a few hours now but cannot get it to do what I am trying. The main issue I have is I don't care if highs or lows go passed the predefined area. I only care that the candle open or close or both are within the area. The wicks are meaningless to me.
 
Alright I tried my best to figure out a method of doing this. I have the code that identifies what I want, using up to 3 bars forward (would just have to repeat the lines to test further candles but still working on making this usable first).

What I need help on is drawing the cloud/range:
1. I don't know how to make a cloud keep drawing with the same dimensions from the triggering candle. I know the aforementioned script does it but I don't know how to modify their code to use my criteria.
2. I attempted to just draw two lines at the prices I wanted however I am not able to make it extend past the first line so I am clearly missing something in the code. (this code is borrowed from my other thread (https://usethinkscript.com/threads/support-resistance-that-ends-once-touched.9491/#post-86377))

Below I attached my code for identifying the candles I want. And the base code for my attempt of 2 - although I reverted back to its original state and just have comments on what I believe needs to be changed.

I'd greatly appreciate the help.

Code:
input rangeMin = 3;

#idk if defining these variables makes the code less intensive?
def upBoxOpen = open;
def upBoxClose = close;
def downBoxOpen = open;
def downBoxClose = close;

#green start - Checks if the future open/close are between the Open/close of initial bar.
def gct1 = if Between(close[-1], upBoxOpen, upBoxClose) or Between(open[-1], upBoxOpen, upBoxClose) then 1 else 0;
def gct2 = if gct1 == 1 and (Between(close[-2], upBoxOpen, upBoxClose) or Between(open[-2], upBoxOpen, upBoxClose)) then 1 else 0;
def gct3 = if gct2 == 1 and (Between(close[-3], upBoxOpen, upBoxClose) or Between(open[-3], upBoxOpen, upBoxClose)) then 1 else 0;

#Red Starts - Checks if the future open/close are between the Open/close of initial bar.
def rct1 = if Between(close[-1], upBoxClose, upBoxOpen) or Between(open[-1], upBoxClose, upBoxOpen) then 1 else 0;
def rct2 = if rct1 == 1 and (Between(close[-2], upBoxClose, upBoxOpen) or Between(open[-2], upBoxClose, upBoxOpen)) then 1 else 0;
def rct3 = if rct2 == 1 and (Between(close[-3], upBoxClose, upBoxOpen) or Between(open[-3], upBoxClose, upBoxOpen)) then 1 else 0;

#Checking to make sure it finds the correct bars
plot gSum = gct1 + gct2 + gct3;
gSum.SetPaintingStrategy(PaintingStrategy.VALUES_BELOW);
plot rSum = rct1 + rct2 + rct3;
rSum.SetPaintingStrategy(PaintingStrategy.VALUES_ABOVE);

#Ideally I'd like a cloud but idk how to keep the cloud drawing forward with original dimensions.
#addcloud(if gSum == 3 then upBoxOpen else double.NaN, upBoxClose, color.gray, color.gray);
#addcloud(if gSum[3] == 3 then upBoxOpen[3] else double.NaN, upBoxClose[3], color.gray, color.gray);

#New Attempt for make shift cloud (just a line)

######################################################################################
#Defintions of Support Levels.########################################################
######################################################################################
# would have to copy paste this for the close line as well.
plot SupportLevel = if gSum == rangeMin then open else Double.NaN;
SupportLevel.SetPaintingStrategy(PaintingStrategy.VALUES_ABOVE);

#Need open and Close Lines. SO SLineOpen, and SLineClose probably?
def SLine0;
def SLine1;
def SLine2;
def SLine3;
def SLine4;

#I believe what needs to be changes is the "low <= SLine0[1]"
#The new check would be Between(close, SLineOpen, SLineClose) or Between(open, SlineOpen, SLineClose)
#Check if the close or then open of the current candle are between the original open/close
def SLineCount;
if BarNumber() == 1 {
    SLineCount = 0;
} else if (IsNaN(SupportLevel) and SLine0[1] <> 0 and low <= SLine0[1]) {
    SLineCount = 20;
} else if (IsNaN(SupportLevel) and SLine1[1] <> 0 and low <= SLine1[1]) {
    SLineCount = 0;
} else if (IsNaN(SupportLevel) and SLine2[1] <> 0 and low <= SLine2[1]) {
    SLineCount = 1;
} else if (IsNaN(SupportLevel) and SLine3[1] <> 0 and low <= SLine3[1]) {
    SLineCount = 2;
} else if (IsNaN(SupportLevel) and SLine4[1] <> 0 and low <= SLine4[1]) {
    SLineCount = 3;

} else if (!IsNaN(SupportLevel) and SLine0[1] <> 0 and low <= SLine0[1]) {
    SLineCount = 0;
} else if (!IsNaN(SupportLevel) and SLine1[1] <> 0 and low <= SLine1[1]) {
    SLineCount = 1;
} else if (!IsNaN(SupportLevel) and SLine2[1] <> 0 and low <= SLine2[1]) {
    SLineCount = 2;
} else if (!IsNaN(SupportLevel) and SLine3[1] <> 0 and low <= SLine3[1]) {
    SLineCount = 3;
} else if (!IsNaN(SupportLevel) and SLine4[1] <> 0 and low <= SLine4[1]) {
    SLineCount = 4;
} else if (!IsNaN(SupportLevel)) and SLineCount[1] != 4 {
    SLineCount = SLineCount[1] + 1;
} else if (!IsNaN(SupportLevel)) and SLineCount[1] == 4 {
    SLineCount = 0;
} else {
    SLineCount = SLineCount[1];
}

#green candles
######################################################################################
#Plots of Support Levels. ############################################################
######################################################################################
#Same changes as above
#I believe what needs to be changes is the "low <= SLine0[1]"
#The new check would be Between(close, SLineOpen, SLineClose) or Between(open, SlineOpen, SLineClose)
#Check if the close or then open of the current candle are between the original open/close

SLine0 = if !IsNaN(SupportLevel) and SLineCount == 0 then SupportLevel else if !IsNaN(SLine0[1]) and low <= SLine0[1] then 0 else SLine0[1];
plot SLineP0 = if SLine0 > 0 then SLine0 else Double.NaN;
SLineP0.SetStyle(Curve.POINTS);
SLineP0.SetDefaultColor(Color.LIGHT_GREEN);
SLineP0.SetLineWeight(1);
SLineP0.HideBubble();
#----------------------------------------------------------------------------------
SLine1 = if !IsNaN(SupportLevel) and SLineCount == 1 then SupportLevel else if !IsNaN(SLine1[1]) and low <= SLine1[1] then 0 else SLine1[1];
plot SLineP1 = if SLine1 > 0 then SLine1 else Double.NaN;
SLineP1.SetStyle(Curve.POINTS);
SLineP1.SetDefaultColor(Color.LIGHT_GREEN);
SLineP1.SetLineWeight(1);
SLineP1.HideBubble();
#----------------------------------------------------------------------------------
SLine2 = if !IsNaN(SupportLevel) and SLineCount == 2 then SupportLevel else if !IsNaN(SLine2[1]) and low <= SLine2[1] then 0 else SLine2[1];
plot SLineP2 = if SLine2 > 0 then SLine2 else Double.NaN;
SLineP2.SetStyle(Curve.POINTS);
SLineP2.SetDefaultColor(Color.LIGHT_GREEN);
SLineP2.SetLineWeight(1);
SLineP2.HideBubble();
#----------------------------------------------------------------------------------
SLine3 = if !IsNaN(SupportLevel) and SLineCount == 3 then SupportLevel else if !IsNaN(SLine3[1]) and low <= SLine3[1] then 0 else SLine3[1];
plot SLineP3 = if SLine3 > 0 then SLine3 else Double.NaN;
SLineP3.SetStyle(Curve.POINTS);
SLineP3.SetDefaultColor(Color.LIGHT_GREEN);
SLineP3.SetLineWeight(1);
SLineP3.HideBubble();
#----------------------------------------------------------------------------------
SLine4 = if !IsNaN(SupportLevel) and SLineCount == 4 then SupportLevel else if !IsNaN(SLine4[1]) and low <= SLine4[1] then 0 else SLine4[1];
plot SLineP4 = if SLine4 > 0 then SLine4 else Double.NaN;
SLineP4.SetStyle(Curve.POINTS);
SLineP4.SetDefaultColor(Color.LIGHT_GREEN);
SLineP4.SetLineWeight(1);
SLineP4.HideBubble();
#----------------------------------------------------------------------------------
 
The main issue I have is I don't care if highs or lows go passed the predefined area. I only care that the candle open or close or both are within the area. The wicks are meaningless to me.
Question, before getting too deep into this. Why not just modify the price plot to not have wicks and use the Consolidation Box with that? You could then edit to do what you want. Might be worth a look.

vDBAefV.png

Ruby:
# B3 Consolidation Box   v1
# -- Automates a box and shows the breakouts via price color with targets based on the box's range.
# -- In a system the gray balance line would be your stop, or you may exit on any trip back within the old box range.
# -- The color of the candles does not tell you when to be long or short, it simply tells you the last signal given.
# -- You must manage your trade targets via your own profit protection tactics.
# Intended only for the use of the person(s) to who(m) this script was originally distributed.
# User of the script assumes all risk;
# The coder and the distributers are not responsible for any loss of capital incurred upon usage of this script.
# amalia added commentary after chatting more with B3 about the study:
# The first 2 inputs will need to be set for the chart you are looking at. What you want to find is the consolidation box settings that give you actionable targeting. If the price is shooting way past the tgt6 point, you need to lower the second input. The first input should likely be either 1, 2 or 3 only. Script is based on a strategy I learned from Ben's webcasts on TOS. He was doing some futurescast thing on consolidation boxes, and I had to see if I could make it work too. My Hypothesis is it is a great little scalper... you have to be willing to take singles and doubles and forget homers. He was trading ES

################################################################################
#edit by Svanoy
def highgreen= if open>=close then open else Double.NaN;
def lowgreen = if open>=close then close else Double.NaN;
def highred = if open<=close then close else Double.NaN;
def lowred = if open<=close then open else Double.NaN;

hidePricePlot();
AddChart(growColor = color.red, fallColor = Color.green, neutralColor = Color.current, high = highgreen, low = lowgreen, open = open, close = close, type = ChartType.CANDLE);
AddChart(growColor = Color.green, fallColor = Color.red, neutralColor = Color.current, high = highred, low = lowred, open = open, close = close, type = ChartType.CANDLE);

def newhigh = if open>=close then open else close;
def newlow = if open<=close then open else close;
#################################################################################

declare upper;
input BarsUsedForRange = 3;
input BarsRequiredToRemainInRange = 5;
input TargetMultiple = 0.5;
input ColorPrice = no;
input HideTargets = yes;
input HideBalance = yes;
input HideBoxLines = no;
input HideCloud = no;
input HideLabels = yes;

# Identify Consolidation
def HH = Highest(newhigh[1], BarsUsedForRange);
def LL = Lowest(newlow[1], BarsUsedForRange);
def maxH = Highest(HH, BarsRequiredToRemainInRange);
def maxL = Lowest(LL, BarsRequiredToRemainInRange);
def HHn = if maxH == maxH[1] or maxL == maxL then maxH else HHn[1];
def LLn = if maxH == maxH[1] or maxL == maxL then maxL else LLn[1];
def Bh = if newhigh <= HHn and HHn == HHn[1] then HHn else Double.NaN;
def Bl = if newlow >= LLn and LLn == LLn[1] then LLn else Double.NaN;
def CountH = if IsNaN(Bh) or IsNaN(Bl) then 2 else CountH[1] + 1;
def CountL = if IsNaN(Bh) or IsNaN(Bl) then 2 else CountL[1] + 1;
def ExpH = if BarNumber() == 1 then Double.NaN else
            if CountH[-BarsRequiredToRemainInRange] >= BarsRequiredToRemainInRange then HHn[-BarsRequiredToRemainInRange] else
            if newhigh <= ExpH[1] then ExpH[1] else Double.NaN;
def ExpL = if BarNumber() == 1 then Double.NaN else
            if CountL[-BarsRequiredToRemainInRange] >= BarsRequiredToRemainInRange then LLn[-BarsRequiredToRemainInRange] else
            if newlow >= ExpL[1] then ExpL[1] else Double.NaN;

# Plot the High and Low of the Box; Paint Cloud

plot BoxHigh = if !IsNaN(ExpL) and !IsNaN(ExpH) then ExpH else Double.NaN;
plot BoxLow = if !IsNaN(ExpL) and !IsNaN(ExpH) then ExpL else Double.NaN;
BoxHigh.SetDefaultColor(Color.DARK_GREEN);
BoxHigh.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
BoxLow.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
BoxLow.SetDefaultColor(Color.DARK_RED);
BoxHigh.SetHiding(HideBoxLines);
BoxLow.SetHiding(HideBoxLines);

AddCloud(if !HideCloud then BoxHigh else Double.NaN, BoxLow, Color.GRAY, Color.GRAY);

# Things to the Right of a Finished Box
def eH = if BarNumber() == 1 then Double.NaN else if !IsNaN(BoxHigh[1]) and IsNaN(BoxHigh) then BoxHigh[1] else eH[1];
def eL = if BarNumber() == 1 then Double.NaN else if !IsNaN(BoxLow[1]) and IsNaN(BoxLow) then BoxLow[1] else eL[1];
def diff = (eH - eL) * TargetMultiple;
plot Balance = if IsNaN(BoxHigh) and IsNaN(BoxLow) then (eH + eL) / 2 else Double.NaN;
plot Htgt_1 = if IsNaN(BoxHigh) and newhigh >= eH then eH + diff else Double.NaN;
plot Htgt_2 = if IsNaN(BoxHigh) and newhigh >= eH then eH + diff * 2 else Double.NaN;
plot Htgt_3 = if IsNaN(BoxHigh) and newhigh >= eH then eH + diff * 3 else Double.NaN;
plot Htgt_4 = if IsNaN(BoxHigh) and newhigh >= eH then eH + diff * 4 else Double.NaN;
plot Htgt_5 = if IsNaN(BoxHigh) and newhigh >= eH then eH + diff * 5 else Double.NaN;
plot Htgt_6 = if IsNaN(BoxHigh) and newhigh >= eH then eH + diff * 6 else Double.NaN;
plot Ltgt_1 = if IsNaN(BoxLow) and newlow <= eL then eL - diff else Double.NaN;
plot Ltgt_2 = if IsNaN(BoxLow) and newlow <= eL then eL - diff * 2 else Double.NaN;
plot Ltgt_3 = if IsNaN(BoxLow) and newlow <= eL then eL - diff * 3 else Double.NaN;
plot Ltgt_4 = if IsNaN(BoxLow) and newlow <= eL then eL - diff * 4 else Double.NaN;
plot Ltgt_5 = if IsNaN(BoxLow) and newlow <= eL then eL - diff * 5 else Double.NaN;
plot Ltgt_6 = if IsNaN(BoxLow) and newlow <= eL then eL - diff * 6 else Double.NaN;
Balance.SetHiding(HideBalance);
Balance.SetDefaultColor(CreateColor(255, 255, 255));
Balance.SetPaintingStrategy(PaintingStrategy.SQUARES);
Htgt_2.SetLineWeight(2);
Htgt_4.SetLineWeight(2);
Htgt_6.SetLineWeight(2);
Htgt_1.SetDefaultColor(CreateColor( 50, 100 , 75));
Htgt_1.SetPaintingStrategy(PaintingStrategy.DASHES);
Htgt_2.SetDefaultColor(CreateColor( 50, 100 , 75));
Htgt_2.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Htgt_3.SetDefaultColor(CreateColor( 50, 100 , 75));
Htgt_3.SetPaintingStrategy(PaintingStrategy.DASHES);
Htgt_4.SetDefaultColor(CreateColor( 50, 100 , 75));
Htgt_4.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Htgt_5.SetDefaultColor(CreateColor( 50, 100 , 75));
Htgt_5.SetPaintingStrategy(PaintingStrategy.DASHES);
Htgt_6.SetDefaultColor(CreateColor( 50, 100 , 75));
Htgt_6.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Ltgt_2.SetLineWeight(2);
Ltgt_4.SetLineWeight(2);
Ltgt_6.SetLineWeight(2);
Ltgt_1.SetDefaultColor(CreateColor( 100, 50 , 75));
Ltgt_1.SetPaintingStrategy(PaintingStrategy.DASHES);
Ltgt_2.SetDefaultColor(CreateColor( 100, 50 , 75));
Ltgt_2.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Ltgt_3.SetDefaultColor(CreateColor( 100, 50 , 75));
Ltgt_3.SetPaintingStrategy(PaintingStrategy.DASHES);
Ltgt_4.SetDefaultColor(CreateColor( 100, 50 , 75));
Ltgt_4.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Ltgt_5.SetDefaultColor(CreateColor( 100, 50 , 75));
Ltgt_5.SetPaintingStrategy(PaintingStrategy.DASHES);
Ltgt_6.SetDefaultColor(CreateColor( 100, 50 , 75));
Ltgt_6.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
Htgt_1.SetHiding(HideTargets);
Htgt_2.SetHiding(HideTargets);
Htgt_3.SetHiding(HideTargets);
Htgt_4.SetHiding(HideTargets);
Htgt_5.SetHiding(HideTargets);
Htgt_6.SetHiding(HideTargets);
Ltgt_1.SetHiding(HideTargets);
Ltgt_2.SetHiding(HideTargets);
Ltgt_3.SetHiding(HideTargets);
Ltgt_4.SetHiding(HideTargets);
Ltgt_5.SetHiding(HideTargets);
Ltgt_6.SetHiding(HideTargets);

# Labels
AddLabel(!HideLabels, "TgtLvls = " + diff + "pts each | Bal = " + Balance, if newhigh > eH  and newlow < eL then Color.YELLOW else if newhigh > eH then Color.GREEN else if newlow < eL then Color.RED else Color.GRAY);
AddLabel(!HideLabels && newhigh > eH && newlow < eL, "OUTSIDE BAR!!", Color.YELLOW);
AddLabel(!HideLabels && newhigh > eH && newlow >= eL, "Long", Color.GREEN);
AddLabel(!HideLabels && newhigh <= eH && newlow < eL, "Short", Color.RED);

#Price Color
AssignPriceColor(if !ColorPrice then Color.CURRENT else if !IsNaN(BoxHigh) then Color.GRAY else
                    if newhigh > eH  and newlow < eL then Color.YELLOW else
                    if newhigh > eH then Color.GREEN else if newlow < eL then Color.RED else Color.GRAY);
 
Question, before getting too deep into this. Why not just modify the price plot to not have wicks and use the Consolidation Box with that? You could then edit to do what you want. Might be worth a look.
1. I personally care about the wicks to see whats happened
2. I'm using multiple chart types (candles and heikin-ashi) --> seeing wicks matters
2.1 I'd rather not & don't have the screen real estate to have another chart open solely to have this
3. The above code changes the zone with new highs/lows -- However I recognize this could be changed.
4. The issue of repainting even if it is already inside a zone & length continuation

Below is an image of March 11th, where the zone turned out really long - I have the study you have linked on, and a light transparent box of where I'd ideally have a zone.

Length-issue.png
 
1. I personally care about the wicks to see whats happened
2. I'm using multiple chart types (candles and heikin-ashi) --> seeing wicks matters
2.1 I'd rather not & don't have the screen real estate to have another chart open solely to have this
3. The above code changes the zone with new highs/lows -- However I recognize this could be changed.
4. The issue of repainting even if it is already inside a zone & length continuation

Below is an image of March 11th, where the zone turned out really long - I have the study you have linked on, and a light transparent box of where I'd ideally have a zone.

Length-issue.png

EDIT - my code was wrong, so i didn't see the desired patterns
see below for my updated studies
-----------------------------------------------------------------

what is the exact date and time of the first bar in the box in the image?
i'm wondering if your cursor was off the chart so it showed the wrong date at the top of chart?
i looked and i can't find it.

i made a version of this. will test more tomorrow and post
 
Last edited:
Hello! I need help creating this indicator for highlighting congestion.

Idea: Take candle body [open to close] and extend those prices levels forward. If x number (say 3) candles open or close in that range create a grey box from initial candle. Then stop the grey box once the first candle does not open/close inside the grey box around. (Grey box is = open/close of initial candle)

Here is an image of what is envisioned - /ES on March 10th, 2022, at 11:25am to 11:45am
ES-mar-10-22-zone.png


Requested Inputs:
1. Number of candles inside zone to begin painting
2. Maximum range of body to count as an initial candle (AKA prevent large bodied candles from triggering this as they are likely to engulf many candles)
2.1 I predict this to be a function of ATR of the last 5/10 candles.

Issues I predict might happen:
1. A candle after the initial candle will fit the criteria and create another grey box leading to overlapping boxes. I have no idea how to prevent this...

i reread your rules and realize what i made is just inside bars. not this ...open or close in that range...
later, i will look at the posts in this thread and see if it's worthwhile to convert what i have.
 
Last edited:
@halcyonguy
i reread your rules and realize i what i made is just inside bars. not this ...open or close in that range...
I had missed that too.. lol..
Kept looking at @Department screencap, thinking 'that's not right'.

Anyway after seeing that, here is a rough start, I've not been able to give this much attention yet.


fLPmenc.png

Ruby:
input rangeMin = 3;

#idk if defining these variables makes the code less intensive?
def upBoxOpen = open;
def upBoxClose = close;
def downBoxOpen = open;
def downBoxClose = close;

#green start - Checks if the future open/close are between the Open/close of initial bar.
def gct1 = if Between(close[-1], upBoxOpen, upBoxClose) or Between(open[-1], upBoxOpen, upBoxClose) then 1 else 0;
def gct2 = if gct1 == 1 and (Between(close[-2], upBoxOpen, upBoxClose) or Between(open[-2], upBoxOpen, upBoxClose)) then 1 else 0;
def gct3 = if gct2 == 1 and (Between(close[-3], upBoxOpen, upBoxClose) or Between(open[-3], upBoxOpen, upBoxClose)) then 1 else 0;

#Red Starts - Checks if the future open/close are between the Open/close of initial bar.
def rct1 = if Between(close[-1], upBoxClose, upBoxOpen) or Between(open[-1], upBoxClose, upBoxOpen) then 1 else 0;
def rct2 = if rct1 == 1 and (Between(close[-2], upBoxClose, upBoxOpen) or Between(open[-2], upBoxClose, upBoxOpen)) then 1 else 0;
def rct3 = if rct2 == 1 and (Between(close[-3], upBoxClose, upBoxOpen) or Between(open[-3], upBoxClose, upBoxOpen)) then 1 else 0;

#Checking to make sure it finds the correct bars
plot gSum = gct1 + gct2 + gct3;
gSum.SetPaintingStrategy(PaintingStrategy.VALUES_BELOW);
plot rSum = rct1 + rct2 + rct3;
rSum.SetPaintingStrategy(PaintingStrategy.VALUES_ABOVE);

def rBoxUpper;
def rBoxLower;
def gBoxUpper;
def gBoxLower;

if !IsNaN(rBoxUpper[1]) and (!Between(open,rBoxLower[1],rBoxUpper[1]) and !Between(close,rBoxLower[1],rBoxUpper[1])) {
rBoxUpper = Double.Nan;
rBoxLower = Double.NaN;
}else if IsNaN(rBoxUpper[1]) and IsNaN(gBoxUpper[1]) and rsum[3] == rangeMin {
rBoxUpper = open[3];
rBoxLower = close[3];
}else{
rBoxUpper = rBoxUpper[1];
rBoxLower = rBoxLower[1];
}

if !IsNaN(gBoxUpper[1]) and !Between(open,gBoxLower[1],gBoxUpper[1]) and !Between(close,gBoxLower[1],gBoxUpper[1]) {
gBoxUpper = Double.Nan;
gBoxLower = Double.NaN;
}else if IsNaN(gBoxUpper[1]) and IsNaN(rBoxUpper[1]) and gsum[3] == rangeMin {
gBoxUpper = close[3];
gBoxLower = open[3];
}else{
gBoxUpper = gBoxUpper[1];
gBoxLower = gBoxLower[1];
}

plot rUpperPlot = if (!IsNaN(close),rBoxUpper[-rangeMin],Double.NaN);
rUpperPlot.SetPaintingStrategy(PaintingStrategy.DASHES);
rUpperPlot.SetDefaultColor(Color.Red);

plot rLowerPlot = if (!IsNaN(close),rBoxlower[-RangeMin],Double.NaN);
rLowerPlot.SetPaintingStrategy(PaintingStrategy.DASHES);
rLowerPlot.SetDefaultColor(Color.Red);

plot rCZoneUpper = if (IsNaN(rUpperPlot[-1]) and !IsNaN(rUpperPlot[rangeMin]),rUpperPlot[rangeMin],Double.NaN);
rcZoneUpper.SetPaintingStrategy(PaintingStrategy.DASHES);
rcZoneUpper.SetDefaultColor(Color.Red);

plot rCZoneLower =if (IsNaN(rLowerPlot[-1]) and !IsNaN(rlowerPlot[rangeMin]),rLowerPlot[rangeMin],Double.NaN);
rcZoneLower.SetPaintingStrategy(PaintingStrategy.DASHES);
rcZoneLower.SetDefaultColor(Color.Red);

AddCloud(rUpperPlot, rLowerPlot,color.LIGHT_GRAY,color.LIGHT_GRAY);
AddCloud(rcZoneUpper, rcZoneLower,color.LIGHT_GRAY,color.LIGHT_GRAY);

###################################################################################################################

plot gUpperPlot = if (!IsNaN(close),gBoxUpper[-rangeMin],Double.NaN);
gUpperPlot.SetPaintingStrategy(PaintingStrategy.DASHES);
gUpperPlot.SetDefaultColor(Color.Green);

plot gLowerPlot = if (!IsNaN(close),gBoxlower[-RangeMin],Double.NaN);
gLowerPlot.SetPaintingStrategy(PaintingStrategy.DASHES);
gLowerPlot.SetDefaultColor(Color.Green);

plot gCZoneUpper = if (IsNaN(gUpperPlot[-1]) and !IsNaN(gUpperPlot[rangeMin]),gUpperPlot[rangeMin],Double.NaN);
gcZoneUpper.SetPaintingStrategy(PaintingStrategy.DASHES);
gcZoneUpper.SetDefaultColor(Color.Green);

plot gCZoneLower =if (IsNaN(gLowerPlot[-1]) and !IsNaN(glowerPlot[rangeMin]),gLowerPlot[rangeMin],Double.NaN);
gcZoneLower.SetPaintingStrategy(PaintingStrategy.DASHES);
gcZoneLower.SetDefaultColor(Color.Green);

AddCloud(gUpperPlot, gLowerPlot,color.LIGHT_GRAY,color.LIGHT_GRAY);
AddCloud(gcZoneUpper, gcZoneLower,color.LIGHT_GRAY,color.LIGHT_GRAY);
 
Last edited:
Solution
Hello! I need help creating this indicator for highlighting congestion.

Idea: Take candle body [open to close] and extend those prices levels forward. If x number (say 3) candles open or close in that range create a grey box from initial candle. Then stop the grey box once the first candle does not open/close inside the grey box around. (Grey box is = open/close of initial candle)

here is my version of congestion bars
it uses a fold loop, so it might be slower than what svanoy posted.


this looks for a big candle (bar #1) and bars after it that are partly within the range of the first bar.

if a bar is big, but still within the bar#1 range, it is ignored.
when price moves beyond the price levels of bar #1, the pattern stops.

. choose price levels , wicks or body. ( default is body)
. choose a minimum quantity of smaller bars before a pattern will start. default is 3.
. choose to ignore big candles. a candle much bigger won't be used to start a pattern.
. based on comparing to an average.
. pick the height factor(5) and average length(20)

. show color shading, cloud.
. show labels, wick or body, min quantity of bars.
. show a bubble with the count of bars in the pattern.
. show an arrow under the 1st bar of pattern.

on each bar, it uses a fold loop to compare future bars to the current bar, to see if 3 or more are smaller.


Ruby:
# congestion_box_00a

# change a code line in insidebars, in fold loop, to turn it into a congestion study, to look for,
#  ...If x number candles open or close in that range...
# i left the original insidebar code line in

#https://usethinkscript.com/threads/congestion-zone.10503/#post-92890

def na = double.nan;
def bn = barnumber();
#-------------------------------------
# choose wick or body price levels
input candle_levels = { "wick" , default "body" };
def highx;
def lowx;
switch (candle_levels) {
case "wick":
  highx = high;
  lowx = low;
case "body":
  highx = max(open, close);
  lowx = min(open, close);
}

def ht = highx - lowx;
#-----------------------------------
input min_inside_bars = 3;

input show_label__candle_levels = no;
addlabel(show_label__candle_levels, "Candle levels - " + candle_levels, color.yellow);

input show_label__min_inside_bars = no;
addlabel(show_label__min_inside_bars, "Min inside bars - " + min_inside_bars, color.yellow);
# --------------------------------
# test if a giant candle appears,  then ignore it
input ignore_big_candles = no;
input candle_ht_avg_multiplier_max = 5.0;
input candle_height_avg_len = 20;

def ht_avg = round(Average( ht[1], candle_height_avg_len),2);
def ht_avg_factor = round(ht / ht_avg, 1);

def ht_en = !ignore_big_candles or (ht < (ht_avg * candle_ht_avg_multiplier_max));
#----------------------------------
# inside bar , count smaller bars after the current bar  
def max_bars = 70;
def future_bar_count = fold k = 1 to max_bars
  with q = 1
## congestion , 1 bar parameter within high/low
  while (ht_en and (between(getvalue(highx, -k), lowx, highx) or between(getvalue(lowx, -k), lowx, highx)))
## insidebars , top and bottom of bar is within high/low
# while (ht_en and highx[0] >= getvalue(highx, -k) and lowx[0] <= getvalue(lowx, -k))
  do q + 1;


# -------------------------------
def rev_cnt = 
 if bn == 1 then 0
 else if rev_cnt[1] > 1 then (rev_cnt[1] - 1)
 else if future_bar_count >= min_inside_bars then future_bar_count
 else 0;

def inside_start = (rev_cnt[1] <= 1 and future_bar_count >= min_inside_bars);
def start_cnt = if bn == 1 then 0 else if inside_start then (start_cnt[1] + 1) else start_cnt[1];

#def vert = 0.0006;
def vert = 0.00;
input show_cloud = yes;
input show_bubble_pattern_bar_count = no;
addchartbubble(show_bubble_pattern_bar_count and inside_start, (high * (1 + vert)), future_bar_count, color.gray, yes);

# ----------------------------------
# plot lines

def inside_hi =
 if rev_cnt == 0 then na
 else if inside_start then highx 
 else inside_hi[1];

def inside_lo =
 if rev_cnt == 0 then na
 else if inside_start then lowx 
 else inside_lo[1];

plot zhi = inside_hi;
plot zlo = inside_lo;

zhi.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
#zhi.SetStyle(Curve.MEDIUM_DASH);
#zhi.SetDefaultColor(Color.cyan);
zhi.SetDefaultColor(Color.gray);
zhi.setlineweight(1);
zhi.hidebubble();

zlo.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
#zlo.SetStyle(Curve.MEDIUM_DASH);
#zlo.SetDefaultColor(Color.cyan);
zlo.SetDefaultColor(Color.gray);
zlo.setlineweight(1);
zlo.hidebubble();

# ---------------------------------------
# use 2 clouds, to avoid 2 adjacent patterns being connected
def iscnt_odd = ( start_cnt % 2 == 1 );
def zhiodd = if (show_cloud and iscnt_odd) then zhi else na;
addcloud(zhiodd, zlo, color.gray);
def zhieven = if (show_cloud and !iscnt_odd) then zhi else na;
addcloud(zhieven, zlo, color.gray);

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

input show_arrow_on_bar1 = no;
plot z1 = if show_arrow_on_bar1 and inside_start then (low * (1 - vert)) else na;
z1.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
z1.SetDefaultColor(Color.cyan);
z1.setlineweight(2);
z1.hidebubble();
#

price levels set to (candle) body
gAUZEEM.jpg
 
Last edited:
this is similar and might of interest , so i am posting it


i misunderstood the question and made this study, that finds sequential inside bars
it has just 1 line that is different from my congestion study


inside bars

this looks for a big candle (bar #1) and several smaller candles (inside bars) after it.
if a bar is big, but less than the first bar of an existing pattern, it is ignored.
when price moves beyond the price levels of bar #1, the pattern stops.

. choose price levels , wicks or body.
. choose a minimum quantity of smaller bars before a pattern will start. default is 3.
. choose to ignore big candles. a candle much bigger won't be used to start a pattern.
. based on comparing to an average.
. pick the height factor(5) and average length(20)

. show color shading, cloud.
. show labels, wick or body, min quantity of bars.
. show a bubble with the count of bars in the pattern.
. show an arrow under the 1st bar of pattern.

on each bar, it compares future bars to the current bar, to see if 3 or more are smaller.


Ruby:
# insidebars_congestion_box_00f

#https://usethinkscript.com/threads/congestion-zone.10503/#post-92890
# find a pattern of several inside bars, that don't start from an abnormally large bar.

def na = double.nan;
def bn = barnumber();
#-------------------------------------
# choose wick or body price levels
input candle_levels = { "wick" , default "body" };
def highx;
def lowx;
switch (candle_levels) {
case "wick":
  highx = high;
  lowx = low;
case "body":
  highx = max(open, close);
  lowx = min(open, close);
}

def ht = highx - lowx;
#-----------------------------------
input min_inside_bars = 3;

input show_label__candle_levels = no;
addlabel(show_label__candle_levels, "Candle levels - " + candle_levels, color.yellow);

input show_label__min_inside_bars = no;
addlabel(show_label__min_inside_bars, "Min inside bars - " + min_inside_bars, color.yellow);
# --------------------------------
# test if a giant candle appears,  then ignore it
input ignore_big_candles = no;
input candle_ht_avg_multiplier_max = 5.0;
input candle_height_avg_len = 20;

def ht_avg = round(Average( ht[1], candle_height_avg_len),2);
def ht_avg_factor = round(ht / ht_avg, 1);

def ht_en = !ignore_big_candles or (ht < (ht_avg * candle_ht_avg_multiplier_max));
#----------------------------------
# inside bar , count smaller bars after the current bar 
def max_bars = 50;
def inside_bar_count = fold k = 1 to max_bars
  with q = 1
  while (ht_en and highx[0] >= getvalue(highx, -k) and lowx[0] <= getvalue(lowx, -k))
  do q + 1;

# -------------------------------
def rev_cnt =
 if bn == 1 then 0
 else if rev_cnt[1] > 1 then (rev_cnt[1] - 1)
 else if inside_bar_count >= min_inside_bars then inside_bar_count
 else 0;

def inside_start = (rev_cnt[1] <= 1 and inside_bar_count >= min_inside_bars);
def start_cnt = if bn == 1 then 0 else if inside_start then (start_cnt[1] + 1) else start_cnt[1];

#def vert = 0.0006;
def vert = 0.00;
input show_cloud = yes;
input show_bubble_pattern_bar_count = yes;
addchartbubble(show_bubble_pattern_bar_count and inside_start, (high * (1 + vert)), inside_bar_count, color.gray, yes);

# ----------------------------------
# plot lines

def inside_hi =
 if rev_cnt == 0 then na
 else if inside_start then highx
 else inside_hi[1];

def inside_lo =
 if rev_cnt == 0 then na
 else if inside_start then lowx
 else inside_lo[1];

plot zhi = inside_hi;
plot zlo = inside_lo;

zhi.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
#zhi.SetStyle(Curve.MEDIUM_DASH);
#zhi.SetDefaultColor(Color.cyan);
zhi.SetDefaultColor(Color.gray);
zhi.setlineweight(1);
zhi.hidebubble();

zlo.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
#zlo.SetStyle(Curve.MEDIUM_DASH);
#zlo.SetDefaultColor(Color.cyan);
zlo.SetDefaultColor(Color.gray);
zlo.setlineweight(1);
zlo.hidebubble();

# ---------------------------------------
# use 2 clouds, to avoid 2 adjacent patterns being connected
def iscnt_odd = ( start_cnt % 2 == 1 );
def zhiodd = if (show_cloud and iscnt_odd) then zhi else na;
addcloud(zhiodd, zlo, color.gray);
def zhieven = if (show_cloud and !iscnt_odd) then zhi else na;
addcloud(zhieven, zlo, color.gray);

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

input show_arrow_on_bar1 = no;
plot z1 = if show_arrow_on_bar1 and inside_start then (low * (1 - vert)) else na;
z1.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
z1.SetDefaultColor(Color.cyan);
z1.setlineweight(2);
z1.hidebubble();
#


pattern bar count bubbles turned on
/ES 3/7 4day 1min
hMNJmmK.jpg

hal_inside
 
Last edited:
this is similar and might of interest , so i am posting it


i misunderstood the question and made this study, that finds sequential inside bars
it has just 1 line that is different from my congestion study


inside bars

this looks for a big candle (bar #1) and several smaller candles (inside bars) after it.
if a bar is big, but less than the first bar of an existing pattern, it is ignored.
when price moves beyond the price levels of bar #1, the pattern stops.

. choose price levels , wicks or body.
. choose a minimum quantity of smaller bars before a pattern will start. default is 3.
. choose to ignore big candles. a candle much bigger won't be used to start a pattern.
. based on comparing to an average.
. pick the height factor(5) and average length(20)

. show color shading, cloud.
. show labels, wick or body, min quantity of bars.
. show a bubble with the count of bars in the pattern.
. show an arrow under the 1st bar of pattern.

on each bar, it compares future bars to the current bar, to see if 3 or more are smaller.


Ruby:
# insidebars_congestion_box_00f

#https://usethinkscript.com/threads/congestion-zone.10503/#post-92890
# find a pattern of several inside bars, that don't start from an abnormally large bar.

def na = double.nan;
def bn = barnumber();
#-------------------------------------
# choose wick or body price levels
input candle_levels = { "wick" , default "body" };
def highx;
def lowx;
switch (candle_levels) {
case "wick":
  highx = high;
  lowx = low;
case "body":
  highx = max(open, close);
  lowx = min(open, close);
}

def ht = highx - lowx;
#-----------------------------------
input min_inside_bars = 3;

input show_label__candle_levels = no;
addlabel(show_label__candle_levels, "Candle levels - " + candle_levels, color.yellow);

input show_label__min_inside_bars = no;
addlabel(show_label__min_inside_bars, "Min inside bars - " + min_inside_bars, color.yellow);
# --------------------------------
# test if a giant candle appears,  then ignore it
input ignore_big_candles = no;
input candle_ht_avg_multiplier_max = 5.0;
input candle_height_avg_len = 20;

def ht_avg = round(Average( ht[1], candle_height_avg_len),2);
def ht_avg_factor = round(ht / ht_avg, 1);

def ht_en = !ignore_big_candles or (ht < (ht_avg * candle_ht_avg_multiplier_max));
#----------------------------------
# inside bar , count smaller bars after the current bar 
def max_bars = 50;
def inside_bar_count = fold k = 1 to max_bars
  with q = 1
  while (ht_en and highx[0] >= getvalue(highx, -k) and lowx[0] <= getvalue(lowx, -k))
  do q + 1;

# -------------------------------
def rev_cnt =
 if bn == 1 then 0
 else if rev_cnt[1] > 1 then (rev_cnt[1] - 1)
 else if inside_bar_count >= min_inside_bars then inside_bar_count
 else 0;

def inside_start = (rev_cnt[1] <= 1 and inside_bar_count >= min_inside_bars);
def start_cnt = if bn == 1 then 0 else if inside_start then (start_cnt[1] + 1) else start_cnt[1];

#def vert = 0.0006;
def vert = 0.00;
input show_cloud = yes;
input show_bubble_pattern_bar_count = yes;
addchartbubble(show_bubble_pattern_bar_count and inside_start, (high * (1 + vert)), inside_bar_count, color.gray, yes);

# ----------------------------------
# plot lines

def inside_hi =
 if rev_cnt == 0 then na
 else if inside_start then highx
 else inside_hi[1];

def inside_lo =
 if rev_cnt == 0 then na
 else if inside_start then lowx
 else inside_lo[1];

plot zhi = inside_hi;
plot zlo = inside_lo;

zhi.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
#zhi.SetStyle(Curve.MEDIUM_DASH);
#zhi.SetDefaultColor(Color.cyan);
zhi.SetDefaultColor(Color.gray);
zhi.setlineweight(1);
zhi.hidebubble();

zlo.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
#zlo.SetStyle(Curve.MEDIUM_DASH);
#zlo.SetDefaultColor(Color.cyan);
zlo.SetDefaultColor(Color.gray);
zlo.setlineweight(1);
zlo.hidebubble();

# ---------------------------------------
# use 2 clouds, to avoid 2 adjacent patterns being connected
def iscnt_odd = ( start_cnt % 2 == 1 );
def zhiodd = if (show_cloud and iscnt_odd) then zhi else na;
addcloud(zhiodd, zlo, color.gray);
def zhieven = if (show_cloud and !iscnt_odd) then zhi else na;
addcloud(zhieven, zlo, color.gray);

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

input show_arrow_on_bar1 = no;
plot z1 = if show_arrow_on_bar1 and inside_start then (low * (1 - vert)) else na;
z1.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
z1.SetDefaultColor(Color.cyan);
z1.setlineweight(2);
z1.hidebubble();
#


pattern bar count bubbles turned on
/ES 3/7 4day 1min
hMNJmmK.jpg
@halcyonguy @Svanoy @Department Thank you for this indicator! @halcyonguy I am wondering if it would be possible to add bullish and bearish target levels the same range as the mother bar breakout? Similar to what @Svanoy had in POST#5. Thank you!
 
@halcyonguy @Svanoy @Department Thank you for this indicator! @halcyonguy I am wondering if it would be possible to add bullish and bearish target levels the same range as the mother bar breakout? Similar to what @Svanoy had in POST#5. Thank you!

sorry, i'm not sure what you are asking.
i don't know what bullish and bearish target levels are.
my studies already draw lines from the motherbar.
i looked briefly at svanoy's b3 code, but i am not sure what defines the box top and bottom levels. the levels come from multiple candles.
 
@halcyonguy @Svanoy @Department Thank you for this indicator! @halcyonguy I am wondering if it would be possible to add bullish and bearish target levels the same range as the mother bar breakout? Similar to what @Svanoy had in POST#5. Thank you!

maybe this is what you were asking for ?
the image in post1 had lines above and below the box. i added them in this version
--------------------------------------------------------

i modified my congestion study from post11
i added horizontal lines at the highest and lowest of each congestion range.


Ruby:
# congestion_box_00c

# add horz lines at highest hi above box, and lowest low below box

# https://usethinkscript.com/threads/congestion-zone.10503/#post-92890

def na = double.nan;
def bn = barnumber();
#-------------------------------------
# choose wick or body price levels
input candle_levels = { "wick" , default "body" };
def highx;
def lowx;
switch (candle_levels) {
case "wick":
  highx = high;
  lowx = low;
case "body":
  highx = max(open, close);
  lowx = min(open, close);
}

def ht = highx - lowx;
#-----------------------------------
input min_inside_bars = 3;

input show_label__candle_levels = no;
addlabel(show_label__candle_levels, "Candle levels - " + candle_levels, color.yellow);

input show_label__min_inside_bars = no;
addlabel(show_label__min_inside_bars, "Min inside bars - " + min_inside_bars, color.yellow);
# --------------------------------
# test if a giant candle appears,  then ignore it
input ignore_big_candles = no;
input candle_ht_avg_multiplier_max = 5.0;
input candle_height_avg_len = 20;

def ht_avg = round(Average( ht[1], candle_height_avg_len),2);
def ht_avg_factor = round(ht / ht_avg, 1);

def ht_en = !ignore_big_candles or (ht < (ht_avg * candle_ht_avg_multiplier_max));
#----------------------------------
# inside bar , count smaller bars after the current bar  
def max_bars = 70;
def future_bar_count = fold k = 1 to max_bars
  with q = 1
## congestion , 1 bar parameter within high/low
  while (ht_en and (between(getvalue(highx, -k), lowx, highx) or between(getvalue(lowx, -k), lowx, highx)))
## insidebars , top and bottom of bar is within high/low
# while (ht_en and highx[0] >= getvalue(highx, -k) and lowx[0] <= getvalue(lowx, -k))
  do q + 1;


# -------------------------------
def rev_cnt = 
 if bn == 1 then 0
 else if rev_cnt[1] > 1 then (rev_cnt[1] - 1)
 else if future_bar_count >= min_inside_bars then future_bar_count
 else 0;

def inside_start = (rev_cnt[1] <= 1 and future_bar_count >= min_inside_bars);
def start_cnt = if bn == 1 then 0 else if inside_start then (start_cnt[1] + 1) else start_cnt[1];

#def vert = 0.0006;
def vert = 0.00;
input show_cloud = yes;
input show_bubble_pattern_bar_count = no;
addchartbubble(show_bubble_pattern_bar_count and inside_start, (high * (1 + vert)), future_bar_count, color.gray, yes);

# ----------------------------------
# plot lines

def inside_hi =
 if rev_cnt == 0 then na
 else if inside_start then highx 
 else inside_hi[1];

def inside_lo =
 if rev_cnt == 0 then na
 else if inside_start then lowx 
 else inside_lo[1];

plot zhi = inside_hi;
plot zlo = inside_lo;

zhi.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
#zhi.SetStyle(Curve.MEDIUM_DASH);
#zhi.SetDefaultColor(Color.cyan);
zhi.SetDefaultColor(Color.gray);
zhi.setlineweight(1);
zhi.hidebubble();

zlo.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
#zlo.SetStyle(Curve.MEDIUM_DASH);
#zlo.SetDefaultColor(Color.cyan);
zlo.SetDefaultColor(Color.gray);
zlo.setlineweight(1);
zlo.hidebubble();

# ---------------------------------------
# use 2 clouds, to avoid 2 adjacent patterns being connected
def iscnt_odd = ( start_cnt % 2 == 1 );

def zhiodd = if (show_cloud and iscnt_odd) then zhi else na;
addcloud(zhiodd, zlo, color.gray);
def zhieven = if (show_cloud and !iscnt_odd) then zhi else na;
addcloud(zhieven, zlo, color.gray);

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

input show_arrow_on_bar1 = no;
plot z1 = if show_arrow_on_bar1 and inside_start then (low * (1 - vert)) else na;
z1.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
z1.SetDefaultColor(Color.cyan);
z1.setlineweight(2);
z1.hidebubble();
#
# ---------------------------------


# add horz lines at,
#  highest hi above box,
#  and lowest low below box
# iscnt_odd

input show_range_highest_lowest_lines = no;
def srl = show_range_highest_lowest_lines;

def toplimit;
if srl and inside_start then {
toplimit = fold t1 = 0 to max_bars 
  with top1
  while t1 < future_bar_count
  do max(top1, getvalue(high, -t1));
} else if srl and rev_cnt > 0 then {
toplimit = toplimit[1];
} else {
toplimit = na;
}

plot zt = toplimit;
zt.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
zt.SetDefaultColor(Color.yellow);
#zt.setlineweight(1);
zt.hidebubble();


def botlimit;
if srl and inside_start then {
botlimit = fold b1 = 0 to max_bars 
  with bot1 = 999999
  while b1 < future_bar_count
  do min(bot1, getvalue(low, -b1));
} else if srl and rev_cnt > 0 then {
botlimit = botlimit[1];
} else {
botlimit = na;
}

plot zb = botlimit;
zb.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
zb.SetDefaultColor(Color.yellow);
#zb.setlineweight(1);
zb.hidebubble();
#


WWACPL8.jpg
 
@halcyonguy Is there a way to have the upper and low lines to continue even if there are few bar above or below the range or can I set a date range and plot the upper and low lines of the high and low of that date range?
 
Last edited:
maybe this is what you were asking for ?
the image in post1 had lines above and below the box. i added them in this version
--------------------------------------------------------

i modified my congestion study from post11
i added horizontal lines at the highest and lowest of each congestion range.


Ruby:
# congestion_box_00c

# add horz lines at highest hi above box, and lowest low below box

# https://usethinkscript.com/threads/congestion-zone.10503/#post-92890

def na = double.nan;
def bn = barnumber();
#-------------------------------------
# choose wick or body price levels
input candle_levels = { "wick" , default "body" };
def highx;
def lowx;
switch (candle_levels) {
case "wick":
  highx = high;
  lowx = low;
case "body":
  highx = max(open, close);
  lowx = min(open, close);
}

def ht = highx - lowx;
#-----------------------------------
input min_inside_bars = 3;

input show_label__candle_levels = no;
addlabel(show_label__candle_levels, "Candle levels - " + candle_levels, color.yellow);

input show_label__min_inside_bars = no;
addlabel(show_label__min_inside_bars, "Min inside bars - " + min_inside_bars, color.yellow);
# --------------------------------
# test if a giant candle appears,  then ignore it
input ignore_big_candles = no;
input candle_ht_avg_multiplier_max = 5.0;
input candle_height_avg_len = 20;

def ht_avg = round(Average( ht[1], candle_height_avg_len),2);
def ht_avg_factor = round(ht / ht_avg, 1);

def ht_en = !ignore_big_candles or (ht < (ht_avg * candle_ht_avg_multiplier_max));
#----------------------------------
# inside bar , count smaller bars after the current bar 
def max_bars = 70;
def future_bar_count = fold k = 1 to max_bars
  with q = 1
## congestion , 1 bar parameter within high/low
  while (ht_en and (between(getvalue(highx, -k), lowx, highx) or between(getvalue(lowx, -k), lowx, highx)))
## insidebars , top and bottom of bar is within high/low
# while (ht_en and highx[0] >= getvalue(highx, -k) and lowx[0] <= getvalue(lowx, -k))
  do q + 1;


# -------------------------------
def rev_cnt =
 if bn == 1 then 0
 else if rev_cnt[1] > 1 then (rev_cnt[1] - 1)
 else if future_bar_count >= min_inside_bars then future_bar_count
 else 0;

def inside_start = (rev_cnt[1] <= 1 and future_bar_count >= min_inside_bars);
def start_cnt = if bn == 1 then 0 else if inside_start then (start_cnt[1] + 1) else start_cnt[1];

#def vert = 0.0006;
def vert = 0.00;
input show_cloud = yes;
input show_bubble_pattern_bar_count = no;
addchartbubble(show_bubble_pattern_bar_count and inside_start, (high * (1 + vert)), future_bar_count, color.gray, yes);

# ----------------------------------
# plot lines

def inside_hi =
 if rev_cnt == 0 then na
 else if inside_start then highx
 else inside_hi[1];

def inside_lo =
 if rev_cnt == 0 then na
 else if inside_start then lowx
 else inside_lo[1];

plot zhi = inside_hi;
plot zlo = inside_lo;

zhi.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
#zhi.SetStyle(Curve.MEDIUM_DASH);
#zhi.SetDefaultColor(Color.cyan);
zhi.SetDefaultColor(Color.gray);
zhi.setlineweight(1);
zhi.hidebubble();

zlo.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
#zlo.SetStyle(Curve.MEDIUM_DASH);
#zlo.SetDefaultColor(Color.cyan);
zlo.SetDefaultColor(Color.gray);
zlo.setlineweight(1);
zlo.hidebubble();

# ---------------------------------------
# use 2 clouds, to avoid 2 adjacent patterns being connected
def iscnt_odd = ( start_cnt % 2 == 1 );

def zhiodd = if (show_cloud and iscnt_odd) then zhi else na;
addcloud(zhiodd, zlo, color.gray);
def zhieven = if (show_cloud and !iscnt_odd) then zhi else na;
addcloud(zhieven, zlo, color.gray);

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

input show_arrow_on_bar1 = no;
plot z1 = if show_arrow_on_bar1 and inside_start then (low * (1 - vert)) else na;
z1.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
z1.SetDefaultColor(Color.cyan);
z1.setlineweight(2);
z1.hidebubble();
#
# ---------------------------------


# add horz lines at,
#  highest hi above box,
#  and lowest low below box
# iscnt_odd

input show_range_highest_lowest_lines = no;
def srl = show_range_highest_lowest_lines;

def toplimit;
if srl and inside_start then {
toplimit = fold t1 = 0 to max_bars
  with top1
  while t1 < future_bar_count
  do max(top1, getvalue(high, -t1));
} else if srl and rev_cnt > 0 then {
toplimit = toplimit[1];
} else {
toplimit = na;
}

plot zt = toplimit;
zt.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
zt.SetDefaultColor(Color.yellow);
#zt.setlineweight(1);
zt.hidebubble();


def botlimit;
if srl and inside_start then {
botlimit = fold b1 = 0 to max_bars
  with bot1 = 999999
  while b1 < future_bar_count
  do min(bot1, getvalue(low, -b1));
} else if srl and rev_cnt > 0 then {
botlimit = botlimit[1];
} else {
botlimit = na;
}

plot zb = botlimit;
zb.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
zb.SetDefaultColor(Color.yellow);
#zb.setlineweight(1);
zb.hidebubble();
#


WWACPL8.jpg
@halcyonguy The lines need to be the same height (size) as the consolidation box and act as targets to the upside and to the downside. It's so that when price breaks out of the consolidation box, you will know what your target is to exit the trade. Similar to the image attached.
 
@halcyonguy The lines need to be the same height (size) as the consolidation box and act as targets to the upside and to the downside. It's so that when price breaks out of the consolidation box, you will know what your target is to exit the trade. Similar to the image attached.

this version has 3 risk and 3 reward lines

Code:
# congestion_box_00d

#  add risk/reward lines , 3x
# https://usethinkscript.com/threads/congestion-zone.10503/#post-97560
# post 18

def na = double.nan;
def bn = barnumber();
#-------------------------------------
# choose wick or body price levels
input candle_levels = { default "wick" , "body" };
def highx;
def lowx;
switch (candle_levels) {
case "wick":
  highx = high;
  lowx = low;
case "body":
  highx = max(open, close);
  lowx = min(open, close);
}

def ht = highx - lowx;
#-----------------------------------
input min_inside_bars = 3;

input show_label__candle_levels = no;
addlabel(show_label__candle_levels, "Candle levels - " + candle_levels, color.yellow);

input show_label__min_inside_bars = no;
addlabel(show_label__min_inside_bars, "Min inside bars - " + min_inside_bars, color.yellow);
# --------------------------------
# test if a giant candle appears,  then ignore it
input ignore_big_candles = no;
input candle_ht_avg_multiplier_max = 5.0;
input candle_height_avg_len = 20;

def ht_avg = round(Average( ht[1], candle_height_avg_len),2);
def ht_avg_factor = round(ht / ht_avg, 1);

def ht_en = !ignore_big_candles or (ht < (ht_avg * candle_ht_avg_multiplier_max));
#----------------------------------
# inside bar , count smaller bars after the current bar 
def max_bars = 70;
def future_bar_count = fold k = 1 to max_bars
  with q = 1
## congestion , 1 bar parameter within high/low
  while (ht_en and (between(getvalue(highx, -k), lowx, highx) or between(getvalue(lowx, -k), lowx, highx)))
## insidebars , top and bottom of bar is within high/low
# while (ht_en and highx[0] >= getvalue(highx, -k) and lowx[0] <= getvalue(lowx, -k))
  do q + 1;


# -------------------------------
# count down from mother bar, to last inside bar
def rev_cnt =
 if bn == 1 then 0
 else if rev_cnt[1] > 1 then (rev_cnt[1] - 1)
 else if future_bar_count >= min_inside_bars then future_bar_count
 else 0;

def inside_start = (rev_cnt[1] <= 1 and future_bar_count >= min_inside_bars);
def start_cnt = if bn == 1 then 0 else if inside_start then (start_cnt[1] + 1) else start_cnt[1];

#def vert = 0.0006;
def vert = 0.00;
input show_cloud = yes;
input show_bubble_pattern_bar_count = no;
addchartbubble(show_bubble_pattern_bar_count and inside_start, (high * (1 + vert)), future_bar_count, color.gray, yes);

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

# ----------------------------------
# plot lines

def inside_hi =
 if rev_cnt == 0 then na
 else if inside_start then highx
 else inside_hi[1];

def inside_lo =
 if rev_cnt == 0 then na
 else if inside_start then lowx
 else inside_lo[1];

plot zhi = inside_hi;
plot zlo = inside_lo;

zhi.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
#zhi.SetStyle(Curve.MEDIUM_DASH);
#zhi.SetDefaultColor(Color.cyan);
zhi.SetDefaultColor(Color.gray);
zhi.setlineweight(1);
zhi.hidebubble();

zlo.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
#zlo.SetStyle(Curve.MEDIUM_DASH);
#zlo.SetDefaultColor(Color.cyan);
zlo.SetDefaultColor(Color.gray);
zlo.setlineweight(1);
zlo.hidebubble();

# ---------------------------------------
# use 2 clouds, to avoid 2 adjacent patterns being connected
def iscnt_odd = ( start_cnt % 2 == 1 );

def zhiodd = if (show_cloud and iscnt_odd) then zhi else na;
addcloud(zhiodd, zlo, color.gray);
def zhieven = if (show_cloud and !iscnt_odd) then zhi else na;
addcloud(zhieven, zlo, color.gray);

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

input show_arrow_on_bar1 = no;
plot z1 = if show_arrow_on_bar1 and inside_start then (low * (1 - vert)) else na;
z1.SetPaintingStrategy(PaintingStrategy.ARROW_UP);
z1.SetDefaultColor(Color.cyan);
z1.setlineweight(2);
z1.hidebubble();
#
# ---------------------------------

# show risk/reward lines, a multiple of mother bar height

def rng = inside_hi - inside_lo;

input show_risk_reward_lines = yes;
def srr = show_risk_reward_lines;

plot reward1 = if srr then (inside_hi + (1 * rng)) else na;
reward1.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
reward1.SetDefaultColor(Color.gray);
reward1.hidebubble();

plot reward2 = if srr then (inside_hi + (2 * rng)) else na;
reward2.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
reward2.SetDefaultColor(Color.gray);
reward2.hidebubble();

plot reward3 = if srr then (inside_hi + (3 * rng)) else na;
reward3.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
reward3.SetDefaultColor(Color.gray);
reward3.hidebubble();


plot risk1 = if srr then (inside_lo - (1 * rng)) else na;
risk1.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
risk1.SetDefaultColor(Color.gray);
risk1.hidebubble();

plot risk2 = if srr then (inside_lo - (2 * rng)) else na;
risk2.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
risk2.SetDefaultColor(Color.gray);
risk2.hidebubble();

plot risk3 = if srr then (inside_lo - (3 * rng)) else na;
risk3.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
risk3.SetDefaultColor(Color.gray);
risk3.hidebubble();




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

# add horz lines at,
#  highest hi above box,
#  and lowest low below box
# iscnt_odd

input show_range_highest_lowest_lines = no;
def srl = show_range_highest_lowest_lines;

def toplimit;
if srl and inside_start then {
toplimit = fold t1 = 0 to max_bars
  with top1
  while t1 < future_bar_count
  do max(top1, getvalue(high, -t1));
} else if srl and rev_cnt > 0 then {
toplimit = toplimit[1];
} else {
toplimit = na;
}

plot zt = toplimit;
zt.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
zt.SetDefaultColor(Color.yellow);
#zt.setlineweight(1);
zt.hidebubble();


def botlimit;
if srl and inside_start then {
botlimit = fold b1 = 0 to max_bars
  with bot1 = 999999
  while b1 < future_bar_count
  do min(bot1, getvalue(low, -b1));
} else if srl and rev_cnt > 0 then {
botlimit = botlimit[1];
} else {
botlimit = na;
}

plot zb = botlimit;
zb.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
zb.SetDefaultColor(Color.yellow);
#zb.setlineweight(1);
zb.hidebubble();



# -----------------------------------
# -----------------------------------
# test stuff - and me


addchartbubble(0, low*0.996,
inside_start + "\n" +
toplimit + "\n" +
rev_cnt + "\n" +
high + "\n"
, ( if inside_start then color.yellow else color.gray), no);



def u = 0;
addchartbubble(u and inside_start, low,
start_cnt + " cnt\n" +
iscnt_odd + " odd"
, color.yellow, no);


# count how many patterns on chart
# if a stock has many, more opportuneties to catch a move



def cnt3 = if bn == 1 then 0 else if (inside_start and future_bar_count == 3) then (cnt3[1] + 1) else cnt3[1];
def cnt4 = if bn == 1 then 0 else if (inside_start and future_bar_count == 4) then (cnt4[1] + 1) else cnt4[1];
def cnt5 = if bn == 1 then 0 else if (inside_start and future_bar_count == 5) then (cnt5[1] + 1) else cnt5[1];
def cnt6 = if bn == 1 then 0 else if (inside_start and future_bar_count == 6) then (cnt6[1] + 1) else cnt6[1];
def cnt7 = if bn == 1 then 0 else if (inside_start and future_bar_count == 7) then (cnt7[1] + 1) else cnt7[1];
def cnt8 = if bn == 1 then 0 else if (inside_start and future_bar_count == 8) then (cnt8[1] + 1) else cnt8[1];
def cnt9 = if bn == 1 then 0 else if (inside_start and future_bar_count == 9) then (cnt9[1] + 1) else cnt9[1];

def cnt10 = if bn == 1 then 0 else if (inside_start and future_bar_count > 9) then (cnt10[1] + 1) else cnt10[1];

input cnt_labels = yes;
addlabel(cnt_labels, "      " , color.black);
addlabel(cnt_labels, "3 bars " + cnt3, color.yellow);
addlabel(cnt_labels, "4 bars " + cnt4, color.yellow);
addlabel(cnt_labels, "5 bars " + cnt5, color.yellow);
addlabel(cnt_labels, "6 bars " + cnt6, color.yellow);
addlabel(cnt_labels, "7 bars " + cnt7, color.yellow);
addlabel(cnt_labels, "8 bars " + cnt8, color.yellow);
addlabel(cnt_labels, "9 bars " + cnt9, color.yellow);
addlabel(cnt_labels, "10+ bars " + cnt10, color.yellow);

#
 
@halcyonguy The lines need to be the same height (size) as the consolidation box and act as targets to the upside and to the downside. It's so that when price breaks out of the consolidation box, you will know what your target is to exit the trade. Similar to the image attached.
@halcyonguy The lines need to be the same height (size) as the consolidation box and act as targets to the upside and to the downside. It's so that when price breaks out of the consolidation box, you will know what your target is to exit the trade. Similar to the image attached.
Do u have study script for mother bar high and low with targets?
 

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