How to get the offset value of the first of the last so many times a condition occurred?

Jman831

Member
I'm essentially trying to get the offset value of the first "peak" that occurred out of the last so many "peaks" that occurred of a moving average, but I'm having a hard time figuring out how to go about that. I feel like there's a simple solution to this that I just can't seem to pinpoint. Please refer to the code below:

Code:
input length = 12;

def avg = MovingAverage(averageType.SIMPLE, close, length);
def avgpeak = avg < avg[1] and avg[1] > avg[2];
def avgpeakprice = if avgpeak then avg[1] else 0;

What I want to do is to make an average out of the "avgpeakprice"s. So let's say I want an average price of the last 5 "avgpeakprice"s. In my mind, this means I need to somehow get the offset value of the first of the last 5 "avgpeak"s that occurred so I can use the offset value to add up all of the "avgpeakprice"s of the last 5 "avgpeak"s using the Sum function. I'd then divide the sum of the last 5 "avgpeakprice"s by 5 to get the average I'm looking for:

Code:
def peakpriceaverage = sum(avgpeakprice, <offset value of the first of the last 5 avgpeaks>) / 5;

I feel like I'm overthinking or overcomplicating something and I'll honestly be surprised if there isn't someone out there who can find a simple solution to my issue. I'm fairly certain I'm going to have a big "DUH" moment as soon as someone answers my question.
 
I'm essentially trying to get the offset value of the first "peak" that occurred out of the last so many "peaks" that occurred of a moving average, but I'm having a hard time figuring out how to go about that. I feel like there's a simple solution to this that I just can't seem to pinpoint. Please refer to the code below:

Code:
input length = 12;

def avg = MovingAverage(averageType.SIMPLE, close, length);
def avgpeak = avg < avg[1] and avg[1] > avg[2];
def avgpeakprice = if avgpeak then avg[1] else 0;

What I want to do is to make an average out of the "avgpeakprice"s. So let's say I want an average price of the last 5 "avgpeakprice"s. In my mind, this means I need to somehow get the offset value of the first of the last 5 "avgpeak"s that occurred so I can use the offset value to add up all of the "avgpeakprice"s of the last 5 "avgpeak"s using the Sum function. I'd then divide the sum of the last 5 "avgpeakprice"s by 5 to get the average I'm looking for:

Code:
def peakpriceaverage = sum(avgpeakprice, <offset value of the first of the last 5 avgpeaks>) / 5;

I feel like I'm overthinking or overcomplicating something and I'll honestly be surprised if there isn't someone out there who can find a simple solution to my issue. I'm fairly certain I'm going to have a big "DUH" moment as soon as someone answers my question.

like many people with an idea, you are jumping around with your thoughts and guessing at functions to use, before you define the tasks to do.
you didn't explain what you want to do with these numbers. what do you want to see? a label? a line?
what you want, determines how and when to collect the data.

asking these 3 things will help steer your project.
..where - on a chart
..what - ? a line ? a label ?
..when - a line spanning the last 5 peaks? the last 5 bars ?


if you want an average of several values, then your first paragraph is irrelevent. it doesn't matter where the first in a group is. you just need a way to look at previous bars until you have found the desired quantity of signals. then add the values as you find them. then divide the total by the quantity to get an average.
sum() looks at many bars, so you might read from 50 bars and divide by 5, which would be wrong. might be able to use an if then to supply data to sum(), but the length will always be different, and i don't think thinkscript will allow a variable for sum length.
avgavg = sum( (if peak then avg alse 0), length ) / 5

--------------

what i did,
define peaks on an average
count them
create a reverse count
if the reverse count <= the peak quantity then thet are the last 5 peaks, process them.
add up the 5 peak values then /5, to get an average

draw a horizontal line at the average level


Code:
# avg_of_prev_x_peaks_01_rev

#https://usethinkscript.com/threads/how-to-get-the-offset-value-of-the-first-of-the-last-so-many-times-a-condition-occurred.16392/

def na = double.nan;
def bn = barnumber();

def lastbn = HighestAll(If(IsNaN(close), 0, bn));
def lastbar = if (bn == lastbn) then 1 else 0;
#def lastbar = !isnan(close[0]) and isnan(close[-1]);

def price = close;

input peak_qtys = 5;
input avg1_len = 12;
#input ma1_type =  AverageType.EXPONENTIAL;
input avg1_type = AverageType.simple;
def avg1 = MovingAverage(avg1_type, price, avg1_len);

