Indicators

Overview

Indicators are a central part of developing strong quantitative models. As we know, price data is noisy, unpredictable, and constantly changing. Using indicators that have been backed by years of research have shown to improve performance and ultimately have become the backbone of many modern quantitative models. Whether it's starting with the most basic golden cross, or using deep learning with inputs including RSI, TEMA, and more, indicators are extremely useful to know about and to learn.

Blankly has implemented a multitude of indicators for your own use and development. Specifically, we take the tulipy library and wrap it with Blankly data and Strategies for backtest.

As always, if you have any indicators that you'd like to be added, or an implementation for one, we'd love a PR!

Moving Averages

Moving averages are just as they sound: they are moving ("rolling window") averages ("aggregating data points together"). The point of moving averages is to greatly improve the quality of data points. As we mentioned before, price data is extremely noisy, with constant ups and downs, moving averages "smooth" out the data so it's very clear to see a specific trend. In Blankly, we offer a multitude of various types of moving averages. We describe them below.

sma(data, period=50, use_series=False)

Arguments

ArgDescriptionExamplesType
dataData to passBTC-USD Price DataFloat[], np.arr, pd.Series
periodThe period/window of the moving average50, 100int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The Rolling Average[2.25, 2.35, 2.45 ...]Float[], np.arr, pd.Series

The simple moving average (SMA) is the simplest type of moving average, it takes a time series (f.e. price data) and divides it up into windows defined by the period. Then it averages all of those points to produce one point. Thus, if you have 250 total data points, you will be returned data points. A common use-case for the SMA is the golden cross or the MACD strategies where we look fro the crossing of various simple moving averages (for example the 50 day SMA and the 100 day SMA) to see trend changes. The longer the period, the "harder" it is to change (the less it follows local market changes).

ema(data, period=50, use_series=False)

Arguments

ArgDescriptionExamplesType
dataData to passBTC-USD Price DataFloat[], np.arr, pd.Series
periodThe period/window of the moving average50, 100int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The Exponential Moving Average[2.25, 2.35, 2.45 ...]Float[], np.arr, pd.Series

Exponential moving average (EMA) is calculated a little differently than the SMA, the key difference between the SMA and the EMA is that the EMA places greater weight and value to more recent data points in the dataset. However, the premise for looking at crossovers and divergences with moving averages stays the same.

Note, we default to using a smoothing factor of 2 for all EMA calculations

For more information, check out investopedia

vwma(data, volume_data, period=50, use_series=False)

Arguments

ArgDescriptionExamplesType
dataData to passBTC-USD Price DataFloat[], np.arr, pd.Series
volume_dataVolume DataBTC-USD Volume DataFloat[], np.arr, pd.Series
periodThe period/window of the moving average50, 100int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The Volume Weighted Moving Average[2.25, 2.35, 2.45 ...]Float[], np.arr, pd.Series

This is a moving average that makes more weight for the days that have higher volume than others. Check out Investopedia

wma(data, period=50, use_series=False)

Arguments

ArgDescriptionExamplesType
dataData to passBTC-USD Price DataFloat[], np.arr, pd.Series
periodThe period/window of the moving average50, 100int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The Weighted Moving Average[2.25, 2.35, 2.45 ...]Float[], np.arr, pd.Series

A weighted moving average is very similar to the EMA, however their weighting function for recent points is different. Namely WMAs are linear weighting and EMA is exponential weighting. Check out this great article by Investopedia

zlema(data, period=50, use_series=False)

Arguments

ArgDescriptionExamplesType
dataData to passBTC-USD Price DataFloat[], np.arr, pd.Series
periodThe period/window of the moving average50, 100int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The Zero-Lag EMA[2.25, 2.35, 2.45 ...]Float[], np.arr, pd.Series

The zero-lag exponential moving average reduces aspects of "lag", check out these docs

hma(data, period=50, use_series=False)

Arguments

ArgDescriptionExamplesType
dataData to passBTC-USD Price DataFloat[], np.arr, pd.Series
periodThe period/window of the moving average50, 100int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The HMA[2.25, 2.35, 2.45 ...]Float[], np.arr, pd.Series

Similar to the ZLEMA, the Hull Moving Average (HMA) modifies the Weighted Moving Average, check out these docs

trima(data, period=50, use_series=False)

Arguments

ArgDescriptionExamplesType
dataData to passBTC-USD Price DataFloat[], np.arr, pd.Series
periodThe period/window of the moving average50, 100int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The TRIMA[2.25, 2.35, 2.45 ...]Float[], np.arr, pd.Series

The Triangle Moving Average (TRIMA) puts more weight on the middle items in the dataset and less weight on the new and old data within a single period. Info here

kaufman_adaptive_ma(data, period=50, use_series=False)

Arguments

ArgDescriptionExamplesType
dataData to passBTC-USD Price DataFloat[], np.arr, pd.Series
periodThe period/window of the moving average50, 100int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The KAMA[2.25, 2.35, 2.45 ...]Float[], np.arr, pd.Series

