Calculating Price Density Index (PDI)

Ecantor

New member
Plus
I just learned thinkscript this weekend and this is my first script. I am trying to plot a horizontal line across the chart for the high of the last 65 bars going back from the most recent bar only. On a daily chart of 10 years, I determined by brute force that the lastbarnumber would be 2517. I have hardcoded this value just for simplicity. For example, on a daily chart of SCCO for 10 years, the high going back 65 bars from the bar of 8/6/21(I am not including today) would have been 83.29. I am therefore aiming to plot a horizontal line at 83.29 going across the chart. the sethiding feature fails. Can anyone tell me how I might accomplish what I am trying to do. I do not want to see any lines except the one at 83.29!

def zoldhigh = 0;

def zcurhigh = fold j = 2516 to 2517 do
if high > zoldhigh then highest(high,65) else zoldhigh;
plot zmaxhigh =if barnumber()==2517 then zcurhigh else 0;
zmaxhigh.sethiding(zmaxhigh==0);
 

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

ty. I got it. Takes a bit of getting used to thinking that the code is evaluated at each bar and reasoning results that way!! A bit different from most other programming languages.:)
yes, it is a different concept to understand (code runs on each bar). but when you do, it will help you to think about offsets, and which bar your formulas should reference from.

here is another fold example. this one uses while.
...while the condition is true, it processes the do formula.
...when while become false, the loop stops.
this study looks for an engulfing bar, a big bar that had several small bars before it.
when it finds one, it draws a bubble under the bar, with the count of previous small bars.

Ruby:
# Engulfing bar
# look back in time, to find bars smaller than the current bar

input minimum_engulfed_bars = 2;
def show_bubbles = yes;
def na = double.nan;
def barup = (close > open);

input lookback = 40;
# if while is used, fold loops as long as while statement is true
# when while becomes false, the loop stops, even if fold hasn't reached the highest count value
def bigbarcnt = fold k = 1 to lookback
with p
while (high > getvalue(high, k) and low < getvalue(low, k))
do p + 1;

addchartbubble((show_bubbles and bigbarcnt > minimum_engulfed_bars),(low * 0.999), bigbarcnt, if bigbarcnt == 0 then color.dark_gray else if barup then color.green else color.red, no);
#
hal_fold hal_engulf
 
Last edited:
I am modifying some code I previously wrote(with your wonderful help) to run on a 15 minute chart rather than a daily or weekly chart. The code plots the high and low of the past 90 days with a slight upwards or downwards adjustment of .15 up for the lower line and down for the upper line.
The problem I am having is that on a 15 minute chart, thinkorswim will display both lines and this will distort the size of the bars or candles on the chart. To get around the problem, I decided to only display one of the lines. So only the line closest to the current close of the 15 minute candle will be displayed. I introduced a variable "whichline" which holds the correct value. IF whichline=1, I only want to display the upper line and if whichline = 0, I only want to display the lower line. I tried using an "If whichline=1 then line2.hide". Next, I tried using "Def line and Def line2" instead of 2 plots. Doing this I thought to do a plot line3 which would plot the appropriate line. I also tried a switch statement based on whichline
having a value of 1 or 0. None of these attempts have worked. Can anyone help me out? Here is my code
Ruby:
#hint length of 1950 on 15 minute chart = 90 days of daily #data
input length = 1950;
input dAdjuster = .015;

def LastBar = HighestAll(if !IsNaN(close) then BarNumber() else Double.NaN);
def BarRem = LastBar - BarNumber();
def High1950 = if !BarRem then Highest(high, length) else Double.NaN;
plot Line = if BarRem <= length then HighestAll(High1950) - HighestAll(High1950) * dAdjuster else Double.NaN;





def low1950 = if !BarRem then Lowest(low, length) else
Double.NaN;
plot line2 = if BarRem <= length then LowestAll(low1950) +
LowestAll(low1950) * dAdjuster
else Double.NaN;

def whichline = if AbsValue(close - High1950) < AbsValue(close - low1950) then 1
else 0;
AddLabel(yes, "whichline " + whichline);