input show_avg = yes;
plot z1 = if show_avg then avg1 else na;
z1.setdefaultcolor(color.light_gray);
#z1.setlineweight(1);
z1.hidebubble();


# avg peaks , ref is middle bar , 1 bar on each side
#def avgpeak = avg1[1] < avg1[0] and avg1[0] > avg1[-1];
def avgpeak = if lastbar then 0 else (avg1[1] < avg1[0] and avg1[0] > avg1[-1]);
# ref 3rd bar ,  low, high, low , bar after peak
#def avgpeak = avg1[2] < avg1[1] and avg1[1] > avg1[0];
def t = 0;

# count the peaks
def avgpeakcnt = if bn == 1 then 1
 else if avgpeak[t] then avgpeakcnt[1] + 1
 else avgpeakcnt[1];

def maxcnt = highestall(avgpeakcnt);
def revcnt = maxcnt - avgpeakcnt + 1;

# define the group of bars that include x peaks
def ispeaks = (avgpeak[t] and revcnt <= peak_qtys);

def peakrange = (revcnt <= peak_qtys);

def avgtotal = if bn == 1 then 0 
 else if lastbar then avgtotal[1]
 else if ispeaks then round(avgtotal[1] + avg1, 2)
 else avgtotal[1];

def avgavg = round(avgtotal / peak_qtys, 2);

def avgavg2 = highestall(if lastbar then avgavg else 0);


plot za = if peakrange then avgavg2 else na;
za.setdefaultcolor(color.cyan);
za.setlineweight(2);
#za.hidebubble();


addlabel(1, " ", color.black);
addlabel(0, peak_qtys + " peaks", color.yellow);
addlabel(1, avgavg2 + " average of the last " + peak_qtys + " peaks, on an average", color.yellow);

addlabel(1, " ", color.black);


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

input test1_peaks = yes;
addchartbubble(test1_peaks and avgpeak[t], high,
revcnt
, (if peakrange then color.yellow else color.gray), yes);


input test2_avg = no;
#addchartbubble(test2_avg and (revcnt <= peak_qtys), low,
addchartbubble(test2_avg, low,
revcnt + "\n" +
peak_qtys + "\n" +
avgavg2 + "\n" +
ispeaks + "\n" +
za
, (if ispeaks then color.yellow else color.gray), no);
#, color.yellow, no);


# peak data
input test1_peak_cnts = no;
addchartbubble(test1_peak_cnts and avgpeak[t], avg1,
 avg1 + "\n" +
 avgpeak[t] + "\n" +
 avgtotal + "\n" +
 avgavg + "\n\n" +
 avgpeakcnt + "\n" +
 maxcnt + "\n" +
 revcnt 
, (if ispeaks then color.yellow else color.gray), yes);
#

MRNA 15min
find 5 peaks on an average line
blue line - average of those 5 peaks
MSKQjzj.jpg
 
like many people with an idea, you are jumping around with your thoughts and guessing at functions to use, before you define the tasks to do.
you didn't explain what you want to do with these numbers. what do you want to see? a label? a line?
what you want, determines how and when to collect the data.

asking these 3 things will help steer your project.
..where - on a chart
..what - ? a line ? a label ?
..when - a line spanning the last 5 peaks? the last 5 bars ?


if you want an average of several values, then your first paragraph is irrelevent. it doesn't matter where the first in a group is. you just need a way to look at previous bars until you have found the desired quantity of signals. then add the values as you find them. then divide the total by the quantity to get an average.
sum() looks at many bars, so you might read from 50 bars and divide by 5, which would be wrong. might be able to use an if then to supply data to sum(), but the length will always be different, and i don't think thinkscript will allow a variable for sum length.
avgavg = sum( (if peak then avg alse 0), length ) / 5

--------------

what i did,
define peaks on an average
count them
create a reverse count
if the reverse count <= the peak quantity then thet are the last 5 peaks, process them.
add up the 5 peak values then /5, to get an average

draw a horizontal line at the average level


Code:
# avg_of_prev_x_peaks_01_rev

#https://usethinkscript.com/threads/how-to-get-the-offset-value-of-the-first-of-the-last-so-many-times-a-condition-occurred.16392/

def na = double.nan;
def bn = barnumber();

