//
-----------------------------------------------------------------------------------
--------------------------------------------------------------------
//@version=5
indicator("Support and Resistance Power Channel Pro", "S&R Power Pro [Scalp]",
overlay = true, max_labels_count = 12, max_bars_back = 500)
//
-----------------------------------------------------------------------------------
// 𝙐𝙎𝙀𝙍 𝙄𝙉𝙋𝙐𝙏𝙎
---------------------------------}
//
-----------------------------------------------------------------------------------
---------------------------------{
// Length for calculating the highest high and lowest low for Support/Resistance.
// A shorter length increases reactivity, which is crucial for scalping.
int length = input.int(50, title="Lookback Period (Reactivity)", minval = 10,
maxval = 200, tooltip="Shorter values increase reactivity for scalping. A good
starting point for gold scalping might be 20-50.")
// Length for calculating Average True Range (ATR), which determines the channel's
width.
// A shorter ATR length makes the channels adapt faster to volatility changes.
int atrLength = input.int(20, title="ATR Length for Channels", minval=5,
maxval=100, tooltip="Adjusts channel width dynamically based on volatility. Shorter
values for more reactive bands, suitable for quick moves.")
// Number of bars to extend the Support/Resistance lines and channel boxes into the
future.
int extend = input.int(30, minval = 20, maxval = 100, title="Extend Lines By Bars")
// Colors for the top (resistance) and bottom (support) channels.
color t_col = input.color(color.fuchsia, "Top Channel Color", inline = "col")
color b_col = input.color(color.lime, "Bottom Channel Color", inline = "col")
// Thresholds for classifying market momentum based on the normalized volume delta
(Volume Pressure Ratio).
// These values allow customization of what 'strong' vs. 'moderate' momentum means
for your trading style.
float deltaThresholdStrong = input.float(0.4, "Strong Momentum Threshold",
minval=0.1, maxval=0.9, step=0.05, tooltip="Ratio of (Buy-Sell)/(Buy+Sell) above
which momentum is considered 'Strong'.")
float deltaThresholdModerate = input.float(0.1, "Moderate Momentum Threshold",
minval=0.01, maxval=0.5, step=0.01, tooltip="Ratio of (Buy-Sell)/(Buy+Sell) above
which momentum is considered 'Moderate'.")
// Custom data type to hold references to drawing objects (lines, boxes, labels).
// This helps in managing and deleting old drawings efficiently for real-time
updates.
type data
line sup = na // Support line
line res = na // Resistance line
box sup_area = na // Shaded support area
box res_area = na // Shaded resistance area
label delta_label = na // Label for volume and market direction
//
-----------------------------------------------------------------------------------
---------------------------------}
// 𝙄𝙉𝘿𝙄𝘾𝘼𝙏𝙊𝙍 𝘾𝘼𝙇𝘾𝙐𝙇𝘼𝙏𝙄𝙊𝙉𝙎
//
-----------------------------------------------------------------------------------
---------------------------------{
// Function to calculate the highest high and lowest low over a specified lookback
period.
// Utilizes built-in Pine Script functions `ta.highest` and `ta.lowest` for
efficiency and reactivity.
max_min_reactive(length_arg)=>
float max_ = ta.highest(length_arg) // Highest price within the last
'length_arg' bars
float min_ = ta.lowest(length_arg) // Lowest price within the last
'length_arg' bars
[max_, min_] // Return both values as a tuple
// Function to delete old drawing objects (lines, boxes, labels).
// This is crucial for performance and preventing clutter, as drawings are
recreated on each new bar.
delte_old_drawings(data d)=>
line.delete(d.sup[1]) // Delete the previous support line
line.delete(d.res[1]) // Delete the previous resistance line
box.delete(d.sup_area[1]) // Delete the previous support area box
box.delete(d.res_area[1]) // Delete the previous resistance area box
label.delete(d.delta_label[1]) // Delete the previous delta label
// Function to update the text content of the support and resistance 'power' boxes.
// This will display the aggregated buy and sell volume directly within the
channels.
power_display(d, buy, sell)=>
// Set text for the support area (originally 'sup_area', but used for buy
volume)
d.sup_area.set_text(str.tostring(buy, " Volume Acheteur: #.##"))
// Set text for the resistance area (originally 'res_area', but used for sell
volume)
d.res_area.set_text(str.tostring(sell, " Volume Vendeur: #.##"))
// Set text properties for improved readability and alignment
d.res_area.set_text_color(chart.fg_color) // Foreground color of the chart
d.sup_area.set_text_color(chart.fg_color)
d.res_area.set_text_halign(text.align_left) // Align text to the left
d.sup_area.set_text_halign(text.align_left)
d.res_area.set_text_size(size.normal) // Normal text size
d.sup_area.set_text_size(size.normal)
// Function to draw potential entry/reversal signals.
// These signals are based on price interacting with the calculated support and
resistance channels.
signals(d, top_channel, bottom_channel)=>
// Ensure this logic runs only on the last bar to avoid historical signal
reprocessing every tick
if barstate.islast
// Iterate through recent bars to find signal triggers.
// The 'length' variable here helps to look back for recent interactions.
for i = 0 to length - 1
// Get the low and high prices of the current and previous bar in the
loop
float low_1 = low[i]
float low_2 = low[i > 0 ? i+1 : i] // Previous bar's low (or current if
i=0)
float high_1 = high[i]
float high_2 = high[i > 0 ? i+1 : i] // Previous bar's high
// Calculate the bar index for accurate label placement
int index = bar_index - i
// Bullish signal: Price bounces off the bottom channel (support).
// This occurs when the current low is above the bottom channel, but
the previous low was at or below it.
if low_1 > bottom_channel and low_2 <= bottom_channel
label.new(index, low_2, "▲", textcolor = b_col, color = color(na),
style = label.style_label_up, size = size.large, tooltip="Potential
Reversal/Support Bounce: Price tested or broke below support and bounced.")
// Bearish signal: Price is rejected at the top channel (resistance).
// This occurs when the current high is below the top channel, but the
previous high was at or above it.
if high_1 < top_channel and high_2 >= top_channel
label.new(index, high_2, "▼", textcolor = t_col, color = color(na),
style = label.style_label_down, size = size.large, tooltip="Potential
Reversal/Resistance Rejection: Price tested or broke above resistance and was
rejected.")
// Main function where the indicator's logic is executed.
run_indicator()=>
// Calculate Average True Range (ATR) based on `atrLength` input.
// ATR is used to dynamically adjust the width of the support and resistance
channels,
// accounting for current market volatility (Gold is highly volatile).
float atr = ta.atr(atrLength) * 0.5 // Using half ATR for a tighter channel
padding.
// Initialize (or re-initialize on first bar) the data structure for drawing
objects.
var data d = data.new(line(na), line(na), box(na), box(na), label(na))
// Get the most reactive max and min price levels over the 'length' lookback
period.
[max_price, min_price] = max_min_reactive(length)
float mid_price = (max_price + min_price) / 2 // Calculate the midpoint of the
channel
// Define the exact levels for the top and bottom channels by
adding/subtracting ATR from max/min prices.
float top_channel = max_price + atr
float bottom_channel = min_price - atr
// All drawing and label updates should ideally happen only on the last bar to
ensure
// real-time information without redrawing historical data unnecessarily.
if barstate.islast
// Draw the top (resistance) channel line.
// It extends from 'length' bars back to 'extend' bars into the future.
d.sup := line.new(bar_index - length, top_channel, bar_index + extend + 30,
top_channel, color = t_col, style = line.style_solid, width=2)
// Draw the bottom (support) channel line.
d.res := line.new(bar_index - length, bottom_channel, bar_index + extend +
30, bottom_channel, color = b_col, style = line.style_solid, width=2)
// Draw the shaded resistance area (between top_channel and max_price -
atr).
// This visually represents the overhead resistance zone.
d.res_area := box.new(bar_index - length, top_channel, bar_index + extend,
max_price - atr, na, bgcolor = color.new(t_col, 80)) // Resistance area
// Draw the shaded support area (between min_price + atr and
bottom_channel).
// This visually represents the underlying support zone.
d.sup_area := box.new(bar_index - length, min_price + atr, bar_index +
extend, bottom_channel, na, bgcolor = color.new(b_col, 80)) // Support area
// Initialize variables for accumulating total buy and sell volume.
float totalBuyVolume = 0.0
float totalSellVolume = 0.0
// Loop through the 'length' most recent bars to calculate aggregated buy
and sell volume.
// This is a crucial part of understanding market momentum.
for i = 0 to length - 1
float currentVolume = volume[i]
float currentHigh = high[i]
float currentLow = low[i]
float currentClose = close[i]
float currentOpen = open[i]
float barRange = currentHigh - currentLow // Calculate the range of the
current bar
if barRange != 0 // Avoid division by zero for flat bars
if currentClose >= currentOpen // Bullish or Doji bar (Close >=
Open)
// Calculate volume proportion based on price movement within
the bar.
// Volume from low to close is considered buying pressure.
totalBuyVolume += currentVolume * (currentClose - currentLow) /
barRange
// Volume from close to high is considered selling pressure
(e.g., profit taking, rejection).
totalSellVolume += currentVolume * (currentHigh - currentClose)
/ barRange
else // Bearish bar (Close < Open)
// Volume from high to close is considered selling pressure.
totalSellVolume += currentVolume * (currentHigh - currentClose)
/ barRange
// Volume from close to low is considered buying pressure
(e.g., absorption, buying the dip).
totalBuyVolume += currentVolume * (currentClose - currentLow) /
barRange
else // If bar is flat (High == Low), split volume equally if present.
if currentVolume > 0
totalBuyVolume += currentVolume / 2
totalSellVolume += currentVolume / 2
// Calculate the net volume delta (difference between buying and selling
volume).
float delta = totalBuyVolume - totalSellVolume
// Calculate the total aggregated volume (sum of buy and sell volume).
float totalAggregatedVolume = totalBuyVolume + totalSellVolume
// Calculate the Volume Pressure Ratio: a normalized measure of buying vs.
selling pressure.
// This ratio ranges from -1 (pure selling) to +1 (pure buying), providing
clear momentum insights.
float volumePressureRatio = totalAggregatedVolume != 0 ? delta /
totalAggregatedVolume : 0.0
// Initialize string and color variables for the market direction label.
string marketDirection = ""
color deltaColor = color.new(color.gray, 10) // Default color: light gray
for neutral
// Determine market direction based on the Volume Pressure Ratio and user-
defined thresholds.
// This provides a clear indication of trend strength and momentum.
if volumePressureRatio > deltaThresholdStrong
marketDirection := "TRÈS HAUSSIER (Achat Fort)"
deltaColor := color.new(color.green, 10) // Strong green for strong
bullish
else if volumePressureRatio > deltaThresholdModerate
marketDirection := "HAUSSIER (Achat Modéré)"
deltaColor := color.new(color.lime, 10) // Lighter green for moderate
bullish
else if volumePressureRatio < -deltaThresholdStrong
marketDirection := "TRÈS BAISSIER (Vente Forte)"
deltaColor := color.new(color.red, 10) // Strong red for strong bearish
else if volumePressureRatio < -deltaThresholdModerate
marketDirection := "BAISSIER (Vente Modérée)"
deltaColor := color.new(color.maroon, 10) // Lighter red for moderate
bearish
else
marketDirection := "NEUTRE (Équilibre)"
deltaColor := color.new(color.gray, 10) // Gray for neutral/balanced
market
// Calculate a simple Exponential Moving Average (EMA) for current price
trend context.
// A 20-period EMA is good for short-term trend confirmation in scalping.
float ema_price = ta.ema(close, 20)
string priceTrend = ""
if close > ema_price
priceTrend := "Prix: Au-dessus EMA (Haussier)"
else if close < ema_price
priceTrend := "Prix: En-dessous EMA (Baissier)"
else
priceTrend := "Prix: Sur EMA (Neutre)"
// Construct the comprehensive label text.
// It now includes raw volume, delta, the normalized ratio, the market
direction (momentum/trend),
// and the current price's relation to a short-term EMA. This provides a
holistic view.
string label_text = ("VOL. A: " + str.tostring(totalBuyVolume, "#.##") +
"\nVOL. V: " + str.tostring(totalSellVolume, "#.##") +
"\nDELTA: " + str.tostring(delta, "#.##") +
"\nRATIO: " + str.tostring(volumePressureRatio,
"#.##") +
"\n\nDIRECTION MARCHÉ: " + marketDirection +
"\n" + priceTrend)
// Create the new delta label, positioned relative to the channel midpoint.
d.delta_label := label.new(bar_index + extend - 13, mid_price, label_text,
style=label.style_label_center, color=deltaColor, size = size.normal,
textcolor=color.white, xloc=xloc.bar_index)
// Update the 'power' boxes with the actual calculated buy and sell
volumes.
power_display(d, totalBuyVolume, totalSellVolume)
// Delete all old drawing objects to ensure the chart is clean and shows
only current data.
delte_old_drawings(d)
// Call the signals function to draw potential entry/reversal points based on
price interaction
// with the dynamic support and resistance channels.
signals(d, top_channel, bottom_channel)
//
-----------------------------------------------------------------------------------
// 𝙑𝙄𝙎𝐔𝐀𝐋𝐈𝙕𝘼𝐓𝐈𝙊𝙉
---------------------------------}
//
-----------------------------------------------------------------------------------
---------------------------------{
run_indicator() // Execute the main indicator logic