Volatility

Volatility indicators measure the degree of price variation in financial instruments. They help traders assess market uncertainty, risk levels, and potential breakout conditions. OpenAlgo provides a comprehensive collection of volatility indicators optimized for performance and accuracy.

Import Statement

from openalgo import ta
from openalgo import api

# Initialize API client
client = api(api_key='your_api_key_here', host='http://127.0.0.1:5000')

# Get sample data
df = client.history(symbol="SBIN", exchange="NSE", interval="5m", 
                   start_date="2025-04-01", end_date="2025-04-08")

Available Volatility Indicators


Average True Range (ATR)

ATR measures market volatility by decomposing the entire range of an asset price for that period. It's one of the most widely used volatility indicators.

Usage

atr_result = ta.atr(high, low, close, period=14)

Parameters

  • high (array-like): High prices

  • low (array-like): Low prices

  • close (array-like): Closing prices

  • period (int, default=14): Number of periods for ATR calculation

Returns

  • array: ATR values in the same format as input

Example

# Calculate 14-period ATR
atr_14 = ta.atr(df['high'], df['low'], df['close'], period=14)
df['ATR_14'] = atr_14

# Calculate 21-period ATR
atr_21 = ta.atr(df['high'], df['low'], df['close'], period=21)
df['ATR_21'] = atr_21

print(df[['close', 'ATR_14', 'ATR_21']].tail())

Bollinger Bands

Bollinger Bands consist of a middle band (SMA) and two outer bands that are standard deviations away from the middle band, used to identify overbought and oversold conditions.

Usage

upper, middle, lower = ta.bbands(data, period=20, std_dev=2.0)

Parameters

  • data (array-like): Price data (typically closing prices)

  • period (int, default=20): Number of periods for moving average and standard deviation

  • std_dev (float, default=2.0): Number of standard deviations for the bands

Returns

  • tuple: (upper_band, middle_band, lower_band) arrays

Example

# Calculate Bollinger Bands
bb_upper, bb_middle, bb_lower = ta.bbands(df['close'], period=20, std_dev=2.0)
df['BB_Upper'] = bb_upper
df['BB_Middle'] = bb_middle
df['BB_Lower'] = bb_lower

# Calculate tighter bands
bb_upper_tight, bb_middle_tight, bb_lower_tight = ta.bbands(df['close'], period=20, std_dev=1.5)
df['BB_Upper_Tight'] = bb_upper_tight
df['BB_Lower_Tight'] = bb_lower_tight

print(df[['close', 'BB_Upper', 'BB_Middle', 'BB_Lower']].tail())

Keltner Channel

Keltner Channels are volatility-based envelopes set above and below an exponential moving average, using ATR to set channel distance.

Usage

upper, middle, lower = ta.keltner(high, low, close, ema_period=20, atr_period=10, multiplier=2.0)

Parameters

  • high (array-like): High prices

  • low (array-like): Low prices

  • close (array-like): Closing prices

  • ema_period (int, default=20): Period for the EMA calculation

  • atr_period (int, default=10): Period for the ATR calculation

  • multiplier (float, default=2.0): Multiplier for the ATR

Returns

  • tuple: (upper_channel, middle_line, lower_channel) arrays

Example

# Calculate Keltner Channel
kc_upper, kc_middle, kc_lower = ta.keltner(df['high'], df['low'], df['close'])
df['KC_Upper'] = kc_upper
df['KC_Middle'] = kc_middle
df['KC_Lower'] = kc_lower

# Custom parameters
kc_upper_custom, kc_middle_custom, kc_lower_custom = ta.keltner(
    df['high'], df['low'], df['close'], 
    ema_period=14, atr_period=14, multiplier=1.5
)

print(df[['close', 'KC_Upper', 'KC_Middle', 'KC_Lower']].tail())

Donchian Channel

Donchian Channels are formed by taking the highest high and lowest low of the last n periods, providing dynamic support and resistance levels.

Usage

upper, middle, lower = ta.donchian(high, low, period=20)

Parameters

  • high (array-like): High prices

  • low (array-like): Low prices

  • period (int, default=20): Number of periods for the channel calculation

Returns

  • tuple: (upper_channel, middle_line, lower_channel) arrays

Example

# Calculate Donchian Channel
dc_upper, dc_middle, dc_lower = ta.donchian(df['high'], df['low'], period=20)
df['DC_Upper'] = dc_upper
df['DC_Middle'] = dc_middle
df['DC_Lower'] = dc_lower

# Different periods
dc_upper_10, dc_middle_10, dc_lower_10 = ta.donchian(df['high'], df['low'], period=10)
df['DC_Upper_10'] = dc_upper_10
df['DC_Lower_10'] = dc_lower_10

print(df[['high', 'low', 'DC_Upper', 'DC_Middle', 'DC_Lower']].tail())