def lastbn = HighestAll(If(IsNaN(close), 0, bn));
def lastbar = if (bn == lastbn) then 1 else 0;
#def lastbar = !isnan(close[0]) and isnan(close[-1]);

def price = close;

input peak_qtys = 5;
input avg1_len = 12;
#input ma1_type =  AverageType.EXPONENTIAL;
input avg1_type = AverageType.simple;
def avg1 = MovingAverage(avg1_type, price, avg1_len);

input show_avg = yes;
plot z1 = if show_avg then avg1 else na;
z1.setdefaultcolor(color.light_gray);
#z1.setlineweight(1);
z1.hidebubble();


# avg peaks , ref is middle bar , 1 bar on each side
#def avgpeak = avg1[1] < avg1[0] and avg1[0] > avg1[-1];
def avgpeak = if lastbar then 0 else (avg1[1] < avg1[0] and avg1[0] > avg1[-1]);
# ref 3rd bar ,  low, high, low , bar after peak
#def avgpeak = avg1[2] < avg1[1] and avg1[1] > avg1[0];
def t = 0;

# count the peaks
def avgpeakcnt = if bn == 1 then 1
 else if avgpeak[t] then avgpeakcnt[1] + 1
 else avgpeakcnt[1];

def maxcnt = highestall(avgpeakcnt);
def revcnt = maxcnt - avgpeakcnt + 1;

# define the group of bars that include x peaks
def ispeaks = (avgpeak[t] and revcnt <= peak_qtys);

def peakrange = (revcnt <= peak_qtys);

def avgtotal = if bn == 1 then 0 
 else if lastbar then avgtotal[1]
 else if ispeaks then round(avgtotal[1] + avg1, 2)
 else avgtotal[1];

def avgavg = round(avgtotal / peak_qtys, 2);

def avgavg2 = highestall(if lastbar then avgavg else 0);


plot za = if peakrange then avgavg2 else na;
za.setdefaultcolor(color.cyan);
za.setlineweight(2);
#za.hidebubble();


addlabel(1, " ", color.black);
addlabel(0, peak_qtys + " peaks", color.yellow);
addlabel(1, avgavg2 + " average of the last " + peak_qtys + " peaks, on an average", color.yellow);

addlabel(1, " ", color.black);


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

input test1_peaks = yes;
addchartbubble(test1_peaks and avgpeak[t], high,
revcnt
, (if peakrange then color.yellow else color.gray), yes);


input test2_avg = no;
#addchartbubble(test2_avg and (revcnt <= peak_qtys), low,
addchartbubble(test2_avg, low,
revcnt + "\n" +
peak_qtys + "\n" +
avgavg2 + "\n" +
ispeaks + "\n" +
za
, (if ispeaks then color.yellow else color.gray), no);
#, color.yellow, no);


# peak data
input test1_peak_cnts = no;
addchartbubble(test1_peak_cnts and avgpeak[t], avg1,
 avg1 + "\n" +
 avgpeak[t] + "\n" +
 avgtotal + "\n" +
 avgavg + "\n\n" +
 avgpeakcnt + "\n" +
 maxcnt + "\n" +
 revcnt 
, (if ispeaks then color.yellow else color.gray), yes);
#

MRNA 15min
find 5 peaks on an average line
blue line - average of those 5 peaks
MSKQjzj.jpg

I need to inspect the code you provided more closely at a later time, but I think you may have answered my question and found a solution to my issue as the last paragraph before the code provided essentially describes what I was going for.
 
@halcyonguy That's essentially what I was trying to do was to a plot a line that defines the average price of X amount of previous peaks defined by the user. The same would be done for previous troughs. This way you'd essentially be able to define a price range between the average of peaks and the average of troughs to more safely trade within, using the trough average as a fair price estimate to buy and the average peak as a fair price estimate to sell. How it's displayed doesn't matter so much. What matters is what the price of each average is. My preference would be to have two horizonal lines like the one provided in your screenshot that together defines the range to trade within.
 
@halcyonguy That's essentially what I was trying to do was to a plot a line that defines the average price of X amount of previous peaks defined by the user. The same would be done for previous troughs. This way you'd essentially be able to define a price range between the average of peaks and the average of troughs to more safely trade within, using the trough average as a fair price estimate to buy and the average peak as a fair price estimate to sell. How it's displayed doesn't matter so much. What matters is what the price of each average is. My preference would be to have two horizonal lines like the one provided in your screenshot that together defines the range to trade within.