The KAMA adjusts its weighting relative to the current market conditions of noise. Check out this

macd(data, short_period=12, long_period=26, signal_period=9)

Arguments

ArgDescriptionExamplesType
dataData to passBTC-USD Price DataFloat[], np.arr, pd.Series
short_periodThe period/window of the short moving average50, 100int
long_periodThe period/window of the longer moving average150, 200Int
signal_periodThe period/window to use as the signal9int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array of Array-Like of The MACD signals[[-2.25, 0, 2.25, 1.25 ... ]]List[Float[], np.arr, pd.Series]

The MACD (Moving Average Convergence and Divergence) is a way of looking at two different moving averages and identifying key characteristics of price movements relative to the crossing and diverging of the two moving averages. It utilizes the exponential moving average, subtracting the long_period from the short_period and using that to compare against the signal_period. Check out this in Investopedia.

Oscillators

Oscillators vary in moving averages in that instead of trying to smooth out the data, they attempt to capture the noise and volatility in the price data. Just as the name states, these indicators attempt to capture how much prices oscillates.

rsi(data, period = 14, round_rsi = False, use_series=False)

Arguments

ArgDescriptionExamplesType
dataData to passBTC-USD Price DataFloat[], np.arr, pd.Series
periodThe period/window to use14, 50, 100int
round_rsiWhether to round to two decimal placesTrue, FalseBool
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The RSI[30, 45.5, 55.5]Float[], np.arr, pd.Series

The Relative Strength Index is perhaps one of the most commonly used oscillators. The RSI attempts to capture the momentum of recent price changes (how strong is the current uptrend and or how week is the downtrend). The RSI is calculated as shown here by Investopedia

aroon_oscillator(high_data, low_data, period=14, use_series=False)

Arguments

ArgDescriptionExamplesType
high_dataPrice Data HighsBTC-USD Price DataFloat[], np.arr, pd.Series
low_dataPrice Data LowsBTC-USD Price DataFloat[], np.arr, pd.Series
periodThe period/window to useTrue, FalseBool
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The Aroon Oscillator[30, 45.5, 55.5]Float[], np.arr, pd.Series

The aroon oscillator utilizes the aroon indicator to determine the current strength of a given trend. A value greater than zero signifies an uptrend and a value less than 0 signifies a downtrend. For more info, see here.

Blankly makes it extremely easy to get OHLCV data at your prescribed resolution, recall that interface.history() returns a dataframe with open, close, high, low, volume that users can grab and utilize for these oscillators and moving averages.

Example Use

from blankly.strategy import Strategy
from blankly import Alpaca, Interface
from blankly.metrics import aroon_oscillator

def price_event(price, symbol, state):
  interface: Interface = state.interface
  history = interface.history(symbol, 500, resolution=state.resolution)
  h = history['high']
  l = history['low']
  oscillation = aroon_oscillator(h, l)
  ...
a = Alpaca()
s = Strategy(a)
s.add_price_event(price_event, resolution='30m')

chande_momentum_oscillator(data, period=14, use_series=False)

Arguments

ArgDescriptionExamplesType
dataPrice DataBTC-USD Price DataFloat[], np.arr, pd.Series
periodThe period/window to useTrue, FalseBool
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The Chande Momentum Oscillator[30, 45.5, 55.5]Float[], np.arr, pd.Series

The chande momentum oscillator takes the sum of all recent gains, the sum of all recent losses and then divides that by the sum of all recent price movements (sum of all gains + losses). The formula is described by Investopedia

absolute_price_oscillator(data, short_period=12, long_period=26, use_series=False)

Arguments

ArgDescriptionExamplesType
dataPrice DataBTC-USD Price DataFloat[], np.arr, pd.Series
short_periodShort Period EMA25, 50int
long_periodLong Period EMA75, 100int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The Absolute Price Oscillator[30, 45.5, 55.5]Float[], np.arr, pd.Series

The absolute price oscillator helps detect the difference between two EMAs and expresses the results as an absolute value. More information can be seen here

percentage_price_oscilator(data, short_period=12, long_period=26, use_series=False)

Arguments

ArgDescriptionExamplesType
dataPrice DataBTC-USD Price DataFloat[], np.arr, pd.Series
short_periodShort Period EMA25, 50int
long_periodLong Period EMA75, 100int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The Percentage Price Oscillator[30, 45.5, 55.5]Float[], np.arr, pd.Series

The same as the absolute price, but returns values as a percentage difference.

stochastic_oscillator(high_data, low_data, close_data, pct_k_period=14, pct_k_slowing_period=3, pct_d_period=3, use_series=False)

Arguments