Chaikin Volatility

Chaikin Volatility measures the rate of change of the trading range, indicating periods of increasing or decreasing volatility.

Usage

cv_result = ta.chaikin(high, low, ema_period=10, roc_period=10)

Parameters

  • high (array-like): High prices

  • low (array-like): Low prices

  • ema_period (int, default=10): Period for EMA of high-low range

  • roc_period (int, default=10): Period for rate of change calculation

Returns

  • array: Chaikin Volatility values

Example

# Calculate Chaikin Volatility
cv = ta.chaikin(df['high'], df['low'])
df['Chaikin_Volatility'] = cv

# Custom parameters
cv_custom = ta.chaikin(df['high'], df['low'], ema_period=14, roc_period=14)
df['CV_Custom'] = cv_custom

print(df[['close', 'Chaikin_Volatility', 'CV_Custom']].tail())

Normalized Average True Range (NATR)

NATR is ATR expressed as a percentage of closing price, making it useful for comparing volatility across different price levels.

Usage

natr_result = ta.natr(high, low, close, period=14)

Parameters

  • high (array-like): High prices

  • low (array-like): Low prices

  • close (array-like): Closing prices

  • period (int, default=14): Period for ATR calculation

Returns

  • array: NATR values (percentage)

Example

# Calculate NATR
natr = ta.natr(df['high'], df['low'], df['close'], period=14)
df['NATR'] = natr

# Different period
natr_21 = ta.natr(df['high'], df['low'], df['close'], period=21)
df['NATR_21'] = natr_21

print(df[['close', 'NATR', 'NATR_21']].tail())

Relative Volatility Index (RVI)

RVI applies the RSI calculation to standard deviation instead of price changes, measuring volatility momentum.

Usage

rvi_result = ta.rvi(data, stdev_period=10, rsi_period=14)

Parameters

  • data (array-like): Price data (typically closing prices)

  • stdev_period (int, default=10): Period for standard deviation calculation

  • rsi_period (int, default=14): Period for RSI calculation

Returns

  • array: RVI values (0-100 range)

Example

# Calculate RVI
rvi = ta.rvi(df['close'])
df['RVI'] = rvi

# Custom parameters
rvi_custom = ta.rvi(df['close'], stdev_period=14, rsi_period=21)
df['RVI_Custom'] = rvi_custom

print(df[['close', 'RVI', 'RVI_Custom']].tail())

Ultimate Oscillator

Ultimate Oscillator combines short, medium, and long-term price action into one oscillator, incorporating volatility analysis.

Usage

uo_result = ta.ultimate_oscillator(high, low, close, period1=7, period2=14, period3=28)

Parameters

  • high (array-like): High prices

  • low (array-like): Low prices

  • close (array-like): Closing prices

  • period1 (int, default=7): Short period

  • period2 (int, default=14): Medium period

  • period3 (int, default=28): Long period

Returns

  • array: Ultimate Oscillator values (0-100 range)

Example

# Calculate Ultimate Oscillator
uo = ta.ultimate_oscillator(df['high'], df['low'], df['close'])
df['Ultimate_Oscillator'] = uo

# Custom periods
uo_custom = ta.ultimate_oscillator(df['high'], df['low'], df['close'], 
                                  period1=5, period2=10, period3=20)
df['UO_Custom'] = uo_custom

print(df[['close', 'Ultimate_Oscillator', 'UO_Custom']].tail())

True Range

True Range measures volatility that accounts for gaps between periods.

Usage

tr_result = ta.true_range(high, low, close)

Parameters

  • high (array-like): High prices

  • low (array-like): Low prices

  • close (array-like): Closing prices

Returns

  • array: True Range values

Example

# Calculate True Range
tr = ta.true_range(df['high'], df['low'], df['close'])
df['True_Range'] = tr

print(df[['high', 'low', 'close', 'True_Range']].tail())

Mass Index

Mass Index uses the high-low range to identify trend reversals based on range expansion.

Usage

mass_result = ta.massindex(high, low, length=10)

Parameters

  • high (array-like): High prices

  • low (array-like): Low prices

  • length (int, default=10): Period for sum calculation

Returns

  • array: Mass Index values

Example

# Calculate Mass Index
mass = ta.massindex(df['high'], df['low'])
df['Mass_Index'] = mass

# Different period
mass_14 = ta.massindex(df['high'], df['low'], length=14)
df['Mass_Index_14'] = mass_14

print(df[['close', 'Mass_Index', 'Mass_Index_14']].tail())

Bollinger Bands %B

%B shows where price is in relation to the Bollinger Bands, with 1 indicating price at upper band and 0 at lower band.

Usage

percent_b = ta.bbpercent(data, period=20, std_dev=2.0)