find 2 average price levels, from a group of peaks and a group of valleys.

choose how many peaks/valleys to find (default is 5)
choose the data source, average line (default) or highs and lows,
choose to include last bar or not
find peaks and valleys on the chosen data,
..peaks are based on the current bar > (1 bar before and 1 bar after)
..valleys are based on the current bar < (1 bar before and 1 bar after)
..2 labels display the prices and data type
dots are plotted at data points. yellow for peaks, cyan for valleys.

Code:
# avg_of_prev_x_peaksvalleys_02

#https://usethinkscript.com/threads/how-to-get-the-offset-value-of-the-first-of-the-last-so-many-times-a-condition-occurred.16392/
#How to get the offset value of the first of the last so many times a condition occurred?

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

def na = double.nan;
def bn = barnumber();

def lastbn = HighestAll(If(IsNaN(close), 0, bn));
def lastbar = if (bn == lastbn) then 1 else 0;
#def lastbar = !isnan(close[0]) and isnan(close[-1]);

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

input qty_peaks_valleys = 5;
input price_data = { default average , high_low };
input last_bar_can_be_peakvalley = yes;

#----------------------
# data - average

def price = close;
input avg1_len = 12;
#input ma1_type =  AverageType.EXPONENTIAL;
input avg1_type = AverageType.simple;
def avg1 = MovingAverage(avg1_type, price, avg1_len);

input show_avg_line = yes;
plot z1 = if show_avg_line then avg1 else na;
z1.setdefaultcolor(color.light_gray);
#z1.setlineweight(1);
z1.hidebubble();

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

# choose price levels to analyze,  avg, close,...
#def peakdata = avg1;
#def valleydata = avg1;
#def peakdata = high;
#def valleydata = low;

#input price_data = { default average , high_low };
def peakdata;
def valleydata;
def datatype;
if price_data == price_data.average then {
 peakdata = avg1;
 valleydata = avg1;
 datatype = 1;
} else if price_data == price_data.high_low then {
 peakdata = high;
 valleydata = low;
 datatype = 2;
} else {
 peakdata = na;
 valleydata = na;
 datatype = 0;
}


def t = 0;

#---------------------------
# peak data

def peak = (peakdata[1] < peakdata[0] and peakdata[0] > peakdata[-1]);
def peaklast = if !last_bar_can_be_peakvalley then 0
 else if lastbar and peakdata > peakdata[1] then 1
 else 0;
def peak2 = if lastbar then peaklast else peak;

# count the peaks
def avgpeakcnt = if bn == 1 then 1
 else if peak2[t] then avgpeakcnt[1] + 1
 else avgpeakcnt[1];

def pkmaxcnt = highestall(avgpeakcnt);
def pkrevcnt = pkmaxcnt - avgpeakcnt + 1;

# define the group of bars that include x peaks
def ispeaks = (peak2[t] and pkrevcnt <= qty_peaks_valleys);

def peakrange = (pkrevcnt <= qty_peaks_valleys);

def pkavgtotal = if bn == 1 then 0
# else if lastbar then avgtotal[1]
 else if lastbar and peaklast then pkavgtotal[1] + peakdata
 else if ispeaks then round(pkavgtotal[1] + peakdata, 2)
 else pkavgtotal[1];

def pkavgavg = round(pkavgtotal / qty_peaks_valleys, 2);
def pkavgavg2 = highestall(if lastbar then pkavgavg else 0);

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

plot zpk = if peakrange then pkavgavg2 else na;
zpk.setdefaultcolor(color.cyan);
zpk.setlineweight(2);
#zpk.hidebubble();

addlabel(1, " ", color.black);
#addlabel(0, qty_peaks_valleys + " peaks", color.yellow);
addlabel(1, pkavgavg2 + " average of the last " + qty_peaks_valleys + " peaks, on " + (if datatype == 1 then "an average" else "highs"), color.yellow);

addlabel(1, " ", color.black);

#---------------------------
#---------------------------
# valley data

def valley = (valleydata[1] > valleydata[0] and valleydata[0] < valleydata[-1]);

def valleylast = if !last_bar_can_be_peakvalley then 0
 else if lastbar and valleydata < valleydata[1] then 1
 else 0;