ArgDescriptionExamplesType
high_dataHigh Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
low_dataLow Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
close_dataClose Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
pct_k_period%K Period to Choose10, 15int
pct_k_slowing_period%K Slowing Period75, 100int
pct_d_period%D Period14, 23int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The Stochastic Oscillator[30, 45.5, 55.5]Float[], np.arr, pd.Series

The stochastic oscillator compares the closing data of a security to a range of varying prices over a specific time period. More information can be found on Investopedia

stochastic_rsi(data, period=14, smooth_pct_k=3, smooth_pct_d=3, use_series=False)

Arguments

ArgDescriptionExamplesType
dataPrice DataBTC-USD Price DataFloat[], np.arr, pd.Series
periodRSI Period10, 15Int
smooth_pct_k%K Smoothing Period10, 15Int
smooth_pct_d%D Smoothing Period10, 15int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of The Stochastic Oscillator[30, 45.5, 55.5]Float[], np.arr, pd.Series

The stochastic RSI combines the RSI with the stochastic oscillators. More info can be found here.

Other Indicators

bbands(data, period=14, stddev=2)

Arguments

ArgDescriptionExamplesType
dataPrice DataBTC-USD Price DataFloat[], np.arr, pd.Series
periodSMA Period20int
stddev# of Standard Deviations Away from Moving Average2, 3int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
2D Array-Like of The Bollinger Bands[[30, 25], [75, 55]]Float[], np.arr, pd.Series

Bollinger Bands are a very popular technical indicator to measure the strength of an uptrend or downtrend. It is also a way to help determine trend reversals. View Investopedia's Explanation.

wad(high_data, low_data, close_data, use_series=False)

Arguments

ArgDescriptionExamplesType
high_dataHigh Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
low_dataLow Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
close_dataClose Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of WAD[[30, 25], [75, 55]]Float[], np.arr, pd.Series

The Williams accumulation/distribution helps determine a trend direction. View this for more info.

wilders(data, period=50, use_series=False)

Arguments

ArgDescriptionExamplesType
dataHigh Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
periodPeriod to Use50, 100Int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of Wilders[20, 25, 30]Float[], np.arr, pd.Series

willr(high_data, low_data, close_data, period=50, use_series=False)

Arguments

ArgDescriptionExamplesType
high_dataHigh Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
low_dataLow Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
close_dataClose Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of Wilders[20, 25, 30]Float[], np.arr, pd.Series

The Williams %R is a measure similar to RSI and the stochastic oscillator where it measures overbought and oversold territory. More information is on Investopedia

true_range(high_data, low_data, close_data, use_series=False)

Arguments

ArgDescriptionExamplesType
high_dataHigh Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
low_dataLow Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
close_dataClose Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of True Range[20, 25, 30]Float[], np.arr, pd.Series

The true range takes the greatest of high - close and low - close for every data point

average_true_range(high_data, low_data, close_data, period=50, use_series=False)

Arguments

ArgDescriptionExamplesType
high_dataHigh Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
low_dataLow Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
close_dataClose Price DataBTC-USD Price DataFloat[], np.arr, pd.Series
periodMoving Average Period50, 100Int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of True Range[20, 25, 30]Float[], np.arr, pd.Series

The average true range takes the greatest of high - close and low - close for every data point and then takes a moving average of the points. More information can be found here.

Statistics

We offer a variety of general statistics as part of our indicators. All of our statistics are implemented so that they work on a period of data (i.e. they're rolling and return an Array-Like).

stddev_period(data, period=14, use_series=False)

Arguments

ArgDescriptionExamplesType
dataAny Type of Array DataBTC-USD Price DataFloat[], np.arr, pd.Series
periodRolling Window50, 100Int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of Standard Deviation[20, 25, 30]Float[], np.arr, pd.Series

var_period(data, period=14, use_series=False)

Arguments

ArgDescriptionExamplesType
dataAny Type of Array DataBTC-USD Price DataFloat[], np.arr, pd.Series
periodRolling Window50, 100Int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of Variance[20, 25, 30]Float[], np.arr, pd.Series

stderr_period(data, period=14, use_series=False)

Arguments

ArgDescriptionExamplesType
dataAny Type of Array DataBTC-USD Price DataFloat[], np.arr, pd.Series
periodRolling Window50, 100Int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of Standard Error[20, 25, 30]Float[], np.arr, pd.Series

min_period(data, period, use_series=False)

Arguments

ArgDescriptionExamplesType
dataAny Type of Array DataBTC-USD Price DataFloat[], np.arr, pd.Series
periodRolling Window50, 100Int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of Minimums[20, 25, 30]Float[], np.arr, pd.Series

max_period(data, period, use_series=False)

Arguments

ArgDescriptionExamplesType
dataAny Type of Array DataBTC-USD Price DataFloat[], np.arr, pd.Series
periodRolling Window50, 100Int
use_seriesWhether or not to return as a pd.SeriesTrue, Falsebool

Returns

DescriptionExamplesType
Array-Like of Maximums[20, 25, 30]Float[], np.arr, pd.Series