#plot line3 = if whichline == 1 then line
# else line2;

#plot line3;
#switch (whichline)
# case 1:
# line3 = line;
#case 0:
# line3=line2;
#default:
# line3=0;
#

# if whichline == 1 then line2.hide()
# else line.hide();

input debug = yes;
AddLabel(debug, "Line" + " " + Line, Color.WHITE);
AddLabel(debug, "Line2" + " " + line2, Color.WHITE);
AddLabel( !BarRem <= length, Concat( "Range ", HighestAll(High1950) - HighestAll(High1950) * dAdjuster -
LowestAll(low1950) +
LowestAll(low1950) * dAdjuster));

def zrange = if !BarRem then HighestAll(High1950) - HighestAll(High1950) * dAdjuster -
LowestAll(low1950) +
LowestAll(low1950) * dAdjuster else Double.NaN;
 
Last edited by a moderator:
I am modifying some code I previously wrote(with your wonderful help) to run on a 15 minute chart rather than a daily or weekly chart. The code plots the high and low of the past 90 days with a slight upwards or downwards adjustment of .15 up for the lower line and down for the upper line.
The problem I am having is that on a 15 minute chart, thinkorswim will display both lines and this will distort the size of the bars or candles on the chart. To get around the problem, I decided to only display one of the lines. So only the line closest to the current close of the 15 minute candle will be displayed. I introduced a variable "whichline" which holds the correct value. IF whichline=1, I only want to display the upper line and if whichline = 0, I only want to display the lower line. I tried using an "If whichline=1 then line2.hide". Next, I tried using "Def line and Def line2" instead of 2 plots. Doing this I thought to do a plot line3 which would plot the appropriate line. I also tried a switch statement based on whichline
having a value of 1 or 0. None of these attempts have worked. Can anyone help me out? Here is my code
Ruby:
#hint length of 1950 on 15 minute chart = 90 days of daily #data
input length = 1950;
input dAdjuster = .015;

def LastBar = HighestAll(if !IsNaN(close) then BarNumber() else Double.NaN);
def BarRem = LastBar - BarNumber();
def High1950 = if !BarRem then Highest(high, length) else Double.NaN;
plot Line = if BarRem <= length then HighestAll(High1950) - HighestAll(High1950) * dAdjuster else Double.NaN;





def low1950 = if !BarRem then Lowest(low, length) else
Double.NaN;
plot line2 = if BarRem <= length then LowestAll(low1950) +
LowestAll(low1950) * dAdjuster
else Double.NaN;

def whichline = if AbsValue(close - High1950) < AbsValue(close - low1950) then 1
else 0;
AddLabel(yes, "whichline " + whichline);

#plot line3 = if whichline == 1 then line
# else line2;

#plot line3;
#switch (whichline)
# case 1:
# line3 = line;
#case 0:
# line3=line2;
#default:
# line3=0;
#

# if whichline == 1 then line2.hide()
# else line.hide();

input debug = yes;
AddLabel(debug, "Line" + " " + Line, Color.WHITE);
AddLabel(debug, "Line2" + " " + line2, Color.WHITE);
AddLabel( !BarRem <= length, Concat( "Range ", HighestAll(High1950) - HighestAll(High1950) * dAdjuster -
LowestAll(low1950) +
LowestAll(low1950) * dAdjuster));

def zrange = if !BarRem then HighestAll(High1950) - HighestAll(High1950) * dAdjuster -
LowestAll(low1950) +
LowestAll(low1950) * dAdjuster else Double.NaN;
First, try unchecking all of the items circled in chart settings, price axis. These are causing the compression of your price bars. Set the up/down expansion area to at least 5% for both also, so that when a line is 'close' then it more likely to show on your chart sooner.

Capture.jpg
 