def valley2 = if lastbar then valleylast else valley;
#def t = 0;

# count the peaks
def avgvalleycnt = if bn == 1 then 1
 else if valley2[t] then avgvalleycnt[1] + 1
 else avgvalleycnt[1];

def valmaxcnt = highestall(avgvalleycnt);
def valrevcnt = valmaxcnt - avgvalleycnt + 1;

# define the group of bars that include x peaks
def isvalleys = (valley2[t] and valrevcnt <= qty_peaks_valleys);

def valleyrange = (valrevcnt <= qty_peaks_valleys);

def valavgtotal = if bn == 1 then 0
# else if lastbar then avgtotal[1]
 else if lastbar and valleylast then valavgtotal[1] + valleydata
 else if isvalleys then round(valavgtotal[1] + valleydata, 2)
 else valavgtotal[1];

def valavgavg = round(valavgtotal / qty_peaks_valleys, 2);
def valavgavg2 = highestall(if lastbar then valavgavg else 0);

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

plot zval = if valleyrange then valavgavg2 else na;
zval.setdefaultcolor(color.cyan);
zval.setlineweight(2);
#zval.hidebubble();

addlabel(1, " ", color.black);
#addlabel(0, qty_peaks_valleys + " valleys", color.yellow);
addlabel(1, valavgavg2 + " average of the last " + qty_peaks_valleys + " valleys, on " + (if datatype == 1 then "an average" else "lows"), color.yellow);

addlabel(1, " ", color.black);

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

input show_peak_dots = yes;
plot zpd = if peak2[t] and peakrange then peakdata else na;
zpd.SetPaintingStrategy(PaintingStrategy.POINTS);
zpd.SetDefaultColor(Color.yellow);
zpd.setlineweight(3);
zpd.hidebubble();

input show_valley_dots = yes;
plot zvd = if valley2[t] and valleyrange then valleydata else na;
zvd.SetPaintingStrategy(PaintingStrategy.POINTS);
zvd.SetDefaultColor(Color.cyan);
zvd.setlineweight(3);
zvd.hidebubble();


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

input test1_peaks = no;
addchartbubble(test1_peaks and peak2[t], peakdata,
pkrevcnt + "\n" +
peakdata
, (if peakrange then color.yellow else color.gray), yes);


input test2_peakdata = no;
#addchartbubble(test2_avg and (revcnt <= peak_qtys), low,
addchartbubble(test2_peakdata, peakdata,
pkrevcnt + "\n" +
qty_peaks_valleys + "\n" +
pkavgavg2 + "\n" +
ispeaks + "\n" +
zpk
, (if ispeaks then color.yellow else color.gray), no);
#, color.yellow, no);


# peak data
input test1_peak_cnts = no;
addchartbubble(test1_peak_cnts and peak2[t], peakdata,
 peakdata + "\n" +
 peak2[t] + "\n" +
 pkavgtotal + "\n" +
 pkavgavg + "\n\n" +
 avgpeakcnt + "\n" +
 pkmaxcnt + "\n" +
 pkrevcnt
, (if ispeaks then color.yellow else color.gray), yes);


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

input test1_valleys = no;
addchartbubble(test1_valleys and valley2[t], valleydata,
valrevcnt + "\n" +
valleydata
, (if valleyrange then color.cyan else color.gray), no);


input test2_valleydata = no;
#addchartbubble(test2_avg and (revcnt <= peak_qtys), low,
addchartbubble(test2_valleydata, valleydata,
valrevcnt + "\n" +
qty_peaks_valleys + "\n" +
valavgavg2 + "\n" +
isvalleys + "\n" +
zval + "\n" +
 valleydata + "\n" +
 valley2[t] + "\n"
, (if isvalleys then color.cyan else color.gray), no);
#, color.yellow, no);


# peak data
input test1_valley_cnts = no;
addchartbubble(test1_valley_cnts and valley2[t], valleydata,
 valleydata + "\n" +
 valley2[t] + "\n" +
 valavgtotal + "\n" +
 valavgavg + "\n\n" +
 avgvalleycnt + "\n" +
 valmaxcnt + "\n" +
 valrevcnt
, (if isvalleys then color.cyan else color.gray), yes);

#

PM 15min
5 peaks , valleys.
data from an average line
include last bar , yes
qfBrN1Q.jpg



PM 15min
5 peaks , valleys
data from high, low
xr4ghOv.jpg
 
