-
Notifications
You must be signed in to change notification settings - Fork 10
/
Abnormal Volume Scanner
100 lines (88 loc) · 7.26 KB
/
Abnormal Volume Scanner
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// =============================================================================================================
// This Pine Script™ is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License.
// To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/4.0/ or send a letter to
// Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
// =============================================================================================================
// github @ 2LV, telegram @ nqmicro, discord @ nqmicro
//@version=5
indicator("Abnormal Volume Scanner", overlay=false, max_lines_count = 500, precision=0, format=format.volume)
// inputs
growingColor = input.color(defval = color.rgb(127, 255, 189, 25), title = 'Growing Volume Color', group = 'Volume Personalization')
fallingColor = input.color(defval = color.rgb(254, 87, 101, 25), title = 'Falling Volume Color', group = 'Volume Personalization')
neutralColor = input.color(defval = color.rgb(255, 255, 255, 25), title = 'Neutral Volume Color', group = 'Volume Personalization')
prevVolBar = input.bool(defval = false, title = 'Color based On Previous Volume', tooltip = 'Base volume color off the previous volume bar instead of OHLC values', group = 'Volume Personalization')
volMA = input.bool(defval = false, title = 'Enable Volume Moving Average', group = 'Volume Moving Average')
volMAColor = input.color(defval = color.rgb(255, 255, 255), title = 'Moving Average Color', group = 'Volume Moving Average')
volMALength = input.int(defval = 20, minval = 1, title = 'Moving Average Length', group = 'Volume Moving Average')
abnormalVolSpike = input.bool(defval = true, title = 'Enable Abnormal Volume Spike', group = 'Abnormal Volume')
abnormalVolLoss = input.bool(defval = true, title = 'Enable Abnormal Volume Loss', group = 'Abnormal Volume')
plotabnormalVolSpikeShape = input.bool(defval = false, title="Plot Shapes On Abnormal", tooltip = 'Plots a shape on any abnormal volume bars (change color and shape under style tab)', group='Abnormal Volume')
abnormalVolSpikeColor = input.color(defval = color.rgb(0, 136, 255, 25), title = 'Abnormal High Volume Color', tooltip = 'The color of the abnormal volume bar (does not change color if "Plot Shapes" is enabled)', group = 'Abnormal Volume')
abnormalVolLossColor = input.color(defval = color.rgb(255, 0, 204, 25), title = 'Abnormal Low Volume Color', tooltip = 'The color of the abnormal volume bar (does not change color if "Plot Shapes" is enabled)', group = 'Abnormal Volume')
abnormalVolSpikeCandles = input.int(defval = 3, minval = 1, title = 'Tracked Candles', tooltip = 'The average of X amount of past candle volume', group = 'Abnormal Volume')
abnormalVolSpikeMultiplier = input.float(defval = 0.4, minval = 0, title = 'Abnormal Volume Multiplier', tooltip = 'X amount multipier necessary to be considered abnormal (es. 0.3 means 1.3x multipler for abnormal spike or 0.7x for abnormal loss)', group = 'Abnormal Volume')
increasingVolume = input.bool(defval = true, title = 'Enable Increasing Volume', group = 'Increasing/Decreasing Volume')
IVColor = input.color(defval = color.rgb(90, 255, 170, 25), title = 'Increasing Volume Line Color', group = 'Increasing/Decreasing Volume')
decreasingVolume = input.bool(defval = true, title = 'Enable Decreasing Volume', group = 'Increasing/Decreasing Volume')
DVColor = input.color(defval = color.rgb(242, 54, 70, 25), title = 'Decreasing Volume Line Color', group = 'Increasing/Decreasing Volume')
consecutiveCandlesLimit = input.int(defval = 3, minval = 1, title = 'Consecutive Candle Requirement', tooltip = 'How many candle required in a row to be considered increasing/decreasing volume', group = 'Increasing/Decreasing Volume') - 1
minVolChange = input.float(defval = 0.05, minval = 0.01, title = 'Minimum Volume Change', tooltip = 'Amount of change in volume per candle required (ex. 0.1 needs 10% more/less in change of volume per candle)', group = 'Increasing/Decreasing Volume')
maxVolChange = input.float(defval = 0.3, minval = 0.01, title = 'Maximum Volume Change', tooltip = 'Maximum amount of change in volume per candle allowed (ex. 0.5 limits to 50% more/less in change of volume per candle)', group = 'Increasing/Decreasing Volume')
// variables
greenCandle = open < close
redCandle = open > close
neutralCandle = open == close
color candleColor = na
AVSVolReq = ta.sma(volume, abnormalVolSpikeCandles) * (1 + abnormalVolSpikeMultiplier)
AVLVolReq = ta.sma(volume, abnormalVolSpikeCandles) * (1 - abnormalVolSpikeMultiplier)
var line mostRecentDVLine = na
var line mostRecentIVLine = na
greenVol = (greenCandle and not prevVolBar) or (volume[1] < volume and prevVolBar)
redVol = (redCandle and not prevVolBar) or (volume[1] > volume and prevVolBar)
neutralVol = (neutralCandle and not prevVolBar) or (volume[1] == volume and prevVolBar)
volSpike = volume > AVSVolReq
volLoss = volume < AVLVolReq
// assign colors
if greenVol
candleColor := growingColor
if redVol
candleColor := fallingColor
if neutralVol
candleColor := neutralColor
if volSpike and abnormalVolSpike and not plotabnormalVolSpikeShape
candleColor := abnormalVolSpikeColor
if volLoss and abnormalVolLoss and not plotabnormalVolSpikeShape
candleColor := abnormalVolLossColor
// detect decreasing/increasing volume
DVStartIndex = 1
IVStartIndex = 1
while true
if volume[DVStartIndex] > volume[DVStartIndex - 1] and volume[DVStartIndex] * (1-minVolChange) >= volume[DVStartIndex - 1] and volume[DVStartIndex] * (1-maxVolChange) <= volume[DVStartIndex - 1]
DVStartIndex += 1
int(na)
else
break
int(na)
while true
if volume[IVStartIndex] < volume[IVStartIndex - 1] and volume[IVStartIndex] * (1+minVolChange) <= volume[IVStartIndex - 1] and volume[IVStartIndex] * (1+maxVolChange) >= volume[IVStartIndex - 1]
IVStartIndex += 1
int(na)
else
break
int(na)
DVStartIndex -= 1
IVStartIndex -= 1
// plotting
plot(volume, color=candleColor, style=plot.style_columns, precision = 0, editable = false)
plotshape(volume > AVSVolReq and plotabnormalVolSpikeShape, style=shape.circle, location = location.bottom)
plot(volMA ? ta.sma(volume, volMALength) : na, color=volMAColor, style=plot.style_line, display=display.all - display.price_scale, editable = false)
if DVStartIndex >= consecutiveCandlesLimit and decreasingVolume and (na(mostRecentDVLine) or line.get_x1(mostRecentDVLine) != time[DVStartIndex])
mostRecentDVLine := line.new(time[DVStartIndex], volume[DVStartIndex] * 1.05, time, volume * 1.05, color = DVColor, width = 2, xloc=xloc.bar_time)
else if DVStartIndex >= consecutiveCandlesLimit and decreasingVolume and not na(mostRecentDVLine) and line.get_x1(mostRecentDVLine) == time[DVStartIndex]
line.set_x2(mostRecentDVLine, time)
line.set_y2(mostRecentDVLine, volume)
if IVStartIndex >= consecutiveCandlesLimit and increasingVolume and (na(mostRecentIVLine) or line.get_x1(mostRecentIVLine) != time[IVStartIndex])
mostRecentIVLine := line.new(time[IVStartIndex], volume[IVStartIndex] * 1.05, time, volume * 1.05, color = IVColor, width = 2, xloc=xloc.bar_time)
else if IVStartIndex >= consecutiveCandlesLimit and increasingVolume and not na(mostRecentIVLine) and line.get_x1(mostRecentIVLine) == time[IVStartIndex]
line.set_x2(mostRecentIVLine, time)
line.set_y2(mostRecentIVLine, volume)