OPEN-SOURCE SCRIPT
Grouped Peaks Screener (5/5) — Intraday (04:00 ET reset) — V1

//version=6
indicator("Grouped Peaks Screener (5/5) — Intraday (04:00 ET reset) — v2", overlay=true, max_lines_count=500, max_labels_count=0, max_boxes_count=0)
// ---------- user spec constants
LEFT = 5
RIGHT = 5
MS_PER_DAY = 24 * 60 * 60 * 1000
// ---------- typed arrays (Pine v6 best practice)
var int[] grp_ticks = array.new_int()
var int[] grp_counts = array.new_int()
var int[] grp_types = array.new_int() // 1 = high(res), -1 = low(sup)
var int[] grp_start = array.new_int() // bar_index of earliest peak in group
var line[] grp_lines = array.new_line()
var bool[] grp_active = array.new_bool()
// ---------- table (top-right)
max_table_rows = 20
var table infoTbl = table.new(position.top_right, 2, max_table_rows + 1, border_width = 1)
// ---------- helper: safely clear groups and delete drawings
f_clear_groups() =>
int nLines = array.size(grp_lines)
if nLines > 0
for i = 0 to nLines - 1
line ln = array.get(grp_lines, i)
if not na(ln)
line.delete(ln)
array.clear(grp_ticks)
array.clear(grp_counts)
array.clear(grp_types)
array.clear(grp_start)
array.clear(grp_lines)
array.clear(grp_active)
// ---------- trading day detection (premarket start 04:00 ET)
int y = year(time, "America/New_York")
int mo = month(time, "America/New_York")
int d = dayofmonth(time, "America/New_York")
int preStart = timestamp("America/New_York", y, mo, d, 4, 0)
int trading_day_start = time >= preStart ? preStart : preStart - MS_PER_DAY
var int prev_trading_day_start = na
if na(prev_trading_day_start)
prev_trading_day_start := trading_day_start
// reset at new premarket
if trading_day_start != prev_trading_day_start
f_clear_groups()
prev_trading_day_start := trading_day_start
bool allow_detection = time >= trading_day_start
// ---------- pivot detection (5 left / 5 right)
float ph = ta.pivothigh(high, LEFT, RIGHT)
float pl = ta.pivotlow(low, LEFT, RIGHT)
// ---------- process peak (add new or merge into existing same-price group)
f_process_peak(float price, int startBar, int kind) =>
int tick = int(math.round(price / syminfo.mintick))
int found = -1
int sz = array.size(grp_ticks)
if sz > 0
for i = 0 to sz - 1
if array.get(grp_active, i) and array.get(grp_types, i) == kind and array.get(grp_ticks, i) == tick
found := i
break
if found != -1
// merge into existing group
array.set(grp_counts, found, array.get(grp_counts, found) + 1)
if startBar < array.get(grp_start, found)
array.set(grp_start, found, startBar)
line ln = array.get(grp_lines, found)
if not na(ln)
line.set_xy1(ln, startBar, float(array.get(grp_ticks, found)) * syminfo.mintick)
line.set_xy2(ln, startBar + 1, float(array.get(grp_ticks, found)) * syminfo.mintick)
line ln2 = array.get(grp_lines, found)
if not na(ln2)
line.set_color(ln2, color.yellow)
else
color col = kind == 1 ? color.red : color.green
line lnNew = line.new(startBar, price, startBar + 1, price, xloc = xloc.bar_index, extend = extend.right, color = col, width = 2)
array.push(grp_ticks, tick)
array.push(grp_counts, 1)
array.push(grp_types, kind)
array.push(grp_start, startBar)
array.push(grp_lines, lnNew)
array.push(grp_active, true)
// apply pivots (pivot bar is bar_index - RIGHT, pivot confirmed at current bar)
if not na(ph)
int pivotBarIdxH = bar_index - RIGHT
int pivotTimeH = time[RIGHT]
if allow_detection and pivotTimeH >= trading_day_start
f_process_peak(ph, pivotBarIdxH, 1)
if not na(pl)
int pivotBarIdxL = bar_index - RIGHT
int pivotTimeL = time[RIGHT]
if allow_detection and pivotTimeL >= trading_day_start
f_process_peak(pl, pivotBarIdxL, -1)
// ---------- deletion rule: if price crosses level by >=1 tick -> delete group immediately
int nGroups = array.size(grp_ticks)
if nGroups > 0
for i = 0 to nGroups - 1
if array.get(grp_active, i)
int tick = array.get(grp_ticks, i)
int kind = array.get(grp_types, i)
int startB = array.get(grp_start, i)
if bar_index >= startB
if kind == 1
int highTick = int(math.round(high / syminfo.mintick))
if highTick > tick
line ln = array.get(grp_lines, i)
if not na(ln)
line.delete(ln)
array.set(grp_active, i, false)
else
int lowTick = int(math.round(low / syminfo.mintick))
if lowTick < tick
line ln = array.get(grp_lines, i)
if not na(ln)
line.delete(ln)
array.set(grp_active, i, false)
// ---------- Update top-right table "Equal H/L" and "Equal H/L price"
// header
table.cell(infoTbl, 0, 0, "Equal H/L", text_color = color.white, bgcolor = color.new(color.gray, 40))
table.cell(infoTbl, 1, 0, "Equal H/L price", text_color = color.white, bgcolor = color.new(color.gray, 40))
// clear rest of rows to avoid stale values
for r = 1 to max_table_rows
table.cell(infoTbl, 0, r, "", text_color = color.white, bgcolor = color.new(color.black, 100))
table.cell(infoTbl, 1, r, "", text_color = color.white, bgcolor = color.new(color.black, 100))
// populate grouped entries (count >= 2) that are active today
int row = 1
if array.size(grp_ticks) > 0
for i = 0 to array.size(grp_ticks) - 1
if array.get(grp_active, i) and array.get(grp_counts, i) >= 2
int kind = array.get(grp_types, i)
string typS = kind == 1 ? "H" : "L"
string leftText = str.tostring(array.get(grp_counts, i)) + "x " + typS
float p = float(array.get(grp_ticks, i)) * syminfo.mintick
string ptxt = str.tostring(p, format.mintick)
table.cell(infoTbl, 0, row, leftText, text_color = color.white, bgcolor = color.new(color.black, 60))
table.cell(infoTbl, 1, row, ptxt, text_color = color.white, bgcolor = color.new(color.black, 60))
row += 1
if row > max_table_rows
break
// invisible plot to keep indicator active
plot(na)
indicator("Grouped Peaks Screener (5/5) — Intraday (04:00 ET reset) — v2", overlay=true, max_lines_count=500, max_labels_count=0, max_boxes_count=0)
// ---------- user spec constants
LEFT = 5
RIGHT = 5
MS_PER_DAY = 24 * 60 * 60 * 1000
// ---------- typed arrays (Pine v6 best practice)
var int[] grp_ticks = array.new_int()
var int[] grp_counts = array.new_int()
var int[] grp_types = array.new_int() // 1 = high(res), -1 = low(sup)
var int[] grp_start = array.new_int() // bar_index of earliest peak in group
var line[] grp_lines = array.new_line()
var bool[] grp_active = array.new_bool()
// ---------- table (top-right)
max_table_rows = 20
var table infoTbl = table.new(position.top_right, 2, max_table_rows + 1, border_width = 1)
// ---------- helper: safely clear groups and delete drawings
f_clear_groups() =>
int nLines = array.size(grp_lines)
if nLines > 0
for i = 0 to nLines - 1
line ln = array.get(grp_lines, i)
if not na(ln)
line.delete(ln)
array.clear(grp_ticks)
array.clear(grp_counts)
array.clear(grp_types)
array.clear(grp_start)
array.clear(grp_lines)
array.clear(grp_active)
// ---------- trading day detection (premarket start 04:00 ET)
int y = year(time, "America/New_York")
int mo = month(time, "America/New_York")
int d = dayofmonth(time, "America/New_York")
int preStart = timestamp("America/New_York", y, mo, d, 4, 0)
int trading_day_start = time >= preStart ? preStart : preStart - MS_PER_DAY
var int prev_trading_day_start = na
if na(prev_trading_day_start)
prev_trading_day_start := trading_day_start
// reset at new premarket
if trading_day_start != prev_trading_day_start
f_clear_groups()
prev_trading_day_start := trading_day_start
bool allow_detection = time >= trading_day_start
// ---------- pivot detection (5 left / 5 right)
float ph = ta.pivothigh(high, LEFT, RIGHT)
float pl = ta.pivotlow(low, LEFT, RIGHT)
// ---------- process peak (add new or merge into existing same-price group)
f_process_peak(float price, int startBar, int kind) =>
int tick = int(math.round(price / syminfo.mintick))
int found = -1
int sz = array.size(grp_ticks)
if sz > 0
for i = 0 to sz - 1
if array.get(grp_active, i) and array.get(grp_types, i) == kind and array.get(grp_ticks, i) == tick
found := i
break
if found != -1
// merge into existing group
array.set(grp_counts, found, array.get(grp_counts, found) + 1)
if startBar < array.get(grp_start, found)
array.set(grp_start, found, startBar)
line ln = array.get(grp_lines, found)
if not na(ln)
line.set_xy1(ln, startBar, float(array.get(grp_ticks, found)) * syminfo.mintick)
line.set_xy2(ln, startBar + 1, float(array.get(grp_ticks, found)) * syminfo.mintick)
line ln2 = array.get(grp_lines, found)
if not na(ln2)
line.set_color(ln2, color.yellow)
else
color col = kind == 1 ? color.red : color.green
line lnNew = line.new(startBar, price, startBar + 1, price, xloc = xloc.bar_index, extend = extend.right, color = col, width = 2)
array.push(grp_ticks, tick)
array.push(grp_counts, 1)
array.push(grp_types, kind)
array.push(grp_start, startBar)
array.push(grp_lines, lnNew)
array.push(grp_active, true)
// apply pivots (pivot bar is bar_index - RIGHT, pivot confirmed at current bar)
if not na(ph)
int pivotBarIdxH = bar_index - RIGHT
int pivotTimeH = time[RIGHT]
if allow_detection and pivotTimeH >= trading_day_start
f_process_peak(ph, pivotBarIdxH, 1)
if not na(pl)
int pivotBarIdxL = bar_index - RIGHT
int pivotTimeL = time[RIGHT]
if allow_detection and pivotTimeL >= trading_day_start
f_process_peak(pl, pivotBarIdxL, -1)
// ---------- deletion rule: if price crosses level by >=1 tick -> delete group immediately
int nGroups = array.size(grp_ticks)
if nGroups > 0
for i = 0 to nGroups - 1
if array.get(grp_active, i)
int tick = array.get(grp_ticks, i)
int kind = array.get(grp_types, i)
int startB = array.get(grp_start, i)
if bar_index >= startB
if kind == 1
int highTick = int(math.round(high / syminfo.mintick))
if highTick > tick
line ln = array.get(grp_lines, i)
if not na(ln)
line.delete(ln)
array.set(grp_active, i, false)
else
int lowTick = int(math.round(low / syminfo.mintick))
if lowTick < tick
line ln = array.get(grp_lines, i)
if not na(ln)
line.delete(ln)
array.set(grp_active, i, false)
// ---------- Update top-right table "Equal H/L" and "Equal H/L price"
// header
table.cell(infoTbl, 0, 0, "Equal H/L", text_color = color.white, bgcolor = color.new(color.gray, 40))
table.cell(infoTbl, 1, 0, "Equal H/L price", text_color = color.white, bgcolor = color.new(color.gray, 40))
// clear rest of rows to avoid stale values
for r = 1 to max_table_rows
table.cell(infoTbl, 0, r, "", text_color = color.white, bgcolor = color.new(color.black, 100))
table.cell(infoTbl, 1, r, "", text_color = color.white, bgcolor = color.new(color.black, 100))
// populate grouped entries (count >= 2) that are active today
int row = 1
if array.size(grp_ticks) > 0
for i = 0 to array.size(grp_ticks) - 1
if array.get(grp_active, i) and array.get(grp_counts, i) >= 2
int kind = array.get(grp_types, i)
string typS = kind == 1 ? "H" : "L"
string leftText = str.tostring(array.get(grp_counts, i)) + "x " + typS
float p = float(array.get(grp_ticks, i)) * syminfo.mintick
string ptxt = str.tostring(p, format.mintick)
table.cell(infoTbl, 0, row, leftText, text_color = color.white, bgcolor = color.new(color.black, 60))
table.cell(infoTbl, 1, row, ptxt, text_color = color.white, bgcolor = color.new(color.black, 60))
row += 1
if row > max_table_rows
break
// invisible plot to keep indicator active
plot(na)
สคริปต์โอเพนซอร์ซ
ด้วยเจตนารมณ์หลักของ TradingView ผู้สร้างสคริปต์นี้ได้ทำให้มันเป็นโอเพ่นซอร์ส เพื่อให้เทรดเดอร์สามารถตรวจสอบและยืนยันการทำงานของสคริปต์ได้ ขอแสดงความชื่นชมผู้เขียน! แม้ว่าคุณจะสามารถใช้งานได้ฟรี แต่อย่าลืมว่าการเผยแพร่โค้ดซ้ำนั้นจะต้องเป็นไปตามกฎระเบียบการใช้งานของเรา
คำจำกัดสิทธิ์ความรับผิดชอบ
ข้อมูลและบทความไม่ได้มีวัตถุประสงค์เพื่อก่อให้เกิดกิจกรรมทางการเงิน, การลงทุน, การซื้อขาย, ข้อเสนอแนะ หรือคำแนะนำประเภทอื่น ๆ ที่ให้หรือรับรองโดย TradingView อ่านเพิ่มเติมที่ ข้อกำหนดการใช้งาน
สคริปต์โอเพนซอร์ซ
ด้วยเจตนารมณ์หลักของ TradingView ผู้สร้างสคริปต์นี้ได้ทำให้มันเป็นโอเพ่นซอร์ส เพื่อให้เทรดเดอร์สามารถตรวจสอบและยืนยันการทำงานของสคริปต์ได้ ขอแสดงความชื่นชมผู้เขียน! แม้ว่าคุณจะสามารถใช้งานได้ฟรี แต่อย่าลืมว่าการเผยแพร่โค้ดซ้ำนั้นจะต้องเป็นไปตามกฎระเบียบการใช้งานของเรา
คำจำกัดสิทธิ์ความรับผิดชอบ
ข้อมูลและบทความไม่ได้มีวัตถุประสงค์เพื่อก่อให้เกิดกิจกรรมทางการเงิน, การลงทุน, การซื้อขาย, ข้อเสนอแนะ หรือคำแนะนำประเภทอื่น ๆ ที่ให้หรือรับรองโดย TradingView อ่านเพิ่มเติมที่ ข้อกำหนดการใช้งาน