Last edited:
find 2 average price levels, from a group of peaks and a group of valleys.

choose how many peaks/valleys to find (default is 5)
choose the data source, average line (default) or highs and lows,
choose to include last bar or not
find peaks and valleys on the chosen data,
..peaks are based on the current bar > (1 bar before and 1 bar after)
..valleys are based on the current bar < (1 bar before and 1 bar after)
..2 labels display the prices and data type
dots are plotted at data points. yellow for peaks, cyan for valleys.

Code:
# avg_of_prev_x_peaksvalleys_02

#https://usethinkscript.com/threads/how-to-get-the-offset-value-of-the-first-of-the-last-so-many-times-a-condition-occurred.16392/
#How to get the offset value of the first of the last so many times a condition occurred?

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

def na = double.nan;
def bn = barnumber();

def lastbn = HighestAll(If(IsNaN(close), 0, bn));
def lastbar = if (bn == lastbn) then 1 else 0;
#def lastbar = !isnan(close[0]) and isnan(close[-1]);

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

input qty_peaks_valleys = 5;
input price_data = { default average , high_low };
input last_bar_can_be_peakvalley = yes;

#----------------------
# data - average

def price = close;
input avg1_len = 12;
#input ma1_type =  AverageType.EXPONENTIAL;
input avg1_type = AverageType.simple;
def avg1 = MovingAverage(avg1_type, price, avg1_len);

input show_avg_line = yes;
plot z1 = if show_avg_line then avg1 else na;
z1.setdefaultcolor(color.light_gray);
#z1.setlineweight(1);
z1.hidebubble();

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

# choose price levels to analyze,  avg, close,...
#def peakdata = avg1;
#def valleydata = avg1;
#def peakdata = high;
#def valleydata = low;

#input price_data = { default average , high_low };
def peakdata;
def valleydata;
def datatype;
if price_data == price_data.average then {
 peakdata = avg1;
 valleydata = avg1;
 datatype = 1;
} else if price_data == price_data.high_low then {
 peakdata = high;
 valleydata = low;
 datatype = 2;
} else {
 peakdata = na;
 valleydata = na;
 datatype = 0;
}


def t = 0;

#---------------------------
# peak data

def peak = (peakdata[1] < peakdata[0] and peakdata[0] > peakdata[-1]);
def peaklast = if !last_bar_can_be_peakvalley then 0
 else if lastbar and peakdata > peakdata[1] then 1
 else 0;
def peak2 = if lastbar then peaklast else peak;

# count the peaks
def avgpeakcnt = if bn == 1 then 1
 else if peak2[t] then avgpeakcnt[1] + 1
 else avgpeakcnt[1];

def pkmaxcnt = highestall(avgpeakcnt);
def pkrevcnt = pkmaxcnt - avgpeakcnt + 1;

# define the group of bars that include x peaks
def ispeaks = (peak2[t] and pkrevcnt <= qty_peaks_valleys);

def peakrange = (pkrevcnt <= qty_peaks_valleys);

def pkavgtotal = if bn == 1 then 0
# else if lastbar then avgtotal[1]
 else if lastbar and peaklast then pkavgtotal[1] + peakdata
 else if ispeaks then round(pkavgtotal[1] + peakdata, 2)
 else pkavgtotal[1];

def pkavgavg = round(pkavgtotal / qty_peaks_valleys, 2);
def pkavgavg2 = highestall(if lastbar then pkavgavg else 0);

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

plot zpk = if peakrange then pkavgavg2 else na;
zpk.setdefaultcolor(color.cyan);
zpk.setlineweight(2);
#zpk.hidebubble();

addlabel(1, " ", color.black);
#addlabel(0, qty_peaks_valleys + " peaks", color.yellow);
addlabel(1, pkavgavg2 + " average of the last " + qty_peaks_valleys + " peaks, on " + (if datatype == 1 then "an average" else "highs"), color.yellow);

addlabel(1, " ", color.black);

#---------------------------
#---------------------------
# valley data

def valley = (valleydata[1] > valleydata[0] and valleydata[0] < valleydata[-1]);

def valleylast = if !last_bar_can_be_peakvalley then 0
 else if lastbar and valleydata < valleydata[1] then 1
 else 0;

def valley2 = if lastbar then valleylast else valley;
#def t = 0;