Parameters

  • data (array-like): Price data (typically closing prices)

  • period (int, default=20): Period for moving average and standard deviation

  • std_dev (float, default=2.0): Number of standard deviations for the bands

Returns

  • array: %B values

Example

# Calculate Bollinger Bands %B
bb_percent = ta.bbpercent(df['close'])
df['BB_Percent_B'] = bb_percent

# Custom parameters
bb_percent_tight = ta.bbpercent(df['close'], period=14, std_dev=1.5)
df['BB_Percent_B_Tight'] = bb_percent_tight

print(df[['close', 'BB_Percent_B', 'BB_Percent_B_Tight']].tail())

Bollinger Bandwidth

Bollinger Bandwidth measures the width of the Bollinger Bands, useful for identifying volatility squeezes.

Usage

bandwidth = ta.bbwidth(data, period=20, std_dev=2.0)

Parameters

  • data (array-like): Price data (typically closing prices)

  • period (int, default=20): Period for moving average and standard deviation

  • std_dev (float, default=2.0): Number of standard deviations for the bands

Returns

  • array: Bandwidth values

Example

# Calculate Bollinger Bandwidth
bb_width = ta.bbwidth(df['close'])
df['BB_Bandwidth'] = bb_width

# Different standard deviation
bb_width_tight = ta.bbwidth(df['close'], std_dev=1.5)
df['BB_Bandwidth_Tight'] = bb_width_tight

print(df[['close', 'BB_Bandwidth', 'BB_Bandwidth_Tight']].tail())

Chandelier Exit

Chandelier Exit is a trailing stop-loss technique that follows price action using highest/lowest values and ATR.

Usage

long_exit, short_exit = ta.chandelier_exit(high, low, close, period=22, multiplier=3.0)

Parameters

  • high (array-like): High prices

  • low (array-like): Low prices

  • close (array-like): Closing prices

  • period (int, default=22): Period for highest/lowest and ATR calculation

  • multiplier (float, default=3.0): ATR multiplier

Returns

  • tuple: (long_exit, short_exit) arrays

Example

# Calculate Chandelier Exit
ce_long, ce_short = ta.chandelier_exit(df['high'], df['low'], df['close'])
df['CE_Long_Exit'] = ce_long
df['CE_Short_Exit'] = ce_short

# Custom parameters
ce_long_custom, ce_short_custom = ta.chandelier_exit(
    df['high'], df['low'], df['close'], period=14, multiplier=2.0
)
df['CE_Long_Custom'] = ce_long_custom
df['CE_Short_Custom'] = ce_short_custom

print(df[['close', 'CE_Long_Exit', 'CE_Short_Exit']].tail())

Historical Volatility

Historical Volatility measures the standard deviation of logarithmic returns over a specified period.

Usage

hv_result = ta.hv(close, length=10, annual=365, per=1)

Parameters

  • close (array-like): Closing prices

  • length (int, default=10): Period for volatility calculation

  • annual (int, default=365): Annual periods for scaling

  • per (int, default=1): Timeframe periods (1 for daily/intraday, 7 for weekly+)

Returns

  • array: Historical volatility values (annualized percentages)

Example

# Calculate Historical Volatility
hv = ta.hv(df['close'], length=20)
df['Historical_Volatility'] = hv

# Different periods
hv_10 = ta.hv(df['close'], length=10)
hv_30 = ta.hv(df['close'], length=30)
df['HV_10'] = hv_10
df['HV_30'] = hv_30

print(df[['close', 'Historical_Volatility', 'HV_10', 'HV_30']].tail())

Ulcer Index

Ulcer Index measures downside risk by calculating the depth and duration of drawdowns from recent highs.

Usage

ui_result = ta.ulcerindex(data, length=14, smooth_length=14, signal_length=52, 
                         signal_type="SMA", return_signal=False)

Parameters

  • data (array-like): Price data (typically closing prices)

  • length (int, default=14): Period for highest calculation

  • smooth_length (int, default=14): Period for smoothing squared drawdowns

  • signal_length (int, default=52): Period for signal line calculation

  • signal_type (str, default="SMA"): Signal smoothing type ("SMA" or "EMA")

  • return_signal (bool, default=False): Whether to return signal line

Returns

  • array or tuple: Ulcer Index values (and signal if return_signal=True)

Example

# Calculate Ulcer Index
ui = ta.ulcerindex(df['close'])
df['Ulcer_Index'] = ui

# With signal line
ui_with_signal, ui_signal = ta.ulcerindex(df['close'], return_signal=True)
df['UI_Signal'] = ui_signal

# Custom parameters
ui_custom = ta.ulcerindex(df['close'], length=21, smooth_length=21)
df['UI_Custom'] = ui_custom

print(df[['close', 'Ulcer_Index', 'UI_Signal', 'UI_Custom']].tail())

STARC Bands

