// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.
0
at
// https://mozilla.org/MPL/2.0/
// ChartPrime
//@version=5
indicator("Support and Resistance Power Channel [ChartPrime]", "S&R Power
[ChartPrime]",
overlay = true, max_labels_count = 12, max_bars_back = 500)
// USER INPUTS
int length = input.int(130, title="Length")
int extend = input.int(30, title="Extend", minval = 20, maxval = 100)
color t_col = input.color(color.fuchsia, "Top Color", inline = "col")
color b_col = input.color(color.lime, "Bottom Color", inline = "col")
// Data Structure for Indicator State
type data
line sup = na
line res = na
box sup_area = na
box res_area = na
// INDICATOR CALCULATIONS
max_min(length, d) =>
var max_val_arr = array.new<float>(length)
var min_val_arr = array.new<float>(length)
var max_idx_arr = array.new<int>(length)
var min_idx_arr = array.new<int>(length)
// Update arrays with current bar's data, shifting old data out
max_val_arr.unshift(high)
min_val_arr.unshift(low)
max_idx_arr.unshift(bar_index)
min_idx_arr.unshift(bar_index)
// Trim arrays to maintain 'length' size
if array.size(max_val_arr) > length
max_val_arr.pop()
min_val_arr.pop()
max_idx_arr.pop()
min_idx_arr.pop()
// Return NA if not enough historical data yet
if array.size(max_val_arr) < length
[na, na]
else
float max_current_val = max_val_arr.max()
float min_current_val = min_val_arr.min()
float mid_val = math.avg(max_current_val, min_current_val)
// Find index of max/min values within the arrays
int index_in_max_arr = max_val_arr.indexof(max_current_val)
int index_in_min_arr = min_val_arr.indexof(min_current_val)
// Get the corresponding bar_index, checking for -1 from indexof
int bar_index_of_max = na
int bar_index_of_min = na
if index_in_max_arr != -1
bar_index_of_max = array.get(max_idx_arr, index_in_max_arr)
if index_in_min_arr != -1
bar_index_of_min = array.get(min_idx_arr, index_in_min_arr)
// --- VISUALIZATION ELEMENTS FOR MAX/MIN/MID ---
// These labels and lines are drawn on the last bar only for performance
if barstate.islast
// Delete previous labels to avoid clutter
label.delete(label.new(bar_index + extend + 15, max_current_val,
str.tostring(max_current_val, "#.##"), color = color(na), style =
label.style_label_center, textcolor = chart.fg_color)[1])
label.delete(label.new(bar_index + extend + 15, min_current_val,
str.tostring(min_current_val, " #.##"), color = color(na), style =
label.style_label_center, textcolor = chart.fg_color)[1])
label.delete(label.new(bar_index + extend, mid_val,
str.tostring(mid_val, " #.##"), color = color(na), style = label.style_label_left,
textcolor = color.gray)[1])
// Delete previous mid-line
line.delete(line.new(bar_index - length, mid_val, bar_index + extend,
mid_val, color = color.gray, style = line.style_dotted)[1])
// Mark max and min points with 'x' (delete previous before creating
new)
if bar_index_of_max != na // Only draw if valid index found
label.delete(label.new(bar_index_of_max, max_current_val, "x",
color = color(na), textcolor = t_col, size = size.normal, style =
label.style_label_center)[1])
if bar_index_of_min != na // Only draw if valid index found
label.delete(label.new(bar_index_of_min, min_current_val, "x",
color = color(na), textcolor = b_col, size = size.normal, style =
label.style_label_center)[1])
[max_current_val, min_current_val]
// Function to delete previous drawing objects
delte_(data d) =>
line.delete(d.sup[1])
line.delete(d.res[1])
box.delete(d.sup_area[1])
box.delete(d.res_area[1])
// Calculate Buy/Sell Power
power(d) =>
int buy = 0
int sell = 0
if barstate.islast
for i = 0 to length - 1
buy += (close[i] > open[i] ? 1 : 0)
sell += (close[i] < open[i] ? 1 : 0) // Corrected 'ell' to 'sell'
// Set text for power areas (fixed str.tostring format)
d.sup_area.set_text(str.tostring(buy, "Buy Power: #"))
d.res_area.set_text(str.tostring(sell, "Sell Power: #"))
// Set text properties
d.res_area.set_text_color(chart.fg_color)
d.sup_area.set_text_color(chart.fg_color)
d.res_area.set_text_halign(text.align_left)
d.sup_area.set_text_halign(text.align_left)
d.res_area.set_text_size(size.normal)
d.sup_area.set_text_size(size.normal)
// Generate signals based on price crossing channels
signals(d) =>
if barstate.islast
// Loop through recent bars for signal detection
for i = 0 to length - 1 // Consider if this loop needs to be 'history-
referencing safe' on first bars
float low_1 = low[i]
float low_2 = low[i > 0 ? i + 1 : i] // Accessing low[i+1] requires
careful handling of bar_index limits
float high_1 = high[i]
float high_2 = high[i > 0 ? i + 1 : i] // Accessing high[i+1] requires
careful handling of bar_index limits
int index = bar_index - i
float top_channel = d.sup_area.get_top() // Renamed to avoid keyword
conflict
float bot_channel = d.res_area.get_bottom() // Renamed to avoid keyword
conflict
// Buy signal: Price crosses above top channel
if low_1 > top_channel and low_2 <= top_channel
label.new(index, low_2, "", textcolor = b_col, color = color(na),
style = label.style_label_up, size = size.large)
// Sell signal: Price crosses below bottom channel
if high_1 < bot_channel and high_2 >= bot_channel // Corrected
condition from 'high_1 bot'
label.new(index, high_2, "", textcolor = t_col, color = color(na),
style = label.style_label_down, size = size.large)
// Main indicator execution function
run_indicator() =>
float atr = ta.atr(200) * 0.5
// Initialize data struct (only once per script execution)
var data d = data.new(line.new(na, na, na, na), line.new(na, na, na, na),
box.new(na, na, na, na), box.new(na, na, na, na))
// Calculate max and min values for channel boundaries
[max_val, min_val] = max_min(length, d)
// Ensure we have valid max/min values before drawing channels
if not na(max_val) and not na(min_val)
if barstate.islast
// Delete old drawing objects before creating new ones to prevent
accumulation
delte_(d)
// Create/update support and resistance lines
d.sup := line.new(bar_index - length, max_val + atr, bar_index + extend
+ 30, max_val + atr, color = t_col, style = line.style_solid)
d.res := line.new(bar_index - length, min_val - atr, bar_index + extend
+ 30, min_val - atr, color = b_col, style = line.style_solid)
// Create/update shaded areas for support and resistance
// Note: box.new parameters are (left, top, right, bottom)
d.res_area := box.new(bar_index - length, max_val + atr, bar_index +
extend, max_val - atr, na, bgcolor = color.new(t_col, 80))
d.sup_area := box.new(bar_index - length, min_val + atr, bar_index +
extend, min_val - atr, na, bgcolor = color.new(b_col, 80))
// Run signal and power calculations/visualizations
signals(d)
power(d)
// Execute the main indicator function
run_indicator()