Created
March 26, 2022 17:57
-
-
Save kuldeepkeshwar/b65c194b22efb02b3cd0e3562d928263 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//@version=5 | |
// ══════════════════════════════════════════════════════════════════════════════════════════════════ // | |
//# * ══════════════════════════════════════════════════════════════════════════════════════════════ | |
//# * | |
//# * Study : Price Action - Support & Resistance | |
//# * - Support & Resistance based on Volume | |
//# * - Volume Weighted Colored Bars and Sign of Exhaustion Indication Add-On | |
//# * Author : © dgtrd | |
//# * | |
//# * Revision History | |
//# * Release : Jan 25, 2021 | |
//# * Update : Jan 26, 2021 : User Request : Add price option for intruments with no volume data | |
//# * Update : Mar 18, 2021 : Ability to draw lines and cofigure alerts when volume spikes detected | |
//# * Update : Mar 21, 2021 : Ability to draw lines and cofigure alerts when high volatility detected | |
//# * - line customization abaility | |
//# * Update : Sep 03, 2021 : Ability to control number of lines drawn | |
//# * Update : Feb 21, 2022 : Added Volume Profile, inspired by Ildar Akhmetgaleev's 'Poor man's volume profile' | |
//# * | |
//# * ══════════════════════════════════════════════════════════════════════════════════════════════ | |
// ══════════════════════════════════════════════════════════════════════════════════════════════════ // | |
indicator('Price Actio', 'S&R', true, max_bars_back = 500, max_lines_count = 500, max_boxes_count = 500) | |
// -Inputs ══════════════════════════════════════════════════════════════════════════════════════ // | |
// ---------------------------------------------------------------------------------------------- // | |
// Definitions ---------------------------------------------------------------------------------- // | |
group_support_and_resistance = 'Consecutively Increasing Volume / Price' | |
tooltip_support_and_resistance = 'Moments where\n' + | |
'- price is bullish or bearish consecutively for minimum 3 bars and on increasing volume with at least one bar\'s volume is above volume moving average\n' + | |
'or\n' + | |
'- price is bullish or bearish consecutively on increasing/decreasing price for minimum 3 bars' | |
group_volume_spike_sign_of_exhaustion = 'Volume Spike - Sign of Exhaustion' | |
tooltip_volume_spike_sign_of_exhaustion = 'Moments where\n' + | |
'huge volume detected : current volume is grater than the product of the theshold value and volume moving average\n' + | |
'presents idea : huge volume may be a sign of exhaustion and may lead to sharp reversals' | |
group_high_volatility = 'High Volatility' | |
tooltip_high_volatility = 'Moments where\n' + | |
'price range of the current bar is grater than the product of the theshold value and average true range value of defined period' | |
group_volume_weighted_colored_bars = 'Volume Weighted Colored Bars' | |
tooltip_volume_weighted_colored_bars = 'Colors bars based on the bar\'s volume relative to volume moving average\n' + | |
'trading tip : a potential breakout trading opportunity may occur when price moves above a resistance level or moves below a support level on increasing volume' | |
tooltip_volume_moving_average = 'Volume simple moving average, serves as reference to\n' + | |
'- Support and Resistance,\n' + | |
'- Volume Weighted Colored Bars,\n' + | |
'- Volume Spike - Sign of Exhaustion\ncalculations' | |
// User Input Declarations ---------------------------------------------------------------------- // | |
// ---------------------------------------------------------------------------------------------- // | |
// Consecutively Increasing Volume / Price ----------------------------------------------------- // | |
i_lenLookback = input.int(360, 'Lookback Interval (Bars)', minval=0, step=10) | |
i_sourceSnR = input.string('Volume', 'S & R Calculation Source', options=['Price', 'Volume'], group=group_support_and_resistance, tooltip=tooltip_support_and_resistance) | |
i_isSnR = input.bool(true, 'S & R Lines', inline='SR', group=group_support_and_resistance) | |
i_srLnColor = input.color(#4dd0e141, '', inline='SR', group=group_support_and_resistance) | |
i_srLnWidth = input.int(3, '', inline='SR', group=group_support_and_resistance) | |
i_srLnStyle = input.string('Solid', '', options=['Dashed', 'Dotted', 'Solid'], inline='SR', group=group_support_and_resistance) | |
// ---------------------------------------------------------------------------------------------- // | |
// Volume Spike - Sign of Exhaustion ------------------------------------------------------------ // | |
i_vSpikeLb = input.bool(true, '🚦', inline='SRS1', group=group_volume_spike_sign_of_exhaustion, tooltip=tooltip_volume_spike_sign_of_exhaustion) | |
i_vSpikeThresh = input.float(4.669, 'Volume Spike Theshold', minval=.1, step=.1, inline='SRS1', group=group_volume_spike_sign_of_exhaustion) | |
i_isSnRSpike = input.bool(true, 'S & R Lines', inline='SRS2', group=group_volume_spike_sign_of_exhaustion) | |
i_spLnColor = input.color(#ffb74d69, '', inline='SRS2', group=group_volume_spike_sign_of_exhaustion) | |
i_spLnWidth = input.int(3, '', inline='SRS2', group=group_volume_spike_sign_of_exhaustion) | |
i_spLnStyle = input.string('Solid', '', options=['Dashed', 'Dotted', 'Solid'], inline='SRS2', group=group_volume_spike_sign_of_exhaustion) | |
i_spLnBullLevel = input.string('Both', 'Levels : Bullish', options=['High', 'Close', 'Both'], inline='SRS3', group=group_volume_spike_sign_of_exhaustion) | |
i_spLnBearLevel = input.string('Both', ' Bearish', options=['Low', 'Close', 'Both'], inline='SRS3', group=group_volume_spike_sign_of_exhaustion) | |
// ---------------------------------------------------------------------------------------------- // | |
// High Volatility ------------------------------------------------------------------------------ // | |
i_hATRLb = input.bool(true, '⚡', inline='ATR', group=group_high_volatility, tooltip=tooltip_high_volatility) | |
i_atrLength = input.int(11, 'ATR : Length', inline='ATR', group=group_high_volatility) | |
i_atrMult = input.float(2.718, 'Mult', minval=.1, step=.1, inline='ATR', group=group_high_volatility) | |
i_hATRLn = input.bool(true, 'S & R Lines', inline='AT1', group=group_high_volatility) | |
i_hATRLnColor = input.color(#81c78455, '', inline='AT1', group=group_high_volatility) | |
i_hATRLnWidth = input.int(3, '', inline='AT1', group=group_high_volatility) | |
i_hATRLnStyle = input.string('Solid', '', options=['Dashed', 'Dotted', 'Solid'], inline='AT1', group=group_high_volatility) | |
i_haLnBullLevel = input.string('Both', 'Levels : Bullish', options=['High', 'Close', 'Both'], inline='AT2', group=group_high_volatility) | |
i_haLnBearLevel = input.string('Both', ' Bearish', options=['Low', 'Close', 'Both'], inline='AT2', group=group_high_volatility) | |
// ---------------------------------------------------------------------------------------------- // | |
// Volume Weighted Colored Bars ----------------------------------------------------------------- // | |
i_vwcb = input.bool(true, '', inline='VWC', group=group_volume_weighted_colored_bars, tooltip=tooltip_volume_weighted_colored_bars) | |
i_vwcbHighThresh = input.float(1.618, 'Thesholds : High ', minval=1., step=.1, inline='VWC', group=group_volume_weighted_colored_bars) | |
i_vwcbLowThresh = input.float(0.618, 'Low', minval=.1, step=.1, inline='VWC', group=group_volume_weighted_colored_bars) | |
// ---------------------------------------------------------------------------------------------- // | |
// Volume Moving Average : Base ----------------------------------------------------------------- // | |
i_vSMA = ta.sma(nz(volume), input.int(89, 'Volume Moving Average Length', group='General Settings', tooltip=tooltip_volume_moving_average)) | |
// -Calculations ════════════════════════════════════════════════════════════════════════════════ // | |
// ---------------------------------------------------------------------------------------------- // | |
// Definitions ---------------------------------------------------------------------------------- // | |
nzVolume = nz(volume) | |
risingVol = nzVolume >= nzVolume[1] | |
bullCandle = close > open | |
bearCandle = close < open | |
risingPrice = close > close[1] | |
fallingPrice = close < close[1] | |
lwstPrice = ta.lowest (low , 3) | |
hstPrice = ta.highest(high, 3) | |
weightedATR = i_atrMult * ta.atr(i_atrLength) | |
range_1 = math.abs(high - low) | |
x2 = timenow + 7 * math.round(ta.change(time)) | |
sProcessing = time > timenow - i_lenLookback * (timeframe.isintraday ? timeframe.multiplier * 86400000 / 1440 : timeframe.multiplier * 86400000) | |
// ---------------------------------------------------------------------------------------------- // | |
// Consecutively Increasing Volume / Price ----------------------------------------------------- // | |
falling = if i_sourceSnR == 'Volume' | |
bearCandle and bearCandle[1] and bearCandle[2] and nzVolume > i_vSMA and risingVol and risingVol[1] | |
else | |
bearCandle and bearCandle[1] and bearCandle[2] and fallingPrice and fallingPrice[1] and fallingPrice[2] | |
rising = if i_sourceSnR == 'Volume' | |
bullCandle and bullCandle[1] and bullCandle[2] and nzVolume > i_vSMA and risingVol and risingVol[1] | |
else | |
bullCandle and bullCandle[1] and bullCandle[2] and risingPrice and risingPrice[1] and risingPrice[2] | |
y = ta.valuewhen(falling or rising, falling ? lwstPrice : hstPrice, 0) | |
x1 = ta.valuewhen(falling or rising, time, 0) | |
// ---------------------------------------------------------------------------------------------- // | |
// Volume Spike - Sign of Exhaustion ------------------------------------------------------------ // | |
exhaustVol = nzVolume > i_vSpikeThresh * i_vSMA | |
x1V = ta.valuewhen(exhaustVol, time, 0) | |
// ---------------------------------------------------------------------------------------------- // | |
// High Volatility ------------------------------------------------------------------------------ // | |
highVolatility = range_1 > weightedATR | |
x1hV = ta.valuewhen(highVolatility, time, 0) | |
// ---------------------------------------------------------------------------------------------- // | |
// Volume Weighted Colored Bars ----------------------------------------------------------------- // | |
vwcbCol = nzVolume > i_vSMA * i_vwcbHighThresh ? bearCandle ? #910000 : #006400 : nzVolume < i_vSMA * i_vwcbLowThresh ? bearCandle ? #FF9800 : #7FFFD4 : na | |
// -Plotting ════════════════════════════════════════════════════════════════════════════════════ // | |
f_getStyle(_s) => | |
_s == 'Solid' ? line.style_solid : _s == 'Dotted' ? line.style_dotted : line.style_dashed | |
// ---------------------------------------------------------------------------------------------- // | |
// Consecutively Increasing Volume / Price ----------------------------------------------------- // | |
var line srLine = na | |
if i_isSnR and falling and sProcessing | |
if falling == falling[1] | |
line.delete(srLine[1]) | |
srLine := line.new(x1, y, x2, y, xloc.bar_time, extend.none, i_srLnColor, f_getStyle(i_srLnStyle), i_srLnWidth) | |
srLine | |
if i_isSnR and rising and sProcessing | |
if rising == rising[1] | |
line.delete(srLine[1]) | |
srLine := line.new(x1, y, x2, y, xloc.bar_time, extend.none, i_srLnColor, f_getStyle(i_srLnStyle), i_srLnWidth) | |
srLine | |
// ---------------------------------------------------------------------------------------------- // | |
// Volume Spike - Sign of Exhaustion ------------------------------------------------------------ // | |
var line spikeLine = na | |
var line spikeLine1 = na | |
var line spikeLine2 = na | |
var line spikeLine3 = na | |
if i_isSnRSpike and exhaustVol and sProcessing | |
if bullCandle | |
if i_spLnBullLevel == 'High' | |
if exhaustVol == exhaustVol[1] and not bearCandle[1] | |
line.delete(spikeLine[1]) | |
spikeLine := line.new(x1V, high, x2, high, xloc.bar_time, extend.none, i_spLnColor, f_getStyle(i_spLnStyle), i_spLnWidth) | |
spikeLine | |
else if i_spLnBullLevel == 'Close' | |
if exhaustVol == exhaustVol[1] and not bearCandle[1] | |
line.delete(spikeLine[1]) | |
spikeLine := line.new(x1V, close, x2, close, xloc.bar_time, extend.none, i_spLnColor, f_getStyle(i_spLnStyle), i_spLnWidth) | |
spikeLine | |
else | |
if exhaustVol == exhaustVol[1] and not bearCandle[1] | |
line.delete(spikeLine1[1]), line.delete(spikeLine2[1]), line.delete(spikeLine3[1]) | |
spikeLine1 := line.new(x1V, close, x2, close, xloc.bar_time, extend.none, i_spLnColor, f_getStyle(i_spLnStyle), i_spLnWidth) | |
spikeLine2 := line.new(x1V, math.avg(high, close), x2, math.avg(high, close), xloc.bar_time, extend.none, i_spLnColor, f_getStyle('Dotted'), i_spLnWidth - 1) | |
spikeLine3 := line.new(x1V, high, x2, high, xloc.bar_time, extend.none, i_spLnColor, f_getStyle(i_spLnStyle), i_spLnWidth) | |
spikeLine3 | |
if bearCandle | |
if i_spLnBearLevel == 'Low' | |
if exhaustVol == exhaustVol[1] and not bullCandle[1] | |
line.delete(spikeLine[1]) | |
spikeLine := line.new(x1V, low, x2, low, xloc.bar_time, extend.none, i_spLnColor, f_getStyle(i_spLnStyle), i_spLnWidth) | |
spikeLine | |
else if i_spLnBearLevel == 'Close' | |
if exhaustVol == exhaustVol[1] and not bullCandle[1] | |
line.delete(spikeLine[1]) | |
spikeLine := line.new(x1V, close, x2, close, xloc.bar_time, extend.none, i_spLnColor, f_getStyle(i_spLnStyle), i_spLnWidth) | |
spikeLine | |
else | |
if exhaustVol == exhaustVol[1] and not bullCandle[1] | |
line.delete(spikeLine1[1]), line.delete(spikeLine2[1]), line.delete(spikeLine3[1]) | |
spikeLine1 := line.new(x1V, low, x2, low, xloc.bar_time, extend.none, i_spLnColor, f_getStyle(i_spLnStyle), i_spLnWidth) | |
spikeLine2 := line.new(x1V, math.avg(low, close), x2, math.avg(low, close), xloc.bar_time, extend.none, i_spLnColor, f_getStyle('Dotted'), i_spLnWidth - 1) | |
spikeLine3 := line.new(x1V, close, x2, close, xloc.bar_time, extend.none, i_spLnColor, f_getStyle(i_spLnStyle), i_spLnWidth) | |
spikeLine3 | |
plotchar(i_vSpikeLb and nzVolume and sProcessing ? exhaustVol : na, 'Exhaustion Bar', '🚦', location.abovebar, size=size.tiny) | |
alertcondition(ta.crossover(nzVolume, i_vSMA * i_vSpikeThresh), 'Volume Spikes', 'sign of exhaustion, huge volume increase detected\n{{exchange}}:{{ticker}}->\nOpen = {{open}}, Current = {{close}},\nTime = {{time}}') | |
// ---------------------------------------------------------------------------------------------- // | |
// High Volatility ------------------------------------------------------------------------------ // | |
var line volatileLine = na | |
var line volatileLine1 = na | |
var line volatileLine2 = na | |
var line volatileLine3 = na | |
if i_hATRLn and highVolatility and sProcessing | |
if bullCandle | |
if i_haLnBullLevel == 'High' | |
if highVolatility == highVolatility[1] and not bearCandle[1] | |
line.delete(volatileLine[1]) | |
volatileLine := line.new(x1hV, high, x2, high, xloc.bar_time, extend.none, i_hATRLnColor, f_getStyle(i_hATRLnStyle), i_hATRLnWidth) | |
volatileLine | |
else if i_haLnBullLevel == 'Close' | |
if highVolatility == highVolatility[1] and not bearCandle[1] | |
line.delete(volatileLine[1]) | |
volatileLine := line.new(x1hV, close, x2, close, xloc.bar_time, extend.none, i_hATRLnColor, f_getStyle(i_hATRLnStyle), i_hATRLnWidth) | |
volatileLine | |
else | |
if highVolatility == highVolatility[1] and not bearCandle[1] | |
line.delete(volatileLine1[1]), line.delete(volatileLine2[1]), line.delete(volatileLine3[1]) | |
volatileLine1 := line.new(x1hV, close, x2, close, xloc.bar_time, extend.none, i_hATRLnColor, f_getStyle(i_hATRLnStyle), i_hATRLnWidth) | |
volatileLine2 := line.new(x1hV, math.avg(high, close), x2, math.avg(high, close), xloc.bar_time, extend.none, i_hATRLnColor, f_getStyle('Dotted'), i_hATRLnWidth - 1) | |
volatileLine3 := line.new(x1hV, high, x2, high, xloc.bar_time, extend.none, i_hATRLnColor, f_getStyle(i_hATRLnStyle), i_hATRLnWidth) | |
volatileLine3 | |
if bearCandle | |
if i_haLnBearLevel == 'Low' | |
if highVolatility == highVolatility[1] and not bullCandle[1] | |
line.delete(volatileLine[1]) | |
volatileLine := line.new(x1hV, low, x2, low, xloc.bar_time, extend.none, i_hATRLnColor, f_getStyle(i_hATRLnStyle), i_hATRLnWidth) | |
volatileLine | |
else if i_haLnBearLevel == 'Close' | |
if highVolatility == highVolatility[1] and not bullCandle[1] | |
line.delete(volatileLine[1]) | |
volatileLine := line.new(x1hV, close, x2, close, xloc.bar_time, extend.none, i_hATRLnColor, f_getStyle(i_hATRLnStyle), i_hATRLnWidth) | |
volatileLine | |
else | |
if highVolatility == highVolatility[1] and not bullCandle[1] | |
line.delete(volatileLine1[1]), line.delete(volatileLine2[1]), line.delete(volatileLine3[1]) | |
volatileLine1 := line.new(x1hV, low, x2, low, xloc.bar_time, extend.none, i_hATRLnColor, f_getStyle(i_hATRLnStyle), i_hATRLnWidth) | |
volatileLine2 := line.new(x1hV, math.avg(low, close), x2, math.avg(low, close), xloc.bar_time, extend.none, i_hATRLnColor, f_getStyle('Dotted'), i_hATRLnWidth - 1) | |
volatileLine3 := line.new(x1hV, close, x2, close, xloc.bar_time, extend.none, i_hATRLnColor, f_getStyle(i_hATRLnStyle), i_hATRLnWidth) | |
volatileLine3 | |
plotchar(i_hATRLb and sProcessing ? highVolatility : na, 'High Volatile Bar', '⚡', location.belowbar, size=size.tiny) | |
alertcondition(ta.crossover(range_1, weightedATR), 'High Volatility', 'high volatility detected\n{{exchange}}:{{ticker}}->\nOpen = {{open}}, Current = {{close}},\nTime = {{time}}') | |
// ---------------------------------------------------------------------------------------------- // | |
// Volume Weighted Colored Bars ----------------------------------------------------------------- // | |
barcolor(i_vwcb and nzVolume ? vwcbCol : na, title='Volume Weighted Colored Bars') | |
// ---------------------------------------------------------------------------------------------- // | |
// Volume Profile (Price by Volume) ------------------------------------------------------------ // | |
group_volume_profile = 'Volume Profile / Price by Volume' | |
tooltip_volume_profile = 'Volume Profile (also known as Price by Volume) is an charting study that displays trading activity over a specified time period at specific price levels' | |
volumeProfile = input.bool(true, group = group_volume_profile, tooltip = tooltip_volume_profile) | |
lookbackLength = input.int(360, 'Lookback Length', minval = 10, maxval = 500, step = 10, inline = 'VP', group = group_volume_profile) | |
profileLevels = input.int(100, 'Number of Rows' , minval = 10, maxval = 500, step = 10, inline = 'VP', group = group_volume_profile) | |
priceHighest = ta.highest(high, lookbackLength) | |
priceLowest = ta.lowest (low , lookbackLength) | |
barPriceLow = low | |
barPriceHigh = high | |
volumeStorage = array.new_float(profileLevels + 1, 0.) | |
var a_box = array.new_box() | |
if barstate.islast and nzVolume and volumeProfile | |
if array.size(a_box) > 0 | |
for i = 1 to array.size(a_box) | |
box.delete(array.shift(a_box)) | |
priceStep = (priceHighest - priceLowest) / profileLevels | |
for barIndex = 0 to lookbackLength - 1 | |
level = 0 | |
for priceLevel = priceLowest to priceHighest by priceStep | |
if barPriceHigh[barIndex] >= priceLevel and barPriceLow[barIndex] < priceLevel + priceStep | |
array.set(volumeStorage, level, array.get(volumeStorage, level) + nzVolume[barIndex] * (timeframe.isseconds or (barPriceHigh[barIndex] - barPriceLow[barIndex]) == 0 ? 1 : priceStep / (barPriceHigh[barIndex] - barPriceLow[barIndex])) )//* (1 - (barPriceHigh[barIndex] - barPriceLow[barIndex]) / (priceHighest - priceLowest) ) ) | |
level += 1 | |
for level = 0 to profileLevels - 1 | |
levelColor = array.get(volumeStorage, level) / array.max(volumeStorage) > .9 ? color.new(color.orange, 69) : color.new(color.gray, 69) | |
array.push(a_box, box.new( bar_index + 49 - int( array.get(volumeStorage, level) / array.max(volumeStorage) * 41), priceLowest + (level + 0.25) * priceStep, bar_index + 50, priceLowest + (level + 0.75) * priceStep, levelColor, bgcolor = levelColor )) | |
array.push(a_box, box.new(bar_index - lookbackLength + 1, priceLowest, bar_index + 50, priceHighest, color.new(color.gray, 37), 2, line.style_dotted, bgcolor=#00000000 )) | |
// Volume Profile (Price by Volume) ------------------------------------------------------------ // | |
// ---------------------------------------------------------------------------------------------- // | |
var table logo = table.new(position.bottom_right, 1, 1) | |
if barstate.islast | |
table.cell(logo, 0, 0, '☼☾ ', text_size=size.normal, text_color=color.teal) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment