ProRealCode - Trading & Coding with ProRealTime™
the below version checks if there is at least 1 bar between 2 points.
defparam drawonlastbaronly=false
if day<>day[1] or intradaybarindex=0 then
unset($peak)
unset($peakbar)
unset($trough)
unset($troughbar)
i=0
j=0
endif
Peak1 = (high[3] >= high[4]) AND (high[3] > high[5]) AND (high[3] > high[6])
Peak2 = (high[3] >= high[2]) AND (high[3] > high[1]) AND (high[3] > high[0])
Peak = Peak1 AND Peak2
if peak then
// drawpoint(barindex[3],high[3],2) coloured("cyan")
$peak[i]=high[3]
$peakbar[i]=barindex[3]
i=i+1
endif
Trough1 = (low[3] <= low[4]) AND (low[3] < low[5]) AND (low[3] < low[6])
Trough2 = (low[3] <= low[2]) AND (low[3] < low[1]) AND (low[3] < low[0])
Trough = Trough1 AND Trough2
if Trough then
//drawpoint(barindex[3],low[3],2) coloured("crimson")
$trough[j]=low[3]
$troughbar[j]=barindex[3]
j=j+1
endif
if islastbarupdate then
if i>0 then
hhcount=0
for k = 0 to i-1 do
drawpoint($peakbar[k], $peak[k],2) coloured("cyan")
for l = 0 to i-1 do
if $peakbar[l]<>$peakbar[k] and abs($peakbar[l]-$peakbar[k])>1 then
diff = abs(round($peak[l],2) - round($peak[k],2))
if diff = 0 then //equal price
//find breakout
period = max(2,max($peakbar[l],$peakbar[k]) - min($peakbar[l],$peakbar[k]))
decay = max(1,barindex-max($peakbar[l],$peakbar[k]))
hh = highest[period](high)[decay]
if hh<=max($peak[l],$peak[k]) then //no breakout at that time
drawsegment($peakbar[l],$peak[l], $peakbar[k], $peak[k]) coloured("cyan")
currPeriod = max(2,barindex-max($peakbar[l],$peakbar[k]))
currHH = highest[max(1,currPeriod)](high)
//test if no broken since (real time)
if currHH<=max($peak[l],$peak[k]) then //no breakout since
drawsegment($peakbar[l],$peak[l], barindex, $peak[l]) coloured("cyan") style(dottedline4)
//drawtext("!",$peakbar[l],$peak[l]+averagetruerange[14], dialog,bold, 22)
hhcount=hhcount+1
endif
endif
endif
endif
next
next
endif
if j>0 then
llcount=0
for k = 0 to j-1 do
drawpoint($troughbar[k], $trough[k],2) coloured("crimson")
for l = 0 to i-1 do
if $troughbar[l]<>$troughbar[k] and abs($troughbar[l]-$troughbar[k])>1 then
diff = abs(round($trough[l],2) - round($trough[k],2))
if diff = 0 then //equal price
//find breakout
period = max(2,max($troughbar[l],$troughbar[k]) - min($troughbar[l],$troughbar[k]))
decay = max(1,barindex-max($troughbar[l],$troughbar[k]))
ll = lowest[period](low)[decay]
if ll>=min($trough[l],$trough[k]) then //no breakout at that time
drawsegment($troughbar[l],$trough[l], $troughbar[k], $trough[k]) coloured("crimson")
currPeriod = max(2,barindex-max($peakbar[l],$peakbar[k]))
currLL = lowest[currPeriod](low)
//test if no broken since (real time)
if currLL>=min($trough[l],$trough[k]) then //no breakout since
drawsegment($troughbar[l],$trough[l], barindex, $trough[l]) coloured("crimson") style(dottedline4)
llcount=llcount+1
endif
endif
endif
endif
next
next
endif
endif
return hhcount as "unbroken highs count", llcount as "unbroken lows count"
yes, it work perfectly
on some stock i have noticed the same eror appeas. I have attached screenshot
Besides that, I think there is nothing to add more
This is an internal platform error I can’t get rid off. I made a ticket for this, waiting for reply.
Thanks for this work
Yea, that is rare, and i have noticed that it’s on ticker with lov volume, where charts choppy
Hi Nicolas,
I have a question about turning indicator into a ProScreener
The problem I ran into:
$peak[], $peakbar[], $trough[], $troughbar[] and nested loops over all stored swings to find all equal‑price pairs and check whether they were broken or not. but ProScreener does not seem to accept array variables with $ or the UNSET instruction at all.$peak, $trough, etc.) into a ProScreener, the editor throws syntax errors (“unauthorized character / missing parenthesis”) exactly on the lines where $ arrays or UNSET $peak are used. So I cannot reproduce the same “store all swings and compare every swing with every other swing” logic inside ProScreener.Do you have anny sugestions? thanks in advance
Try the attached screener, it uses CALL instruction of the indicator. Not tested.
I didn’t know that was possible, but it seems to work great.
Thank you very much
Great to know. Is it possible to post some examples of successful found of the screener?
Also, how do you use those detection in trading? Waiting for breakouts? Only in stocks market? Thanks for sharing.
Sure.
For now, it’s only for stocks — I plan to try it on crypto later. The logic will need to be adjusted since some coins can have very low prices (for example, 0.00032).
Previously, the screener was returning too many results, mostly from choppy charts. So, I added filters to exclude stocks with a small 1‑minute range, less than 1M volume, or a price under $1.
I also changed the alert condition — now it triggers only when the current price actually touches equal swing highs or lows.
Today’s NFLX example after hours is when it triggered and i dont have more screenshot as market is closed.
I use this for breakouts when the right chart pattern is here.
One good example of such breakout today also was on NFLX
( atached both screensshots)
Thanks, that’s very interesting. I found an error in the swing detection on neighboring candles. I’ll post the fix soon. It would be great if you could share the screener code with the filters you mentioned; thanks for the feedback. Have a good weekend.
yea, i believe it wil not detect 100% correct all the time, but at least 9/10 is still would be great.
Have a great weekend too!
Code for screener:
// === Equal Swings Touch Screener with Range Filter (4 return values) ===
// 1) Call indicator (returns 4 values)
hcount, lcount, hhprice, llprice = CALL "PRC_equal swings Hi&Lo"
// 2) Price touching equal-high or equal-low level
tolerance = close * 0.001 // 0.1% of price, adjust if needed
touchHigh = (hcount > 0) AND (ABS(close - hhprice) <= tolerance)
touchLow = (lcount > 0) AND (ABS(close - llprice) <= tolerance)
// 3) Basic filters: price and volume
priceFilter = close > 1
todayVol = 0
IF day = day[1] THEN
FOR i = 0 TO intradaybarindex DO
todayVol = todayVol + volume[i]
NEXT
ENDIF
volumeFilter = todayVol > 1000000 // > 1M shares today
// 4) Range filter to avoid messy low-range charts
avgRange = 0
maxRange = 0
IF day = day[1] THEN
FOR i = 0 TO intradaybarindex DO
r = high[i] - low[i]
avgRange = avgRange + r
IF r > maxRange THEN
maxRange = r
ENDIF
NEXT
IF intradaybarindex >= 0 THEN
avgRange = avgRange / (intradaybarindex + 1)
ENDIF
ENDIF
minAvgRange = 0.03 // average 1-min range at least 3 cents
minMaxRange = 0.10 // at least one 1-min candle with >= 10 cents range
rangeFilter = (avgRange >= minAvgRange) AND (maxRange >= minMaxRange)
// 5) Final condition
cond = (touchHigh OR touchLow) AND priceFilter AND volumeFilter AND rangeFilter
SCREENER[cond](hcount AS "EqHighs", lcount AS "EqLows")
Thanks for the screener code, but it will not work without your modifications of the indicator. I see you added the swings high and low. But, is it the nearest ones? Because there can be many unbroken swings given by the indicator and the last one found by the loop could no be that nearest, but the last found.
I’m not sure if this the nearest one or not. because i have finished at friday just before market close, and not testet this on a lot of charts. will need to figure this out, when market open.
Code for indicator
defparam drawonlastbaronly = false
IF day <> day[1] OR intradaybarindex = 0 THEN
UNSET($peak)
UNSET($peakbar)
UNSET($trough)
UNSET($troughbar)
i = 0
j = 0
hhprice = 0
llprice = 0
ENDIF
Peak1 = (high[3] >= high[4]) AND (high[3] > high[5]) AND (high[3] > high[6])
Peak2 = (high[3] >= high[2]) AND (high[3] > high[1]) AND (high[3] > high[0])
Peak = Peak1 AND Peak2
IF Peak THEN
$peak[i] = high[3]
$peakbar[i] = barindex[3]
i = i + 1
ENDIF
Trough1 = (low[3] <= low[4]) AND (low[3] < low[5]) AND (low[3] < low[6])
Trough2 = (low[3] <= low[2]) AND (low[3] < low[1]) AND (low[3] < low[0])
Trough = Trough1 AND Trough2
IF Trough THEN
$trough[j] = low[3]
$troughbar[j] = barindex[3]
j = j + 1
ENDIF
IF islastbarupdate THEN
// ------- HIGHS -------
IF i > 0 THEN
hhcount = 0
FOR k = 0 TO i - 1 DO
drawpoint($peakbar[k], $peak[k], 2) coloured("cyan")
FOR l = 0 TO i - 1 DO
IF $peakbar[l] <> $peakbar[k] AND ABS($peakbar[l] - $peakbar[k]) > 1 THEN
diff = ABS(ROUND($peak[l], 2) - ROUND($peak[k], 2))
IF diff = 0 THEN // equal price
// find breakout
period = MAX(2, MAX($peakbar[l], $peakbar[k]) - MIN($peakbar[l], $peakbar[k]))
decay = MAX(1, barindex - MAX($peakbar[l], $peakbar[k]))
hh = highest[period](high)[decay]
IF hh <= MAX($peak[l], $peak[k]) THEN // no breakout at that time
drawsegment($peakbar[l], $peak[l], $peakbar[k], $peak[k]) coloured("cyan")
currPeriod = MAX(2, barindex - MAX($peakbar[l], $peakbar[k]))
currHH = highest[MAX(1, currPeriod)](high)
// test if no broken since (real time)
IF currHH <= MAX($peak[l], $peak[k]) THEN // no breakout since
drawsegment($peakbar[l], $peak[l], barindex, $peak[l]) coloured("cyan") style(dottedline4)
hhcount = hhcount + 1
// store price of this unbroken equal high level
hhprice = MAX($peak[l], $peak[k])
ENDIF
ENDIF
ENDIF
ENDIF
NEXT
NEXT
ENDIF
// ------- LOWS -------
IF j > 0 THEN
llcount = 0
FOR k = 0 TO j - 1 DO
drawpoint($troughbar[k], $trough[k], 2) coloured("crimson")
FOR l = 0 TO j - 1 DO
IF $troughbar[l] <> $troughbar[k] AND ABS($troughbar[l] - $troughbar[k]) > 1 THEN
diff = ABS(ROUND($trough[l], 2) - ROUND($trough[k], 2))
IF diff = 0 THEN // equal price
// find breakout
period = MAX(2, MAX($troughbar[l], $troughbar[k]) - MIN($troughbar[l], $troughbar[k]))
decay = MAX(1, barindex - MAX($troughbar[l], $troughbar[k]))
ll = lowest[period](low)[decay]
IF ll >= MIN($trough[l], $trough[k]) THEN // no breakout at that time
drawsegment($troughbar[l], $trough[l], $troughbar[k], $trough[k]) coloured("crimson")
currPeriod = MAX(2, barindex - MAX($troughbar[l], $troughbar[k]))
currLL = lowest[currPeriod](low)
// test if no broken since (real time)
IF currLL >= MIN($trough[l], $trough[k]) THEN // no breakout since
drawsegment($troughbar[l], $trough[l], barindex, $trough[l]) coloured("crimson") style(dottedline4)
llcount = llcount + 1
// store price of this unbroken equal low level
llprice = MIN($trough[l], $trough[k])
ENDIF
ENDIF
ENDIF
ENDIF
NEXT
NEXT
ENDIF
ENDIF
RETURN hhcount AS "unbroken highs count", llcount AS "unbroken lows count", hhprice AS "high level", llprice AS "low level"
That’s what I thought. hhprice and llprice are the last unbroken levels tested in the loop, it takes the swings one by one to build the levels, It means that they can be far away from the current price and you will miss some breakout. Just add a test in the loop to return the nearest ones found from the current price, so that your screener condition that test only this given levels is more accurate.
I had no idea, possilbly would have noticed it a lot later. Thank you again. I would want to ask you about a little new screener is that possible to create here or not. it’s like breakout screener that we made, but a little more nuanced I believe
So goal is : to find with screener which stock have linear 3 and more swing lows.
– Identify low swings (which we can already do with current indicator)
Give stocks on which there are such trendline.
Will send screenshots
Screener breakout swing tie highs and lows in 1 min
This topic contains 30 replies,
has 3 voices, and was last updated by
Nicolas
9 hours, 20 minutes ago.
| Forum: | ProScreener: Market Scanners & Detection |
| Language: | English |
| Started: | 10/15/2025 |
| Status: | Active |
| Attachments: | 38 files |
The information collected on this form is stored in a computer file by ProRealCode to create and access your ProRealCode profile. This data is kept in a secure database for the duration of the member's membership. They will be kept as long as you use our services and will be automatically deleted after 3 years of inactivity. Your personal data is used to create your private profile on ProRealCode. This data is maintained by SAS ProRealCode, 407 rue Freycinet, 59151 Arleux, France. If you subscribe to our newsletters, your email address is provided to our service provider "MailChimp" located in the United States, with whom we have signed a confidentiality agreement. This company is also compliant with the EU/Swiss Privacy Shield, and the GDPR. For any request for correction or deletion concerning your data, you can directly contact the ProRealCode team by email at privacy@prorealcode.com If you would like to lodge a complaint regarding the use of your personal data, you can contact your data protection supervisory authority.