I am modifying some code I previously wrote(with your wonderful help) to run on a 15 minute chart rather than a daily or weekly chart. The code plots the high and low of the past 90 days with a slight upwards or downwards adjustment of .15 up for the lower line and down for the upper line.
The problem I am having is that on a 15 minute chart, thinkorswim will display both lines and this will distort the size of the bars or candles on the chart. To get around the problem, I decided to only display one of the lines. So only the line closest to the current close of the 15 minute candle will be displayed. I introduced a variable "whichline" which holds the correct value. IF whichline=1, I only want to display the upper line and if whichline = 0, I only want to display the lower line. I tried using an "If whichline=1 then line2.hide". Next, I tried using "Def line and Def line2" instead of 2 plots. Doing this I thought to do a plot line3 which would plot the appropriate line. I also tried a switch statement based on whichline
having a value of 1 or 0. None of these attempts have worked. Can anyone help me out? Here is my code
Ruby:
#hint length of 1950 on 15 minute chart = 90 days of daily #data
input length = 1950;
input dAdjuster = .015;

def LastBar = HighestAll(if !IsNaN(close) then BarNumber() else Double.NaN);
def BarRem = LastBar - BarNumber();
def High1950 = if !BarRem then Highest(high, length) else Double.NaN;
plot Line = if BarRem <= length then HighestAll(High1950) - HighestAll(High1950) * dAdjuster else Double.NaN;





def low1950 = if !BarRem then Lowest(low, length) else
Double.NaN;
plot line2 = if BarRem <= length then LowestAll(low1950) +
LowestAll(low1950) * dAdjuster
else Double.NaN;

def whichline = if AbsValue(close - High1950) < AbsValue(close - low1950) then 1
else 0;
AddLabel(yes, "whichline " + whichline);

#plot line3 = if whichline == 1 then line
# else line2;

#plot line3;
#switch (whichline)
# case 1:
# line3 = line;
#case 0:
# line3=line2;
#default:
# line3=0;
#

# if whichline == 1 then line2.hide()
# else line.hide();

input debug = yes;
AddLabel(debug, "Line" + " " + Line, Color.WHITE);
AddLabel(debug, "Line2" + " " + line2, Color.WHITE);
AddLabel( !BarRem <= length, Concat( "Range ", HighestAll(High1950) - HighestAll(High1950) * dAdjuster -
LowestAll(low1950) +
LowestAll(low1950) * dAdjuster));

def zrange = if !BarRem then HighestAll(High1950) - HighestAll(High1950) * dAdjuster -
LowestAll(low1950) +
LowestAll(low1950) * dAdjuster else Double.NaN;

here is a different way to approach the problem.
this automatically turns off a 1950 line if it is more than x% from a highest/lowest line.
it has an input for a % ,
input percent_away_from_hilo = 5.0;
if the % difference from the highest level to the high1950 level, is less than the user input % value, the line is displayed.
..similar formulas for the lowest lines.
show bubbles on lines , on last bar. can turn off.
show labels of line price levels, %.

Code:
# remove_outer_lines_01

input percent_away_from_hilo = 5.0;
def per = percent_away_from_hilo/100;
addlabel(1, "line diff " + percent_away_from_hilo + "%" ,color.gray);

def na = double.nan;
def bn = barnumber();
#def hiz = if bn == 1 then high else if high > hiz[1] then high else hiz[1];
#def loz = if bn == 1 then low else if low < loz[1] then low else loz[1];
def hiz = highestall(high);
def loz = lowestall(low);

input show_highest_lowest = yes;
plot a = if (show_highest_lowest and !isnan(close))then hiz else na;
plot b = if (show_highest_lowest and !isnan(close)) then loz else na;

# day cnt is wrong. length of 1950 on 15 minute chart is not 90 days
# 390min in a day / 15min bars = 26 , 15min bars in a day
# 1950 / 26 = 75 days

input length = 1950;
input dAdjuster = .015;

def LastBar = HighestAll(if !IsNaN(close) then BarNumber() else Double.NaN);
def BarRem = LastBar - BarNumber();
def lastbar2 = if bn == lastbar then 1 else 0;

# high line ----
#def High1950 = if !BarRem then Highest(high, length) else Double.NaN;
def High1950 = if BarRem >= 0 then Highest(high, length) else Double.NaN;
#plot Line = if BarRem <= length then HighestAll(High1950) - HighestAll(High1950) * dAdjuster else Double.NaN;