# count the peaks
def avgvalleycnt = if bn == 1 then 1
 else if valley2[t] then avgvalleycnt[1] + 1
 else avgvalleycnt[1];

def valmaxcnt = highestall(avgvalleycnt);
def valrevcnt = valmaxcnt - avgvalleycnt + 1;

# define the group of bars that include x peaks
def isvalleys = (valley2[t] and valrevcnt <= qty_peaks_valleys);

def valleyrange = (valrevcnt <= qty_peaks_valleys);

def valavgtotal = if bn == 1 then 0
# else if lastbar then avgtotal[1]
 else if lastbar and valleylast then valavgtotal[1] + valleydata
 else if isvalleys then round(valavgtotal[1] + valleydata, 2)
 else valavgtotal[1];

def valavgavg = round(valavgtotal / qty_peaks_valleys, 2);
def valavgavg2 = highestall(if lastbar then valavgavg else 0);

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

plot zval = if valleyrange then valavgavg2 else na;
zval.setdefaultcolor(color.cyan);
zval.setlineweight(2);
#zval.hidebubble();

addlabel(1, " ", color.black);
#addlabel(0, qty_peaks_valleys + " valleys", color.yellow);
addlabel(1, valavgavg2 + " average of the last " + qty_peaks_valleys + " valleys, on " + (if datatype == 1 then "an average" else "lows"), color.yellow);

addlabel(1, " ", color.black);

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

input show_peak_dots = yes;
plot zpd = if peak2[t] and peakrange then peakdata else na;
zpd.SetPaintingStrategy(PaintingStrategy.POINTS);
zpd.SetDefaultColor(Color.yellow);
zpd.setlineweight(3);
zpd.hidebubble();

input show_valley_dots = yes;
plot zvd = if valley2[t] and valleyrange then valleydata else na;
zvd.SetPaintingStrategy(PaintingStrategy.POINTS);
zvd.SetDefaultColor(Color.cyan);
zvd.setlineweight(3);
zvd.hidebubble();


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

input test1_peaks = no;
addchartbubble(test1_peaks and peak2[t], peakdata,
pkrevcnt + "\n" +
peakdata
, (if peakrange then color.yellow else color.gray), yes);


input test2_peakdata = no;
#addchartbubble(test2_avg and (revcnt <= peak_qtys), low,
addchartbubble(test2_peakdata, peakdata,
pkrevcnt + "\n" +
qty_peaks_valleys + "\n" +
pkavgavg2 + "\n" +
ispeaks + "\n" +
zpk
, (if ispeaks then color.yellow else color.gray), no);
#, color.yellow, no);


# peak data
input test1_peak_cnts = no;
addchartbubble(test1_peak_cnts and peak2[t], peakdata,
 peakdata + "\n" +
 peak2[t] + "\n" +
 pkavgtotal + "\n" +
 pkavgavg + "\n\n" +
 avgpeakcnt + "\n" +
 pkmaxcnt + "\n" +
 pkrevcnt
, (if ispeaks then color.yellow else color.gray), yes);


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

input test1_valleys = no;
addchartbubble(test1_valleys and valley2[t], valleydata,
valrevcnt + "\n" +
valleydata
, (if valleyrange then color.cyan else color.gray), no);


input test2_valleydata = no;
#addchartbubble(test2_avg and (revcnt <= peak_qtys), low,
addchartbubble(test2_valleydata, valleydata,
valrevcnt + "\n" +
qty_peaks_valleys + "\n" +
valavgavg2 + "\n" +
isvalleys + "\n" +
zval + "\n" +
 valleydata + "\n" +
 valley2[t] + "\n"
, (if isvalleys then color.cyan else color.gray), no);
#, color.yellow, no);


# peak data
input test1_valley_cnts = no;
addchartbubble(test1_valley_cnts and valley2[t], valleydata,
 valleydata + "\n" +
 valley2[t] + "\n" +
 valavgtotal + "\n" +
 valavgavg + "\n\n" +
 avgvalleycnt + "\n" +
 valmaxcnt + "\n" +
 valrevcnt
, (if isvalleys then color.cyan else color.gray), yes);

#

PM 15min
5 peaks , valleys.
data from an average line
qfBrN1Q.jpg



PM 15min
5 peaks , valleys
data from high, low
xr4ghOv.jpg

Precisely what I was going for, can't thank you enough! Well done!
 

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