STARC Bands use a Simple Moving Average and Average True Range to create volatility-based bands.

Usage

upper, middle, lower = ta.starc(high, low, close, ma_period=5, atr_period=15, multiplier=1.33)

Parameters

  • high (array-like): High prices

  • low (array-like): Low prices

  • close (array-like): Closing prices

  • ma_period (int, default=5): Period for SMA calculation

  • atr_period (int, default=15): Period for ATR calculation

  • multiplier (float, default=1.33): ATR multiplier

Returns

  • tuple: (upper_band, middle_line, lower_band) arrays

Example

# Calculate STARC Bands
starc_upper, starc_middle, starc_lower = ta.starc(df['high'], df['low'], df['close'])
df['STARC_Upper'] = starc_upper
df['STARC_Middle'] = starc_middle
df['STARC_Lower'] = starc_lower

# Custom parameters
starc_upper_custom, starc_middle_custom, starc_lower_custom = ta.starc(
    df['high'], df['low'], df['close'], 
    ma_period=10, atr_period=20, multiplier=2.0
)

print(df[['close', 'STARC_Upper', 'STARC_Middle', 'STARC_Lower']].tail())

Complete Example: Volatility Analysis

from openalgo import ta, api
import pandas as pd

# Initialize API and get data
client = api(api_key='your_api_key_here', host='http://127.0.0.1:5000')
df = client.history(symbol="SBIN", exchange="NSE", interval="5m", 
                   start_date="2025-04-01", end_date="2025-04-08")

# Calculate multiple volatility indicators
df['ATR'] = ta.atr(df['high'], df['low'], df['close'], period=14)
df['NATR'] = ta.natr(df['high'], df['low'], df['close'], period=14)

# Bollinger Bands
bb_upper, bb_middle, bb_lower = ta.bbands(df['close'], period=20, std_dev=2.0)
df['BB_Upper'] = bb_upper
df['BB_Middle'] = bb_middle
df['BB_Lower'] = bb_lower
df['BB_Width'] = ta.bbwidth(df['close'], period=20, std_dev=2.0)
df['BB_Percent_B'] = ta.bbpercent(df['close'], period=20, std_dev=2.0)

# Keltner Channel
kc_upper, kc_middle, kc_lower = ta.keltner(df['high'], df['low'], df['close'])
df['KC_Upper'] = kc_upper
df['KC_Middle'] = kc_middle
df['KC_Lower'] = kc_lower

# Donchian Channel
dc_upper, dc_middle, dc_lower = ta.donchian(df['high'], df['low'], period=20)
df['DC_Upper'] = dc_upper
df['DC_Middle'] = dc_middle
df['DC_Lower'] = dc_lower

# Advanced volatility indicators
df['RVI'] = ta.rvi(df['close'])
df['Historical_Vol'] = ta.hv(df['close'], length=20)
df['Ulcer_Index'] = ta.ulcerindex(df['close'])
df['Mass_Index'] = ta.massindex(df['high'], df['low'])

# Chandelier Exit levels
ce_long, ce_short = ta.chandelier_exit(df['high'], df['low'], df['close'])
df['CE_Long'] = ce_long
df['CE_Short'] = ce_short

# Volatility analysis
print("=== Volatility Analysis ===")
print(f"Average ATR: {df['ATR'].mean():.2f}")
print(f"Average NATR: {df['NATR'].mean():.2f}%")
print(f"Average Historical Volatility: {df['Historical_Vol'].mean():.2f}%")
print(f"Average BB Width: {df['BB_Width'].mean():.4f}")

# Recent values
print("\n=== Recent Volatility Indicators ===")
recent_data = df[['close', 'ATR', 'NATR', 'BB_Width', 'RVI', 'Historical_Vol']].tail()
print(recent_data)

# Volatility squeeze detection (BB Width < KC Width equivalent)
df['Squeeze'] = (df['BB_Upper'] - df['BB_Lower']) < (df['KC_Upper'] - df['KC_Lower'])
print(f"\nVolatility Squeeze periods: {df['Squeeze'].sum()} out of {len(df)} periods")

Common Use Cases

  1. Volatility Breakouts: Use BB Width and Mass Index to identify low volatility periods before breakouts

  2. Risk Management: Use ATR and NATR for position sizing and stop-loss placement

  3. Overbought/Oversold: Use BB %B and RVI to identify extreme price levels

  4. Trend Strength: Higher volatility often accompanies strong trends

  5. Market Regime: Compare different volatility measures to understand market conditions

Performance Tips

  1. Efficient Calculations: Use vectorized operations for multiple timeframes

  2. Memory Management: Calculate only needed indicators to save memory

  3. Parameter Optimization: Test different periods for your specific market and timeframe

  4. Combination Analysis: Use multiple volatility indicators together for confirmation

Last updated