def hi1950per = round(((high1950 - hiz)/hiz)*100,1);
def showhi = (high1950 - hiz) <= (hiz * per);
plot hix = if !showhi then na else high1950;
hix.setdefaultcolor(color.gray);
#plot e = high1950;

# low line ----
#def low1950 = if !BarRem then Lowest(low, length) else Double.NaN;
def low1950 = if BarRem >= 0 then Lowest(low, length) else Double.NaN;
#plot line2 = if BarRem <= length then LowestAll(low1950) + LowestAll(low1950) * dAdjuster else Double.NaN;

def lo1950per = round(((loz - low1950)/loz)*100,1);
def showlo = (loz - low1950) <= (loz * per);
plot lox = if !showlo then na else low1950;
lox.setdefaultcolor(color.gray);

# ------------------
#def whichline = if AbsValue(close - High1950) < AbsValue(close - low1950) then 1 else 0;
#AddLabel(yes, "whichline " + whichline);

input show_line_bubbles = yes;
addchartbubble(show_line_bubbles and showhi and lastbar2, High1950, "High1950: " + High1950 + " , " + hi1950per + "%" , color.yellow, no);
addchartbubble(show_line_bubbles and showlo and lastbar2, low1950, "Low1950: " + low1950 + " , " + lo1950per + "%" , color.orange, yes);

addchartbubble(show_line_bubbles and lastbar2, Hiz, "Highest " + Hiz, color.yellow, yes);
addchartbubble(show_line_bubbles and lastbar2, loz, "Lowest " + loz, color.orange, no);
# ---------------------
input show_line_labels = yes;
addlabel(show_line_labels, "High1950 " + High1950 + " | " + hi1950per + "%" + " above highest " + hiz, color.yellow);
addlabel(show_line_labels, "Low1950 " + low1950 + " | " + lo1950per + "%" + " below lowest " + loz, color.orange);

# ------ test data ------------------
input test1 = no;
addchartbubble(test1, low, bn + "\n" + barrem + "\n" + showhi + "\n" + (high1950 - hiz) + "\n" + (hiz * per), color.cyan, no);
#

cKIHrPk.jpg
 
Last edited:
So sorry that I didn't get back to you to say thank you.!! I've just been so busy, I completely forgot. Not a very good excuse, but the truth.

I will adjust my 1950 input number as well. I am looking for 90 calendar days so a 3 month high and 3 month low based on calendar days rather than trading days.
 
here is a different way to approach the problem.
this automatically turns off a 1950 line if it is more than x% from a highest/lowest line.
it has an input for a % ,
input percent_away_from_hilo = 5.0;
if the % difference from the highest level to the high1950 level, is less than the user input % value, the line is displayed.
..similar formulas for the lowest lines.
show bubbles on lines , on last bar. can turn off.
show labels of line price levels, %.

Code:
# remove_outer_lines_01

input percent_away_from_hilo = 5.0;
def per = percent_away_from_hilo/100;
addlabel(1, "line diff " + percent_away_from_hilo + "%" ,color.gray);

def na = double.nan;
def bn = barnumber();
#def hiz = if bn == 1 then high else if high > hiz[1] then high else hiz[1];
#def loz = if bn == 1 then low else if low < loz[1] then low else loz[1];
def hiz = highestall(high);
def loz = lowestall(low);

input show_highest_lowest = yes;
plot a = if (show_highest_lowest and !isnan(close))then hiz else na;
plot b = if (show_highest_lowest and !isnan(close)) then loz else na;

# day cnt is wrong. length of 1950 on 15 minute chart is not 90 days
# 390min in a day / 15min bars = 26 , 15min bars in a day
# 1950 / 26 = 75 days

input length = 1950;
input dAdjuster = .015;

def LastBar = HighestAll(if !IsNaN(close) then BarNumber() else Double.NaN);
def BarRem = LastBar - BarNumber();
def lastbar2 = if bn == lastbar then 1 else 0;

