0
# Volatility Indicators
1
2
Volatility-based technical indicators that measure the degree of price variation and market uncertainty. These indicators help traders assess market conditions, identify potential breakouts, determine support and resistance levels, and gauge the likelihood of significant price movements.
3
4
## Capabilities
5
6
### Average True Range (ATR)
7
8
Provides an indication of the degree of price volatility by measuring the average range between high and low prices over a specified period.
9
10
```python { .api }
11
class AverageTrueRange:
12
def __init__(self, high, low, close, window=14, fillna=False):
13
"""
14
Average True Range (ATR).
15
16
Parameters:
17
- high (Series): Dataset 'High' column
18
- low (Series): Dataset 'Low' column
19
- close (Series): Dataset 'Close' column
20
- window (int): Period for calculation (default: 14)
21
- fillna (bool): If True, fill NaN values (default: False)
22
"""
23
24
def average_true_range(self):
25
"""Returns: Series with Average True Range values"""
26
27
def average_true_range(high, low, close, window=14, fillna=False):
28
"""Functional interface for Average True Range"""
29
```
30
31
### Bollinger Bands
32
33
Volatility bands placed above and below a moving average that expand and contract based on market volatility, useful for identifying overbought and oversold conditions.
34
35
```python { .api }
36
class BollingerBands:
37
def __init__(self, close, window=20, window_dev=2, fillna=False):
38
"""
39
Bollinger Bands.
40
41
Parameters:
42
- close (Series): Dataset 'Close' column
43
- window (int): Period for moving average (default: 20)
44
- window_dev (int): Standard deviation factor (default: 2)
45
- fillna (bool): If True, fill NaN values (default: False)
46
"""
47
48
def bollinger_mavg(self):
49
"""Returns: Series with Bollinger Channel Middle Band (SMA)"""
50
51
def bollinger_hband(self):
52
"""Returns: Series with Bollinger Channel High Band (Upper)"""
53
54
def bollinger_lband(self):
55
"""Returns: Series with Bollinger Channel Low Band (Lower)"""
56
57
def bollinger_wband(self):
58
"""Returns: Series with Bollinger Channel Band Width"""
59
60
def bollinger_pband(self):
61
"""Returns: Series with Bollinger Channel Percentage Band (%B)"""
62
63
def bollinger_hband_indicator(self):
64
"""Returns: Series with Bollinger High Band Indicator (binary signal)"""
65
66
def bollinger_lband_indicator(self):
67
"""Returns: Series with Bollinger Low Band Indicator (binary signal)"""
68
69
def bollinger_mavg(close, window=20, fillna=False):
70
"""Functional interface for Bollinger Middle Band"""
71
72
def bollinger_hband(close, window=20, window_dev=2, fillna=False):
73
"""Functional interface for Bollinger High Band"""
74
75
def bollinger_lband(close, window=20, window_dev=2, fillna=False):
76
"""Functional interface for Bollinger Low Band"""
77
78
def bollinger_wband(close, window=20, window_dev=2, fillna=False):
79
"""Functional interface for Bollinger Band Width"""
80
81
def bollinger_pband(close, window=20, window_dev=2, fillna=False):
82
"""Functional interface for Bollinger Percentage Band"""
83
84
def bollinger_hband_indicator(close, window=20, window_dev=2, fillna=False):
85
"""Functional interface for Bollinger High Band Indicator"""
86
87
def bollinger_lband_indicator(close, window=20, window_dev=2, fillna=False):
88
"""Functional interface for Bollinger Low Band Indicator"""
89
```
90
91
### Keltner Channel
92
93
Trend-following indicator used to identify reversals with channel breakouts and closures, based on exponential moving average and Average True Range.
94
95
```python { .api }
96
class KeltnerChannel:
97
def __init__(self, high, low, close, window=20, window_atr=10, fillna=False,
98
original_version=True, multiplier=2):
99
"""
100
Keltner Channel.
101
102
Parameters:
103
- high (Series): Dataset 'High' column
104
- low (Series): Dataset 'Low' column
105
- close (Series): Dataset 'Close' column
106
- window (int): Period for centerline calculation (default: 20)
107
- window_atr (int): Period for ATR calculation (default: 10)
108
- fillna (bool): If True, fill NaN values (default: False)
109
- original_version (bool): If True, use original version as centerline (default: False)
110
- multiplier (int): Multiplier for channel width (default: 2)
111
"""
112
113
def keltner_channel_mband(self):
114
"""Returns: Series with Keltner Channel Middle Band (centerline)"""
115
116
def keltner_channel_hband(self):
117
"""Returns: Series with Keltner Channel High Band (upper)"""
118
119
def keltner_channel_lband(self):
120
"""Returns: Series with Keltner Channel Low Band (lower)"""
121
122
def keltner_channel_wband(self):
123
"""Returns: Series with Keltner Channel Band Width"""
124
125
def keltner_channel_pband(self):
126
"""Returns: Series with Keltner Channel Percentage Band"""
127
128
def keltner_channel_hband_indicator(self):
129
"""Returns: Series with Keltner High Band Indicator (binary signal)"""
130
131
def keltner_channel_lband_indicator(self):
132
"""Returns: Series with Keltner Low Band Indicator (binary signal)"""
133
134
def keltner_channel_mband(high, low, close, window=20, window_atr=10, fillna=False,
135
original_version=False, multiplier=2):
136
"""Functional interface for Keltner Channel Middle Band"""
137
138
def keltner_channel_hband(high, low, close, window=20, window_atr=10, fillna=False,
139
original_version=False, multiplier=2):
140
"""Functional interface for Keltner Channel High Band"""
141
142
def keltner_channel_lband(high, low, close, window=20, window_atr=10, fillna=False,
143
original_version=False, multiplier=2):
144
"""Functional interface for Keltner Channel Low Band"""
145
146
def keltner_channel_wband(high, low, close, window=20, window_atr=10, fillna=False,
147
original_version=False, multiplier=2):
148
"""Functional interface for Keltner Channel Band Width"""
149
150
def keltner_channel_pband(high, low, close, window=20, window_atr=10, fillna=False,
151
original_version=False, multiplier=2):
152
"""Functional interface for Keltner Channel Percentage Band"""
153
154
def keltner_channel_hband_indicator(high, low, close, window=20, window_atr=10,
155
fillna=False, original_version=False, multiplier=2):
156
"""Functional interface for Keltner Channel High Band Indicator"""
157
158
def keltner_channel_lband_indicator(high, low, close, window=20, window_atr=10,
159
fillna=False, original_version=False, multiplier=2):
160
"""Functional interface for Keltner Channel Low Band Indicator"""
161
```
162
163
### Donchian Channel
164
165
Channel-based indicator that identifies the highest high and lowest low over a specified period, useful for breakout strategies and trend identification.
166
167
```python { .api }
168
class DonchianChannel:
169
def __init__(self, high, low, close, window=20, offset=0, fillna=False):
170
"""
171
Donchian Channel.
172
173
Parameters:
174
- high (Series): Dataset 'High' column
175
- low (Series): Dataset 'Low' column
176
- close (Series): Dataset 'Close' column
177
- window (int): Period for calculation (default: 20)
178
- offset (int): Offset for calculation (default: 0)
179
- fillna (bool): If True, fill NaN values (default: False)
180
"""
181
182
def donchian_channel_hband(self):
183
"""Returns: Series with Donchian Channel High Band (highest high)"""
184
185
def donchian_channel_lband(self):
186
"""Returns: Series with Donchian Channel Low Band (lowest low)"""
187
188
def donchian_channel_mband(self):
189
"""Returns: Series with Donchian Channel Middle Band (midpoint)"""
190
191
def donchian_channel_wband(self):
192
"""Returns: Series with Donchian Channel Band Width"""
193
194
def donchian_channel_pband(self):
195
"""Returns: Series with Donchian Channel Percentage Band"""
196
197
def donchian_channel_hband(high, low, close, window=20, offset=0, fillna=False):
198
"""Functional interface for Donchian Channel High Band"""
199
200
def donchian_channel_lband(high, low, close, window=20, offset=0, fillna=False):
201
"""Functional interface for Donchian Channel Low Band"""
202
203
def donchian_channel_mband(high, low, close, window=10, offset=0, fillna=False):
204
"""Functional interface for Donchian Channel Middle Band"""
205
206
def donchian_channel_wband(high, low, close, window=10, offset=0, fillna=False):
207
"""Functional interface for Donchian Channel Band Width"""
208
209
def donchian_channel_pband(high, low, close, window=10, offset=0, fillna=False):
210
"""Functional interface for Donchian Channel Percentage Band"""
211
```
212
213
### Ulcer Index
214
215
Measures downside risk by calculating the percentage drawdown from the highest high over a specified period, focusing on the depth and duration of drawdowns.
216
217
```python { .api }
218
class UlcerIndex:
219
def __init__(self, close, window=14, fillna=False):
220
"""
221
Ulcer Index.
222
223
Parameters:
224
- close (Series): Dataset 'Close' column
225
- window (int): Period for calculation (default: 14)
226
- fillna (bool): If True, fill NaN values (default: False)
227
"""
228
229
def ulcer_index(self):
230
"""Returns: Series with Ulcer Index values (downside risk measure)"""
231
232
def ulcer_index(close, window=14, fillna=False):
233
"""Functional interface for Ulcer Index"""
234
```
235
236
## Usage Examples
237
238
### Volatility Analysis Workflow
239
240
```python
241
from ta.volatility import *
242
import pandas as pd
243
244
def analyze_volatility(df):
245
# Basic volatility measures
246
df['ATR'] = average_true_range(df['High'], df['Low'], df['Close'])
247
df['Ulcer'] = ulcer_index(df['Close'])
248
249
# Bollinger Bands analysis
250
df['BB_Middle'] = bollinger_mavg(df['Close'])
251
df['BB_Upper'] = bollinger_hband(df['Close'])
252
df['BB_Lower'] = bollinger_lband(df['Close'])
253
df['BB_Width'] = bollinger_wband(df['Close'])
254
df['BB_Percent'] = bollinger_pband(df['Close'])
255
256
# Channel breakout indicators
257
df['Keltner_Upper'] = keltner_channel_hband(df['High'], df['Low'], df['Close'])
258
df['Keltner_Lower'] = keltner_channel_lband(df['High'], df['Low'], df['Close'])
259
df['Donchian_Upper'] = donchian_channel_hband(df['High'], df['Low'], df['Close'])
260
df['Donchian_Lower'] = donchian_channel_lband(df['High'], df['Low'], df['Close'])
261
262
return df
263
264
# Apply volatility analysis
265
df_volatility = analyze_volatility(df)
266
```
267
268
### Bollinger Band Strategy
269
270
```python
271
from ta.volatility import BollingerBands
272
273
# Create Bollinger Bands indicator
274
bb_indicator = BollingerBands(
275
close=df['Close'],
276
window=20,
277
window_dev=2
278
)
279
280
# Calculate all Bollinger Band components
281
df['BB_Middle'] = bb_indicator.bollinger_mavg()
282
df['BB_Upper'] = bb_indicator.bollinger_hband()
283
df['BB_Lower'] = bb_indicator.bollinger_lband()
284
df['BB_Width'] = bb_indicator.bollinger_wband()
285
df['BB_Percent'] = bb_indicator.bollinger_pband()
286
287
# Generate trading signals
288
df['BB_Upper_Signal'] = bb_indicator.bollinger_hband_indicator()
289
df['BB_Lower_Signal'] = bb_indicator.bollinger_lband_indicator()
290
291
# Bollinger Band squeeze detection (low volatility)
292
df['BB_Squeeze'] = df['BB_Width'] < df['BB_Width'].rolling(20).quantile(0.2)
293
294
# Bollinger Band expansion (high volatility)
295
df['BB_Expansion'] = df['BB_Width'] > df['BB_Width'].rolling(20).quantile(0.8)
296
297
# Trading signals based on band position
298
df['BB_Buy_Signal'] = (df['Close'] <= df['BB_Lower']) & (df['BB_Percent'] < 0.05)
299
df['BB_Sell_Signal'] = (df['Close'] >= df['BB_Upper']) & (df['BB_Percent'] > 0.95)
300
```
301
302
### Channel Breakout System
303
304
```python
305
from ta.volatility import KeltnerChannel, DonchianChannel
306
307
# Multi-channel breakout system
308
def channel_breakout_analysis(df):
309
# Keltner Channels
310
keltner = KeltnerChannel(
311
high=df['High'],
312
low=df['Low'],
313
close=df['Close'],
314
window=20,
315
window_atr=10,
316
multiplier=2
317
)
318
319
# Donchian Channels
320
donchian = DonchianChannel(
321
high=df['High'],
322
low=df['Low'],
323
close=df['Close'],
324
window=20
325
)
326
327
# Calculate channel values
328
df['Keltner_Upper'] = keltner.keltner_channel_hband()
329
df['Keltner_Lower'] = keltner.keltner_channel_lband()
330
df['Keltner_Middle'] = keltner.keltner_channel_mband()
331
332
df['Donchian_Upper'] = donchian.donchian_channel_hband()
333
df['Donchian_Lower'] = donchian.donchian_channel_lband()
334
df['Donchian_Middle'] = donchian.donchian_channel_mband()
335
336
# Breakout signals
337
df['Keltner_Breakout_Up'] = keltner.keltner_channel_hband_indicator()
338
df['Keltner_Breakout_Down'] = keltner.keltner_channel_lband_indicator()
339
340
# Channel width for volatility assessment
341
df['Keltner_Width'] = keltner.keltner_channel_wband()
342
df['Donchian_Width'] = donchian.donchian_channel_wband()
343
344
# Combined breakout signal (both channels agree)
345
df['Combined_Breakout_Up'] = (
346
(df['Close'] > df['Keltner_Upper']) &
347
(df['Close'] > df['Donchian_Upper'])
348
)
349
df['Combined_Breakout_Down'] = (
350
(df['Close'] < df['Keltner_Lower']) &
351
(df['Close'] < df['Donchian_Lower'])
352
)
353
354
return df
355
356
df_channels = channel_breakout_analysis(df)
357
```
358
359
### Volatility Regime Detection
360
361
```python
362
from ta.volatility import AverageTrueRange, UlcerIndex
363
364
# Advanced volatility regime analysis
365
def volatility_regime_analysis(df):
366
# Calculate volatility measures
367
atr_indicator = AverageTrueRange(
368
high=df['High'],
369
low=df['Low'],
370
close=df['Close'],
371
window=14
372
)
373
374
ulcer_indicator = UlcerIndex(
375
close=df['Close'],
376
window=14
377
)
378
379
df['ATR'] = atr_indicator.average_true_range()
380
df['Ulcer'] = ulcer_indicator.ulcer_index()
381
382
# Normalized ATR (as percentage of price)
383
df['ATR_Percent'] = (df['ATR'] / df['Close']) * 100
384
385
# Volatility percentiles for regime classification
386
df['ATR_Percentile'] = df['ATR_Percent'].rolling(252).rank(pct=True)
387
df['Ulcer_Percentile'] = df['Ulcer'].rolling(252).rank(pct=True)
388
389
# Volatility regimes
390
df['Volatility_Regime'] = pd.cut(
391
df['ATR_Percentile'],
392
bins=[0, 0.33, 0.66, 1.0],
393
labels=['Low', 'Medium', 'High']
394
)
395
396
# Risk-adjusted signals based on volatility regime
397
df['Risk_Adjusted_Position_Size'] = np.where(
398
df['Volatility_Regime'] == 'High', 0.5, # Reduce size in high vol
399
np.where(df['Volatility_Regime'] == 'Low', 1.5, 1.0) # Increase in low vol
400
)
401
402
# Downside risk assessment
403
df['High_Downside_Risk'] = df['Ulcer_Percentile'] > 0.8
404
405
return df
406
407
df_volatility_regime = volatility_regime_analysis(df)
408
```
409
410
### Multi-Timeframe Volatility Analysis
411
412
```python
413
from ta.volatility import *
414
415
# Multi-timeframe volatility assessment
416
def multi_timeframe_volatility(df):
417
# Short-term volatility (5-day)
418
df['ATR_Short'] = average_true_range(df['High'], df['Low'], df['Close'], window=5)
419
df['BB_Width_Short'] = bollinger_wband(df['Close'], window=10, window_dev=2)
420
421
# Medium-term volatility (20-day)
422
df['ATR_Medium'] = average_true_range(df['High'], df['Low'], df['Close'], window=20)
423
df['BB_Width_Medium'] = bollinger_wband(df['Close'], window=20, window_dev=2)
424
425
# Long-term volatility (50-day)
426
df['ATR_Long'] = average_true_range(df['High'], df['Low'], df['Close'], window=50)
427
df['BB_Width_Long'] = bollinger_wband(df['Close'], window=50, window_dev=2)
428
429
# Volatility term structure analysis
430
df['Vol_Term_Structure'] = df['ATR_Short'] / df['ATR_Long']
431
432
# Volatility momentum (expanding vs contracting)
433
df['Vol_Momentum'] = (
434
(df['BB_Width_Short'] > df['BB_Width_Short'].shift(5)).astype(int) +
435
(df['BB_Width_Medium'] > df['BB_Width_Medium'].shift(10)).astype(int) +
436
(df['BB_Width_Long'] > df['BB_Width_Long'].shift(20)).astype(int)
437
)
438
439
# Volatility divergence signals
440
df['Vol_Divergence'] = (
441
(df['ATR_Short'] > df['ATR_Medium']) &
442
(df['ATR_Medium'] < df['ATR_Long'])
443
)
444
445
return df
446
447
df_multi_tf_vol = multi_timeframe_volatility(df)
448
```