-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathBollinger Bands + Keltner Channel Refurbished.pine
461 lines (382 loc) · 28.4 KB
/
Bollinger Bands + Keltner Channel Refurbished.pine
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
// @version=5
// @author=andre_007
// Credits:
// - TradingView (BB, KC, ATR, MA's)
// - everget (Regularized Exponential Moving Average)
// - TimeFliesBuy ("Triple Bollinger Bands")
// - Rashad ("Fibonacci Bollinger Bands")
// - Dicargo_Beam ("Is the Bollinger Bands assumption wrong?")
// - MightyZinger (Some Moving Averages)
// - CrackingCryptocurrency (MA's)
// - PineCoders (Benchmark)
// - paragjyoti2012 (debug)
// - Franklin Moormann (cheatcountry)
indicator("Bollinger Bands + Keltner Channel Refurbished", shorttitle='BB+KC Refurbished', format=format.price, precision=2, overlay=true)
import andre_007/MovingAveragesProxy/2 as MaProxy
// ———————————————————————————————————————— Only for benchmark {
// import PineCoders/LibraryStopwatch/1 as Stopwatch // Only for debug
// [timePerBarInMs, totalTimeInMs, barsTimed, barsNotTimed] = Stopwatch.stopwatchStats()
// msElapsed = Stopwatch.stopwatch()
// ———————————————————————————————————————— }
// ———————————————————————————————————————— Only for Debug {
// import paragjyoti2012/LoggerLib/5 as Logger
// var logger=Logger.init()
// var logTable=Logger.initTable(logger, max_rows_count=15, offset=0, position='left', size='small', hide_date=false, stickyRows=0)
// ———————————————————————————————————————— }
// ———————————————————————————————————————— Constants {
// Moving Averages Types
var string AARMA = 'Adaptive Autonomous Recursive Moving Average'
var string ADEMA = '* Alpha-Decreasing Exponential Moving Average'
var string AHMA = 'Ahrens Moving Average'
var string ALMA = 'Arnaud Legoux Moving Average'
var string ALSMA = 'Adaptive Least Squares'
var string AUTOL = 'Auto-Line'
var string CMA = 'Corrective Moving average'
var string CORMA = 'Correlation Moving Average Price'
var string COVWEMA = 'Coefficient of Variation Weighted Exponential Moving Average'
var string COVWMA = 'Coefficient of Variation Weighted Moving Average'
var string DEMA = 'Double Exponential Moving Average'
var string DONCHIAN = 'Donchian Middle Channel'
var string DONCHIAN_HL = 'Donchian Middle Channel High-Low Version'
var string EDMA = 'Exponentially Deviating Moving Average'
var string EDSMA = 'Ehlers Dynamic Smoothed Moving Average'
var string EFRAMA = '* Ehlrs Modified Fractal Adaptive Moving Average'
var string EHMA = 'Exponential Hull Moving Average'
var string EMA = 'Exponential Moving Average'
var string EPMA = 'End Point Moving Average'
var string ETMA = 'Exponential Triangular Moving Average'
var string EVWMA = 'Elastic Volume Weighted Moving Average'
var string FAMA = 'Following Adaptive Moving Average'
var string FIBOWMA = 'Fibonacci Weighted Moving Average'
var string FISHLSMA = 'Fisher Least Squares Moving Average'
var string FRAMA = 'Fractal Adaptive Moving Average'
var string GMA = 'Geometric Moving Average'
var string HKAMA = 'Hilbert based Kaufman\'s Adaptive Moving Average'
var string HMA = 'Hull Moving Average'
var string JURIK = 'Jurik Moving Average'
var string KAMA = 'Kaufman\'s Adaptive Moving Average'
var string LC_LSMA = '1LC-LSMA (1 line code lsma with 3 functions)'
var string LEOMA = 'Leo Moving Average'
var string LINWMA = 'Linear Weighted Moving Average'
var string LSMA = 'Least Squares Moving Average'
var string MAMA = 'MESA Adaptive Moving Average'
var string MCMA = 'McNicholl Moving Average'
var string MEDIAN = 'Median'
var string REGMA = 'Regularized Exponential Moving Average'
var string REMA = 'Range EMA'
var string REPMA = 'Repulsion Moving Average'
var string RMA = 'Relative Moving Average'
var string RSIMA = 'RSI Moving average'
var string RVWAP = '* Rolling VWAP'
var string SMA = 'Simple Moving Average'
var string SMMA = 'Smoothed Moving Average'
var string SRWMA = 'Square Root Weighted Moving Average'
var string SW_MA = 'Sine-Weighted Moving Average'
var string SWMA = '* Symmetrically Weighted Moving Average'
var string TEMA = 'Triple Exponential Moving Average'
var string THMA = 'Triple Hull Moving Average'
var string TREMA = 'Triangular Exponential Moving Average'
var string TRSMA = 'Triangular Simple Moving Average'
var string TT3 = 'Tillson T3'
var string VAMA = 'Volatility Adjusted Moving Average'
var string VIDYA = 'Variable Index Dynamic Average'
var string VWAP = '* VWAP'
var string VWMA = 'Volume-weighted Moving Average'
var string WMA = 'Weighted Moving Average'
var string WWMA = 'Welles Wilder Moving Average'
var string XEMA = 'Optimized Exponential Moving Average'
var string ZEMA = 'Zero-Lag Exponential Moving Average'
var string ZSMA = 'Zero-Lag Simple Moving Average'
// ———————————————————————————————————————— }
// ———————————————————————————————————————— Inputs {
src = input.source(defval=hl2, title='Source', inline='1')
var string typeIndicator = input.string(defval='Bollinger Bands', title='Indicator',
options=['Bollinger Bands', 'Keltner Channel', 'Parallel Channels'], inline='1')
var string stDevSrc = input.string(defval='Price', title='Standard Deviation Source for Bollinger Bands',
options=['Price', 'MA'], inline='1', tooltip='Price or Moving Average')
var string typeMa = input.string(defval=REGMA, title='MA',
options=[AARMA,ALSMA,AHMA,ADEMA,ALMA,AUTOL,COVWEMA,COVWMA,CMA,CORMA,DEMA,DONCHIAN,DONCHIAN_HL,EFRAMA,EDSMA,EVWMA,EPMA,EDMA,EHMA,EMA,ETMA,FIBOWMA,FISHLSMA,FAMA,FRAMA,GMA,HKAMA,HMA,JURIK,KAMA,LC_LSMA,LEOMA,LSMA,LINWMA,MEDIAN,MAMA,MCMA,XEMA,REMA,REGMA,RMA,REPMA,RVWAP,RSIMA,SMA,SW_MA,SRWMA,SMMA,SWMA,TT3,TREMA,TRSMA,TEMA,THMA,VIDYA,VAMA,VWAP,WMA,WWMA,ZEMA,ZSMA],
inline='2')
length = input.int(233, minval=1, inline='2', title='Length', tooltip='For moving averages with * the length parameter does not apply')
multiplier = input.float(1, minval=0.001, title='Multiplier', inline='2')
parallelChannelsDivisor = input.int(24, minval=1, inline='2a', title='Parallel Channels Divisor', tooltip='Only for Parallel Channels')
bandsStyleKC = input.string("Average True Range", options = ["Average True Range", "True Range", "Range"], title="Bands Style", inline='3', group='Exclusive for Keltner Channel')
atrlength = input(10, "ATR Length", inline='3', group='Exclusive for Keltner Channel')
// ————————————————— Parameters exclusive for some MA's {
var string GRP_AARMA = 'Adaptive Autonomous Recursive Moving Average'
var float gamma_aarma = input.float(3, "Gamma", group=GRP_AARMA)
var string GRP_ALSMA = 'Adaptive Least Squares Moving Average'
var float smooth = input.float(1.5, "Smooth", group=GRP_ALSMA)
var string GROUP_ALMA = 'Arnaud Legoux Moving Average (ALMA)'
var string TOOLTIP_ALMA = '◆ Offset: this is considered in the formula, not in the graphic! Offset is the Gaussian applied to the combo line and it is 0.85 by default.\nSetting offset at 1 makes it fully aligned to the current price just like the exponential moving average.\nWhile setting it to zero makes it just like a simple moving average.\nTraders may try offset combinations according to their own needs and preferences.\n\n◆ Sigma: the standard deviation applied to the combo line. It makes the combo line sharper.'
var string TOOLTIP_COLOR_AVERAGE = 'Examples:\n🟩 Moving average 1 > moving average 2 is defined by green.\n🟥 Moving average 1 < moving average 2 is defined by red.'
inputAlmaOffset = input.float(title='Offset', defval=0.85, group=GROUP_ALMA, inline='04')
inputAlmaSigma = input.float(title='Sigma', defval=6, group=GROUP_ALMA, inline='04', tooltip=TOOLTIP_ALMA)
var string GRP_CORR = 'Correlation Moving Average'
var string GRP_CORR_TOOLTIP = 'Number multiplied after calculating correlation + standard deviation.'
var float factor = input.float(1.7, "Factor", group=GRP_CORR, tooltip=GRP_CORR_TOOLTIP)
var string GRP_EHLR = 'Ehlrs Modified Fractal Adaptive Moving Average'
var int fc = input.int(8, 'Lower Shift Limit', group=GRP_EHLR)
var int sc = input.int(8, 'Upper Shift Limit', group=GRP_EHLR)
var string GRP_EPMA = 'End Point Moving Average'
offset_epma = input.int(title="Offset", defval=4, group=GRP_EPMA)
var string GRP_JURIK = 'Jurik Moving Average'
var int jurik_phase = input.int(3, "Phase", group=GRP_JURIK)
var int jurik_power = input.int(1, "Power", group=GRP_JURIK)
var string GRP_LWMA = 'Linear Weighted Moving Average'
lwma_weight = input.int(6, title = "Weight", minval=1, step=1, group=GRP_LWMA)
var string GRP_REGMA = 'Regularized Exponential Moving Average'
var string GRP_REGMA_TOOLTIP = 'A factor that controls the \"regularization\" amount. When the Lambda value is set to zero, the Regularized Exponential Moving Average becomes the standard EMA.'
var float lambda = input.float(0.5, "Lambda", group=GRP_REGMA, tooltip=GRP_REGMA_TOOLTIP)
var string GRP_RVWAP = 'Rolling VWAP'
var string TT_WINDOW = "By default, the time period used to calculate the RVWAP automatically adjusts with the chart's timeframe.
Check this to use a fixed-size time period instead, which you define with the following three values."
var string TT_MINBARS = "The minimum number of last values to keep in the moving window, even if these values are outside the time period.
This avoids situations where a large time gap between two bars would cause the time window to be empty."
bool _fixedTfInput = input.bool(false, "Use a fixed time period", group = GRP_RVWAP, tooltip = TT_WINDOW, inline='1')
int _daysInput = input.int(1, "Days", minval = 0, maxval = 90, group = GRP_RVWAP, inline='2')
int _hoursInput = input.int(0, "Hours", minval = 0, maxval = 23, group = GRP_RVWAP, inline='2')
int _minsInput = input.int(0, "Minutes", minval = 0, maxval = 59, group = GRP_RVWAP, inline='2')
int _minBarsInput = input.int(10, "Bars", group = GRP_RVWAP, tooltip = TT_MINBARS, inline='3')
var string GRP_T3 = 'Tillson T3'
var float a1_t3 = input.float(0.7, 'Volume factor', group=GRP_T3)
var string GRP_VADMA = 'Volatility Adjusted Moving Average'
var string GRP_VADMA_TOOLTIP = 'Volatility loopback'
var int volatility_lookback = input.int(10, 'Loopback', minval=1, step=1, group=GRP_VADMA, tooltip=GRP_VADMA_TOOLTIP)
var string GRP_VWMA = 'Volume Weighted Moving Average'
var string GRP_VWMA_TOOLTIP = 'The most common "Volume Weighted Moving Average" is a Simple Moving Average of Price x Volume, divided by Simple Moving Average of Volume. \n' +
'Enabling this checkbox, it\'s possible to have other types and less common moving averages weighted by volume, for example, Exponencial Volume Weighted Moving Average, Alma Volume Weighted Moving Average, etc...'
applyVolumeWeighted = input.bool(title="Volume Weighted Moving Average?", defval=false, group=GRP_VWMA, tooltip=GRP_VWMA_TOOLTIP)
// ————————————————— }
band1 = input.float(0.236, minval=0.000, step=0.2, title='Band 1', inline='1', group='Bands')
band2 = input.float(0.5, minval=0.000, step=0.2, title='Band 2', inline='1', group='Bands', tooltip='Enter zero if you don\'t want a certain band to appear')
band3 = input.float(0.786, minval=0.000, step=0.2, title='Band 3', inline='2', group='Bands')
band4 = input.float(1, minval=0.000, step=0.2, title='Band 4', inline='2', group='Bands')
band5 = input.float(1.236, minval=0.000, step=0.2, title='Band 5', inline='3', group='Bands')
band6 = input.float(1.5, minval=0.000, step=0.2, title='Band 6', inline='3', group='Bands')
band7 = input.float(1.786, minval=0.000, step=0.2, title='Band 7', inline='4', group='Bands')
band8 = input.float(2, minval=0.000, step=0.2, title='Band 8', inline='4', group='Bands')
band9 = input.float(2.236, minval=0.000, step=0.2, title='Band 9', inline='5', group='Bands')
band10 = input.float(2.5, minval=0.000, step=0.2, title='Band 10', inline='5', group='Bands')
band11 = input.float(2.786, minval=0.000, step=0.2, title='Band 11', inline='6', group='Bands')
band12 = input.float(3, minval=0.000, step=0.2, title='Band 12', inline='6', group='Bands')
var string GROUP_AVERAGE_COLORS = 'Colors and theme'
var string inputFill = input.string(title='Fill background between bands?', options=['Always', 'When price inside channel', 'Never'], group=GROUP_AVERAGE_COLORS, defval='When price inside channel')
var color colorBandUp1 = input.color(color.new(#1aa814, 0), 'Upper band 1', group=GROUP_AVERAGE_COLORS, inline='UP')
var color colorBandUp2 = input.color(color.new(#00bcd4, 0), 'Upper band 2', group=GROUP_AVERAGE_COLORS, inline='UP')
var color colorBandUp3 = input.color(color.new(#0036ff, 0), 'Upper band 3', group=GROUP_AVERAGE_COLORS, inline='UP')
var color colorBandDown1 = input.color(color.new(#f57f17, 0), 'Lower band 1', group=GROUP_AVERAGE_COLORS, inline='DOWN')
var color colorBandDown2 = input.color(color.new(#e91e63, 0), 'Lower band 2', group=GROUP_AVERAGE_COLORS, inline='DOWN')
var color colorBandDown3 = input.color(color.new(#b800d8, 0), 'Lower band 3', group=GROUP_AVERAGE_COLORS, inline='DOWN')
var inputColorFillTransparency = input.int(defval=80 , title="Transparency for fill", minval=0, maxval=100, group=GROUP_AVERAGE_COLORS)
var bool inputChangeColor = input.bool(title='Change base color when bullish/\bearish?', defval=false, group=GROUP_AVERAGE_COLORS)
color inputColorBull = input.color(color.new(#3af13c, 0), 'Bull', group=GROUP_AVERAGE_COLORS, inline='Base')
color inputColorBear = input.color(color.new(#ff0000, 0), 'Bear', group=GROUP_AVERAGE_COLORS, inline='Base')
var color colorDefault = input.color(color.new(color.white, 0), 'Default', group=GROUP_AVERAGE_COLORS, inline='Base')
var xloc_labels = input.int(defval=100, title='Position of Labels (x)', group=GROUP_AVERAGE_COLORS, inline='Labels', tooltip = 'Last bar + x')
// ———————————————————————————————————————— }
// ———————————————————————————————————————— Error Handling {
// For VWAP: stop the indicator on charts with no volume
if (typeMa == VWAP or typeMa == RVWAP) and barstate.islast and ta.cum(nz(volume)) == 0
runtime.error("No volume is provided by the data vendor.")
// ———————————————————————————————————————— }
// ———————————————————————————————————————— Calcs {
basis = MaProxy.getMovingAverage(
type=typeMa, src=src, len=length,
lsmaOffset=0,
inputAlmaOffset=inputAlmaOffset, inputAlmaSigma=inputAlmaSigma,
FC=fc, SC=sc,
a1_t3=a1_t3,
fixedTfInput=_fixedTfInput, daysInput=_daysInput, hoursInput=_hoursInput, minsInput=_minsInput, minBarsInput=_minBarsInput,
lambda=lambda,
factor=factor,
offset_epma=offset_epma,
volumeWeighted=applyVolumeWeighted,
gamma_aarma=gamma_aarma,
smooth=smooth,
linweight=lwma_weight,
volatility_lookback=volatility_lookback,
jurik_phase=jurik_phase,
jurik_power=jurik_power)
float rangeMA = na
deviation = if typeIndicator == 'Bollinger Bands'
multiplier * ta.stdev(stDevSrc == 'Price' ? src : basis, length)
else if typeIndicator == 'Keltner Channel'
rangeMA := bandsStyleKC == "True Range" ? ta.tr(true) : bandsStyleKC == "Average True Range" ? ta.atr(atrlength) : ta.rma(high - low, length)
multiplier * rangeMA
else if typeIndicator == 'Parallel Channels'
// With Donchian the logic is duplicated
band_width = if (typeMa == DONCHIAN or typeMa == DONCHIAN_HL)
multiplier * basis/parallelChannelsDivisor
else
pretop = ta.highest(high, length)
prebottom = ta.lowest(low, length)
top = MaProxy.getMovingAverage(
type=typeMa, src=pretop, len=length,
lsmaOffset=0,
inputAlmaOffset=inputAlmaOffset, inputAlmaSigma=inputAlmaSigma,
FC=fc, SC=sc,
a1_t3=a1_t3,
fixedTfInput=_fixedTfInput, daysInput=_daysInput, hoursInput=_hoursInput, minsInput=_minsInput, minBarsInput=_minBarsInput,
lambda=lambda,
factor=factor,
offset_epma=offset_epma,
volumeWeighted=applyVolumeWeighted,
gamma_aarma=gamma_aarma,
smooth=smooth,
linweight=lwma_weight,
volatility_lookback=volatility_lookback,
jurik_phase=jurik_phase,
jurik_power=jurik_power)
bottom = MaProxy.getMovingAverage(
type=typeMa, src=prebottom, len=length,
lsmaOffset=0,
inputAlmaOffset=inputAlmaOffset, inputAlmaSigma=inputAlmaSigma,
FC=fc, SC=sc,
a1_t3=a1_t3,
fixedTfInput=_fixedTfInput, daysInput=_daysInput, hoursInput=_hoursInput, minsInput=_minsInput, minBarsInput=_minBarsInput,
lambda=lambda,
factor=factor,
offset_epma=offset_epma,
volumeWeighted=applyVolumeWeighted,
gamma_aarma=gamma_aarma,
smooth=smooth,
linweight=lwma_weight,
volatility_lookback=volatility_lookback,
jurik_phase=jurik_phase,
jurik_power=jurik_power)
multiplier * (top - bottom)/parallelChannelsDivisor
upper_1 = band1 > 0 ? basis + (band1*deviation) : na
upper_2 = band2 > 0 ? basis + (band2*deviation) : na
upper_3 = band3 > 0 ? basis + (band3*deviation) : na
upper_4 = band4 > 0 ? basis + (band4*deviation) : na
upper_5 = band5 > 0 ? basis + (band5*deviation) : na
upper_6 = band6 > 0 ? basis + (band6*deviation) : na
upper_7 = band7 > 0 ? basis + (band7*deviation) : na
upper_8 = band8 > 0 ? basis + (band8*deviation) : na
upper_9 = band9 > 0 ? basis + (band9*deviation) : na
upper_10 = band10 > 0 ? basis + (band10*deviation) : na
upper_11 = band11 > 0 ? basis + (band11*deviation) : na
upper_12 = band12 > 0 ? basis + (band12*deviation) : na
lower_1 = band1 > 0 ? basis - (band1*deviation) : na
lower_2 = band2 > 0 ? basis - (band2*deviation) : na
lower_3 = band3 > 0 ? basis - (band3*deviation) : na
lower_4 = band4 > 0 ? basis - (band4*deviation) : na
lower_5 = band5 > 0 ? basis - (band5*deviation) : na
lower_6 = band6 > 0 ? basis - (band6*deviation) : na
lower_7 = band7 > 0 ? basis - (band7*deviation) : na
lower_8 = band8 > 0 ? basis - (band8*deviation) : na
lower_9 = band9 > 0 ? basis - (band9*deviation) : na
lower_10 = band10 > 0 ? basis - (band10*deviation) : na
lower_11 = band11 > 0 ? basis - (band11*deviation) : na
lower_12 = band12 > 0 ? basis - (band12*deviation) : na
// ———————————————————————————————————————— }
// ———————————————————————————————————————— Functions {
f_changeLineColor(series float _line) =>
color _color = if inputChangeColor
if src >= _line
inputColorBull
else
inputColorBear
else
colorDefault
// ———————————————————————————————————————— }
// ———————————————————————————————————————— Plots {
pBasis = plot(basis, title='Moving Average', color=f_changeLineColor(basis), linewidth=3)
pUpper1 = plot(upper_1 , color=color.new(colorBandUp1, 50), linewidth=1, title="Band Upper 1", display=display.all)
pUpper2 = plot(upper_2 , color=color.new(colorBandUp1, 40), linewidth=1, title="Band Upper 2", display=display.all)
pUpper3 = plot(upper_3 , color=color.new(colorBandUp1, 30), linewidth=1, title="Band Upper 3", display=display.all)
pUpper4 = plot(upper_4 , color=color.new(colorBandUp1, 0) , linewidth=2, title="Band Upper 4", display=display.all)
pUpper5 = plot(upper_5 , color=color.new(colorBandUp2, 50), linewidth=1, title="Band Upper 5", display=display.all)
pUpper6 = plot(upper_6 , color=color.new(colorBandUp2, 40), linewidth=1, title="Band Upper 6", display=display.all)
pUpper7 = plot(upper_7, color=color.new(colorBandUp2, 30), linewidth=1, title="Band Upper 7", display=display.all)
pUpper8 = plot(upper_8, color=color.new(colorBandUp2, 0) , linewidth=2, title="Band Upper 8", display=display.all)
pUpper9 = plot(upper_9, color=color.new(colorBandUp3, 50), linewidth=1, title="Band Upper 9", display=display.all)
pUpper10 = plot(upper_10, color=color.new(colorBandUp3, 40), linewidth=1, title="Band Upper 10", display=display.all)
pUpper11 = plot(upper_11, color=color.new(colorBandUp3, 30), linewidth=1, title="Band Upper 11", display=display.all)
pUpper12 = plot(upper_12, color=color.new(colorBandUp3, 0), linewidth=3, title="Band Upper 12", display=display.all)
pLower1 = plot(lower_1 , color=color.new(colorBandDown1, 50), linewidth=1, title="Band Lower 1", display=display.all)
pLower2 = plot(lower_2 , color=color.new(colorBandDown1, 40), linewidth=1, title="Band Lower 2", display=display.all)
pLower3 = plot(lower_3 , color=color.new(colorBandDown1, 30), linewidth=1, title="Band Lower 3", display=display.all)
pLower4 = plot(lower_4 , color=color.new(colorBandDown1, 0) , linewidth=2, title="Band Lower 4", display=display.all)
pLower5 = plot(lower_5 , color=color.new(colorBandDown2, 50), linewidth=1, title="Band Lower 5", display=display.all)
pLower6 = plot(lower_6 , color=color.new(colorBandDown2, 40), linewidth=1, title="Band Lower 6", display=display.all)
pLower7 = plot(lower_7, color=color.new(colorBandDown2, 30), linewidth=1, title="Band Lower 7", display=display.all)
pLower8 = plot(lower_8, color=color.new(colorBandDown2, 0) , linewidth=2, title="Band Lower 8", display=display.all)
pLower9 = plot(lower_9, color=color.new(colorBandDown3, 50), linewidth=1, title="Band Upper 9", display=display.all)
pLower10 = plot(lower_10, color=color.new(colorBandDown3, 40), linewidth=1, title="Band Upper 10", display=display.all)
pLower11 = plot(lower_11, color=color.new(colorBandDown3, 30), linewidth=1, title="Band Upper 11", display=display.all)
pLower12 = plot(lower_12, color=color.new(colorBandDown3, 0) , linewidth=3, title="Band Upper 12", display=display.all)
fill(pBasis, pUpper4, (inputFill == 'When price inside channel' and src >= basis and src <= upper_4) or (inputFill == 'Always') ? color.new(colorBandUp1, inputColorFillTransparency) : na, 'Fill Level 1 Upper', display=display.all)
fill(pUpper4, pUpper8, (inputFill == 'When price inside channel' and src >= upper_4 and src <= upper_8) or (inputFill == 'Always') ? color.new(colorBandUp2, inputColorFillTransparency) : na, 'Fill Level 2 Upper', display=display.all)
fill(pUpper8, pUpper12, (inputFill == 'When price inside channel' and src >= upper_8 and src <= upper_12) or (inputFill == 'Always') ? color.new(colorBandUp3, inputColorFillTransparency) : na, 'Fill Level 3 Upper', display=display.all)
fill(pBasis, pLower4, (inputFill == 'When price inside channel' and src <= basis and src >= lower_4) or (inputFill == 'Always') ? color.new(colorBandDown1, inputColorFillTransparency) : na, 'Fill Level 1 Lower', display=display.all)
fill(pLower4, pLower8, (inputFill == 'When price inside channel' and src <= lower_4 and src >= lower_8) or (inputFill == 'Always') ? color.new(colorBandDown2, inputColorFillTransparency) : na, 'Fill Level 2 Lower', display=display.all)
fill(pLower8, pLower12, (inputFill == 'When price inside channel' and src <= lower_8 and src >= lower_12) or (inputFill == 'Always') ? color.new(colorBandDown3, inputColorFillTransparency) : na, 'Fill Level 3 Lower', display=display.all)
// ———————————————————————————————————————— }
// ———————————————————————————————————————— Statistics {
//--> Total bars
bars = ta.cum( not na(upper_4) ? 1 : 0)
//--> Bands
// upper_6 = 1
// upper_12 = 2
// upper_18 = 3
// basis
// lower_6 = 1
// lower_12 = 2
// lower_18 = 3
//--> Counts the bar between the bands
// Between Basis and Band 1
u1 = ta.cum( ((high >= basis and high <= upper_4) or (low >= basis and low <= upper_4) or (close >= basis and close <= upper_4) or (open >= basis and open <= upper_4)) ? 1 : 0 )
// Between Band 1 and Band 2
u2 = ta.cum( ((high >= upper_4 and high <= upper_8) or (low >= upper_4 and low <= upper_8) or (close >= upper_4 and close <= upper_8) or (open >= upper_4 and open <= upper_8)) ? 1 : 0 )
// Between Band 2 and Band 3
u3 = ta.cum( ((high >= upper_8 and high <= upper_12) or (low >= upper_8 and low <= upper_12) or (high >= upper_8 and high <= upper_12) or (low >= upper_8 and low <= upper_12)) ? 1 : 0 )
// Greater than Band 3
u4 = ta.cum(high > upper_12 ? 1 : 0)
// Between Basis and Band 1
l1 = ta.cum( ((low <= basis and low >= lower_4) or (high <= basis and high >= lower_4) or (close <= basis and close >= lower_4) or (open <= basis and open >= lower_4)) ? 1 : 0 )
// Between Band 1 and Band 2
l2 = ta.cum( ((low <= lower_4 and low >= lower_8) or (high <= lower_4 and high >= lower_8) or (close <= lower_4 and close >= lower_8) or (open <= lower_4 and open >= lower_8)) ? 1 : 0 )
// Between Band 2 and Band 3
l3 = ta.cum( ((low <= lower_8 and low >= lower_12) or (high <= lower_8 and high >= lower_12) or (close <= lower_8 and close >= lower_12) or (open <= lower_8 and open >= lower_12)) ? 1 : 0 )
// Greater Band 3
l4 = ta.cum(low < lower_12 ? 1 : 0)
//--> Probability
var float p_u1 = na
var float p_l1 = na
var float p_u2 = na
var float p_l2 = na
var float p_u3 = na
var float p_l3 = na
var float p_u4 = na
var float p_l4 = na
if (barstate.islast) and (na(p_u1))
p_u1 := u1/bars * 100
p_l1 := l1/bars * 100
p_u2 := u2/bars * 100
p_l2 := l2/bars * 100
p_u3 := u3/bars * 100
p_l3 := l3/bars * 100
p_u4 := u4/bars * 100
p_l4 := l4/bars * 100
//--> Labels
label.new(bar_index + xloc_labels, upper_4, text=str.tostring(p_u1,"#.##")+"%" + ' (' + str.tostring(u1) + ')', style=label.style_label_left, color=na, textcolor=colorBandUp1, textalign=text.align_left)
label.new(bar_index + xloc_labels, upper_8, text=str.tostring(p_u2,"#.##")+"%" + ' (' + str.tostring(u2) + ')', style=label.style_label_left, color=na, textcolor=colorBandUp2, textalign=text.align_left)
label.new(bar_index + xloc_labels, upper_12, text=str.tostring(p_u3,"#.##")+"%" + ' (' + str.tostring(u3) + ')' +
' Out: ' + str.tostring(p_u4,"#.##")+"%" + ' (' + str.tostring(u4) + ')', style=label.style_label_left, color=na, textcolor=colorBandUp3, textalign=text.align_left)
label.new(bar_index + xloc_labels, lower_4, text=str.tostring(p_l1,"#.##")+"%" + ' (' + str.tostring(l1) + ')', style=label.style_label_left, color=na, textcolor=colorBandDown1, textalign=text.align_left)
label.new(bar_index + xloc_labels, lower_8, text=str.tostring(p_l2,"#.##")+"%" + ' (' + str.tostring(l2) + ')', style=label.style_label_left, color=na, textcolor=colorBandDown2, textalign=text.align_left)
label.new(bar_index + xloc_labels, lower_12, text=str.tostring(p_l3,"#.##")+"%" + ' (' + str.tostring(l3) + ')' +
' Out: ' + str.tostring(p_l4,"#.##")+"%" + ' (' + str.tostring(l4) + ')', style=label.style_label_left, color=na, textcolor=colorBandDown3, textalign=text.align_left)
label.new(bar_index + xloc_labels, basis, text="Total bars : "+str.tostring(bars,"#"), style=label.style_label_left, color=na, textcolor=color.white, textalign=text.align_left)
// ———————————————————————————————————————— }
// ———————————————————————————————————————— Only for benchmark {
// Print table at the end of chart
// if barstate.islast
// var table t = table.new(position.middle_right, 1, 1)
// var txt = str.tostring(timePerBarInMs, "ms/bar: #.######\n") +
// str.tostring(totalTimeInMs, "Total time (ms): #,###.######\n") +
// str.tostring(barsTimed + barsNotTimed, "Bars analyzed: #")
// table.cell(t, 0, 0, txt, bgcolor = color.yellow, text_halign = text.align_right)
// ———————————————————————————————————————— }