# high line ----
#def High1950 = if !BarRem then Highest(high, length) else Double.NaN;
def High1950 = if BarRem >= 0 then Highest(high, length) else Double.NaN;
#plot Line = if BarRem <= length then HighestAll(High1950) - HighestAll(High1950) * dAdjuster else Double.NaN;

def hi1950per = round(((high1950 - hiz)/hiz)*100,1);
def showhi = (high1950 - hiz) <= (hiz * per);
plot hix = if !showhi then na else high1950;
hix.setdefaultcolor(color.gray);
#plot e = high1950;

# low line ----
#def low1950 = if !BarRem then Lowest(low, length) else Double.NaN;
def low1950 = if BarRem >= 0 then Lowest(low, length) else Double.NaN;
#plot line2 = if BarRem <= length then LowestAll(low1950) + LowestAll(low1950) * dAdjuster else Double.NaN;

def lo1950per = round(((loz - low1950)/loz)*100,1);
def showlo = (loz - low1950) <= (loz * per);
plot lox = if !showlo then na else low1950;
lox.setdefaultcolor(color.gray);

# ------------------
#def whichline = if AbsValue(close - High1950) < AbsValue(close - low1950) then 1 else 0;
#AddLabel(yes, "whichline " + whichline);

input show_line_bubbles = yes;
addchartbubble(show_line_bubbles and showhi and lastbar2, High1950, "High1950: " + High1950 + " , " + hi1950per + "%" , color.yellow, no);
addchartbubble(show_line_bubbles and showlo and lastbar2, low1950, "Low1950: " + low1950 + " , " + lo1950per + "%" , color.orange, yes);

addchartbubble(show_line_bubbles and lastbar2, Hiz, "Highest " + Hiz, color.yellow, yes);
addchartbubble(show_line_bubbles and lastbar2, loz, "Lowest " + loz, color.orange, no);
# ---------------------
input show_line_labels = yes;
addlabel(show_line_labels, "High1950 " + High1950 + " | " + hi1950per + "%" + " above highest " + hiz, color.yellow);
addlabel(show_line_labels, "Low1950 " + low1950 + " | " + lo1950per + "%" + " below lowest " + loz, color.orange);

# ------ test data ------------------
input test1 = no;
addchartbubble(test1, low, bn + "\n" + barrem + "\n" + showhi + "\n" + (high1950 - hiz) + "\n" + (hiz * per), color.cyan, no);
#

cKIHrPk.jpg
Would you have the Shared file ?
 
You can use aggregationPeriod to plot the daily levels on lower timeframes as follows

Code:
# Paints a basic horizontal price level with no bells and whistles at market
input aggregationPeriod = AggregationPeriod.DAY;
input barsBack = 65;

def c = if !IsNaN(close) and IsNaN(close[-1])
        then close
        else c[1];

plot priceLine = if isNaN(close[-barsBack])
            then c[-barsBack]
            else Double.NaN;

priceLine.SetDefaultColor(Color.WHITE);
priceLine.SetStyle(CURVE.FIRM);
priceLine.SetLineWeight(1);

# END PriceLine

# Paints a basic horizontal price level with no bells and whistles at highest high of barsBack
def h = if !IsNaN(high) and IsNaN(high[-1])
        then highest(high(period = aggregationPeriod), barsBack)
        else h[1];

plot hbar = if isNaN(high[-barsBack])
            then h[-barsBack]
            else Double.NaN;

hbar.SetDefaultColor(Color.DARK_RED);
hbar.SetStyle(CURVE.FIRM);
hbar.SetLineWeight(1);

# END hbar

# Paints a basic horizontal price level with no bells and whistles at lowest low of barsBack
def l = if !IsNaN(low) and IsNaN(low[-1])
        then lowest(low(period = aggregationPeriod), barsBack)
        else l[1];

plot lbar = if isNaN(low[-barsBack])
            then l[-barsBack]
            else Double.NaN;

lbar.SetDefaultColor(Color.DARK_GREEN);
lbar.SetStyle(CURVE.FIRM);
lbar.SetLineWeight(1);

# END lbar
# E.O.F.
 
Last edited:

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

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