1353 lines
44 KiB
Python
1353 lines
44 KiB
Python
"""
|
|
.. module:: momentum
|
|
:synopsis: Momentum Indicators.
|
|
|
|
.. moduleauthor:: Dario Lopez Padial (Bukosabino)
|
|
|
|
"""
|
|
import numpy as np
|
|
import pandas as pd
|
|
|
|
from ta.utils import IndicatorMixin, _ema
|
|
|
|
|
|
class RSIIndicator(IndicatorMixin):
|
|
"""Relative Strength Index (RSI)
|
|
|
|
Compares the magnitude of recent gains and losses over a specified time
|
|
period to measure speed and change of price movements of a security. It is
|
|
primarily used to attempt to identify overbought or oversold conditions in
|
|
the trading of an asset.
|
|
|
|
https://www.investopedia.com/terms/r/rsi.asp
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window(int): n period.
|
|
fillna(bool): if True, fill nan values.
|
|
"""
|
|
|
|
def __init__(self, close: pd.Series, window: int = 14, fillna: bool = False):
|
|
self._close = close
|
|
self._window = window
|
|
self._fillna = fillna
|
|
self._run()
|
|
|
|
def _run(self):
|
|
diff = self._close.diff(1)
|
|
up_direction = diff.where(diff > 0, 0.0)
|
|
down_direction = -diff.where(diff < 0, 0.0)
|
|
min_periods = 0 if self._fillna else self._window
|
|
emaup = up_direction.ewm(
|
|
alpha=1 / self._window, min_periods=min_periods, adjust=False
|
|
).mean()
|
|
emadn = down_direction.ewm(
|
|
alpha=1 / self._window, min_periods=min_periods, adjust=False
|
|
).mean()
|
|
relative_strength = emaup / emadn
|
|
self._rsi = pd.Series(
|
|
np.where(emadn == 0, 100, 100 - (100 / (1 + relative_strength))),
|
|
index=self._close.index,
|
|
)
|
|
|
|
def rsi(self) -> pd.Series:
|
|
"""Relative Strength Index (RSI)
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
rsi_series = self._check_fillna(self._rsi, value=50)
|
|
return pd.Series(rsi_series, name="rsi")
|
|
|
|
|
|
class TSIIndicator(IndicatorMixin):
|
|
"""True strength index (TSI)
|
|
|
|
Shows both trend direction and overbought/oversold conditions.
|
|
|
|
https://school.stockcharts.com/doku.php?id=technical_indicators:true_strength_index
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window_slow(int): high period.
|
|
window_fast(int): low period.
|
|
fillna(bool): if True, fill nan values.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
close: pd.Series,
|
|
window_slow: int = 25,
|
|
window_fast: int = 13,
|
|
fillna: bool = False,
|
|
):
|
|
self._close = close
|
|
self._window_slow = window_slow
|
|
self._window_fast = window_fast
|
|
self._fillna = fillna
|
|
self._run()
|
|
|
|
def _run(self):
|
|
diff_close = self._close - self._close.shift(1)
|
|
min_periods_r = 0 if self._fillna else self._window_slow
|
|
min_periods_s = 0 if self._fillna else self._window_fast
|
|
smoothed = (
|
|
diff_close.ewm(
|
|
span=self._window_slow, min_periods=min_periods_r, adjust=False
|
|
)
|
|
.mean()
|
|
.ewm(span=self._window_fast, min_periods=min_periods_s, adjust=False)
|
|
.mean()
|
|
)
|
|
smoothed_abs = (
|
|
abs(diff_close)
|
|
.ewm(span=self._window_slow, min_periods=min_periods_r, adjust=False)
|
|
.mean()
|
|
.ewm(span=self._window_fast, min_periods=min_periods_s, adjust=False)
|
|
.mean()
|
|
)
|
|
self._tsi = smoothed / smoothed_abs
|
|
self._tsi *= 100
|
|
|
|
def tsi(self) -> pd.Series:
|
|
"""True strength index (TSI)
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
tsi_series = self._check_fillna(self._tsi, value=0)
|
|
return pd.Series(tsi_series, name="tsi")
|
|
|
|
|
|
class UltimateOscillator(IndicatorMixin):
|
|
"""Ultimate Oscillator
|
|
|
|
Larry Williams' (1976) signal, a momentum oscillator designed to capture
|
|
momentum across three different timeframes.
|
|
|
|
http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:ultimate_oscillator
|
|
|
|
BP = Close - Minimum(Low or Prior Close).
|
|
TR = Maximum(High or Prior Close) - Minimum(Low or Prior Close)
|
|
Average7 = (7-period BP Sum) / (7-period TR Sum)
|
|
Average14 = (14-period BP Sum) / (14-period TR Sum)
|
|
Average28 = (28-period BP Sum) / (28-period TR Sum)
|
|
|
|
UO = 100 x [(4 x Average7)+(2 x Average14)+Average28]/(4+2+1)
|
|
|
|
Args:
|
|
high(pandas.Series): dataset 'High' column.
|
|
low(pandas.Series): dataset 'Low' column.
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window1(int): short period.
|
|
window2(int): medium period.
|
|
window3(int): long period.
|
|
weight1(float): weight of short BP average for UO.
|
|
weight2(float): weight of medium BP average for UO.
|
|
weight3(float): weight of long BP average for UO.
|
|
fillna(bool): if True, fill nan values with 50.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
high: pd.Series,
|
|
low: pd.Series,
|
|
close: pd.Series,
|
|
window1: int = 7,
|
|
window2: int = 14,
|
|
window3: int = 28,
|
|
weight1: float = 4.0,
|
|
weight2: float = 2.0,
|
|
weight3: float = 1.0,
|
|
fillna: bool = False,
|
|
):
|
|
self._high = high
|
|
self._low = low
|
|
self._close = close
|
|
self._window1 = window1
|
|
self._window2 = window2
|
|
self._window3 = window3
|
|
self._weight1 = weight1
|
|
self._weight2 = weight2
|
|
self._weight3 = weight3
|
|
self._fillna = fillna
|
|
self._run()
|
|
|
|
def _run(self):
|
|
close_shift = self._close.shift(1)
|
|
true_range = self._true_range(self._high, self._low, close_shift)
|
|
buying_pressure = self._close - pd.DataFrame(
|
|
{"low": self._low, "close": close_shift}
|
|
).min(axis=1, skipna=False)
|
|
min_periods_s = 0 if self._fillna else self._window1
|
|
min_periods_m = 0 if self._fillna else self._window2
|
|
min_periods_len = 0 if self._fillna else self._window3
|
|
avg_s = (
|
|
buying_pressure.rolling(self._window1, min_periods=min_periods_s).sum()
|
|
/ true_range.rolling(self._window1, min_periods=min_periods_s).sum()
|
|
)
|
|
avg_m = (
|
|
buying_pressure.rolling(self._window2, min_periods=min_periods_m).sum()
|
|
/ true_range.rolling(self._window2, min_periods=min_periods_m).sum()
|
|
)
|
|
avg_l = (
|
|
buying_pressure.rolling(self._window3, min_periods=min_periods_len).sum()
|
|
/ true_range.rolling(self._window3, min_periods=min_periods_len).sum()
|
|
)
|
|
self._uo = (
|
|
100.0
|
|
* (
|
|
(self._weight1 * avg_s)
|
|
+ (self._weight2 * avg_m)
|
|
+ (self._weight3 * avg_l)
|
|
)
|
|
/ (self._weight1 + self._weight2 + self._weight3)
|
|
)
|
|
|
|
def ultimate_oscillator(self) -> pd.Series:
|
|
"""Ultimate Oscillator
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
ultimate_osc = self._check_fillna(self._uo, value=50)
|
|
return pd.Series(ultimate_osc, name="uo")
|
|
|
|
|
|
class StochasticOscillator(IndicatorMixin):
|
|
"""Stochastic Oscillator
|
|
|
|
Developed in the late 1950s by George Lane. The stochastic
|
|
oscillator presents the location of the closing price of a
|
|
stock in relation to the high and low range of the price
|
|
of a stock over a period of time, typically a 14-day period.
|
|
|
|
https://school.stockcharts.com/doku.php?id=technical_indicators:stochastic_oscillator_fast_slow_and_full
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Close' column.
|
|
high(pandas.Series): dataset 'High' column.
|
|
low(pandas.Series): dataset 'Low' column.
|
|
window(int): n period.
|
|
smooth_window(int): sma period over stoch_k.
|
|
fillna(bool): if True, fill nan values.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
high: pd.Series,
|
|
low: pd.Series,
|
|
close: pd.Series,
|
|
window: int = 14,
|
|
smooth_window: int = 3,
|
|
fillna: bool = False,
|
|
):
|
|
self._close = close
|
|
self._high = high
|
|
self._low = low
|
|
self._window = window
|
|
self._smooth_window = smooth_window
|
|
self._fillna = fillna
|
|
self._run()
|
|
|
|
def _run(self):
|
|
min_periods = 0 if self._fillna else self._window
|
|
smin = self._low.rolling(self._window, min_periods=min_periods).min()
|
|
smax = self._high.rolling(self._window, min_periods=min_periods).max()
|
|
self._stoch_k = 100 * (self._close - smin) / (smax - smin)
|
|
|
|
def stoch(self) -> pd.Series:
|
|
"""Stochastic Oscillator
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
stoch_k = self._check_fillna(self._stoch_k, value=50)
|
|
return pd.Series(stoch_k, name="stoch_k")
|
|
|
|
def stoch_signal(self) -> pd.Series:
|
|
"""Signal Stochastic Oscillator
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
min_periods = 0 if self._fillna else self._smooth_window
|
|
stoch_d = self._stoch_k.rolling(
|
|
self._smooth_window, min_periods=min_periods
|
|
).mean()
|
|
stoch_d = self._check_fillna(stoch_d, value=50)
|
|
return pd.Series(stoch_d, name="stoch_k_signal")
|
|
|
|
|
|
class KAMAIndicator(IndicatorMixin):
|
|
"""Kaufman's Adaptive Moving Average (KAMA)
|
|
|
|
Moving average designed to account for market noise or volatility. KAMA
|
|
will closely follow prices when the price swings are relatively small and
|
|
the noise is low. KAMA will adjust when the price swings widen and follow
|
|
prices from a greater distance. This trend-following indicator can be
|
|
used to identify the overall trend, time turning points and filter price
|
|
movements.
|
|
|
|
https://www.tradingview.com/ideas/kama/
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window(int): n period.
|
|
pow1(int): number of periods for the fastest EMA constant.
|
|
pow2(int): number of periods for the slowest EMA constant.
|
|
fillna(bool): if True, fill nan values.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
close: pd.Series,
|
|
window: int = 10,
|
|
pow1: int = 2,
|
|
pow2: int = 30,
|
|
fillna: bool = False,
|
|
):
|
|
self._close = close
|
|
self._window = window
|
|
self._pow1 = pow1
|
|
self._pow2 = pow2
|
|
self._fillna = fillna
|
|
self._run()
|
|
|
|
def _run(self):
|
|
close_values = self._close.values
|
|
vol = pd.Series(abs(self._close - np.roll(self._close, 1)))
|
|
|
|
min_periods = 0 if self._fillna else self._window
|
|
er_num = abs(close_values - np.roll(close_values, self._window))
|
|
er_den = vol.rolling(self._window, min_periods=min_periods).sum()
|
|
efficiency_ratio = np.divide(
|
|
er_num, er_den, out=np.zeros_like(er_num), where=er_den != 0
|
|
)
|
|
|
|
smoothing_constant = (
|
|
(
|
|
efficiency_ratio * (2.0 / (self._pow1 + 1) - 2.0 / (self._pow2 + 1.0))
|
|
+ 2 / (self._pow2 + 1.0)
|
|
)
|
|
** 2.0
|
|
).values
|
|
|
|
self._kama = np.zeros(smoothing_constant.size)
|
|
len_kama = len(self._kama)
|
|
first_value = True
|
|
|
|
for i in range(len_kama):
|
|
if np.isnan(smoothing_constant[i]):
|
|
self._kama[i] = np.nan
|
|
elif first_value:
|
|
self._kama[i] = close_values[i]
|
|
first_value = False
|
|
else:
|
|
self._kama[i] = self._kama[i - 1] + smoothing_constant[i] * (
|
|
close_values[i] - self._kama[i - 1]
|
|
)
|
|
|
|
def kama(self) -> pd.Series:
|
|
"""Kaufman's Adaptive Moving Average (KAMA)
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
kama_series = pd.Series(self._kama, index=self._close.index)
|
|
kama_series = self._check_fillna(kama_series, value=self._close)
|
|
return pd.Series(kama_series, name="kama")
|
|
|
|
|
|
class ROCIndicator(IndicatorMixin):
|
|
"""Rate of Change (ROC)
|
|
|
|
The Rate-of-Change (ROC) indicator, which is also referred to as simply
|
|
Momentum, is a pure momentum oscillator that measures the percent change in
|
|
price from one period to the next. The ROC calculation compares the current
|
|
price with the price “n” periods ago. The plot forms an oscillator that
|
|
fluctuates above and below the zero line as the Rate-of-Change moves from
|
|
positive to negative. As a momentum oscillator, ROC signals include
|
|
centerline crossovers, divergences and overbought-oversold readings.
|
|
Divergences fail to foreshadow reversals more often than not, so this
|
|
article will forgo a detailed discussion on them. Even though centerline
|
|
crossovers are prone to whipsaw, especially short-term, these crossovers
|
|
can be used to identify the overall trend. Identifying overbought or
|
|
oversold extremes comes naturally to the Rate-of-Change oscillator.
|
|
|
|
https://school.stockcharts.com/doku.php?id=technical_indicators:rate_of_change_roc_and_momentum
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window(int): n period.
|
|
fillna(bool): if True, fill nan values.
|
|
"""
|
|
|
|
def __init__(self, close: pd.Series, window: int = 12, fillna: bool = False):
|
|
self._close = close
|
|
self._window = window
|
|
self._fillna = fillna
|
|
self._run()
|
|
|
|
def _run(self):
|
|
self._roc = (
|
|
(self._close - self._close.shift(self._window))
|
|
/ self._close.shift(self._window)
|
|
) * 100
|
|
|
|
def roc(self) -> pd.Series:
|
|
"""Rate of Change (ROC)
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
roc_series = self._check_fillna(self._roc)
|
|
return pd.Series(roc_series, name="roc")
|
|
|
|
|
|
class AwesomeOscillatorIndicator(IndicatorMixin):
|
|
"""Awesome Oscillator
|
|
|
|
From: https://www.tradingview.com/wiki/Awesome_Oscillator_(AO)
|
|
|
|
The Awesome Oscillator is an indicator used to measure market momentum. AO
|
|
calculates the difference of a 34 Period and 5 Period Simple Moving
|
|
Averages. The Simple Moving Averages that are used are not calculated
|
|
using closing price but rather each bar's midpoints. AO is generally used
|
|
to affirm trends or to anticipate possible reversals.
|
|
|
|
From: https://www.ifcm.co.uk/ntx-indicators/awesome-oscillator
|
|
|
|
Awesome Oscillator is a 34-period simple moving average, plotted through
|
|
the central points of the bars (H+L)/2, and subtracted from the 5-period
|
|
simple moving average, graphed across the central points of the bars
|
|
(H+L)/2.
|
|
|
|
MEDIAN PRICE = (HIGH+LOW)/2
|
|
|
|
AO = SMA(MEDIAN PRICE, 5)-SMA(MEDIAN PRICE, 34)
|
|
|
|
where
|
|
|
|
SMA — Simple Moving Average.
|
|
|
|
Args:
|
|
high(pandas.Series): dataset 'High' column.
|
|
low(pandas.Series): dataset 'Low' column.
|
|
window1(int): short period.
|
|
window2(int): long period.
|
|
fillna(bool): if True, fill nan values with -50.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
high: pd.Series,
|
|
low: pd.Series,
|
|
window1: int = 5,
|
|
window2: int = 34,
|
|
fillna: bool = False,
|
|
):
|
|
self._high = high
|
|
self._low = low
|
|
self._window1 = window1
|
|
self._window2 = window2
|
|
self._fillna = fillna
|
|
self._run()
|
|
|
|
def _run(self):
|
|
median_price = 0.5 * (self._high + self._low)
|
|
min_periods_s = 0 if self._fillna else self._window1
|
|
min_periods_len = 0 if self._fillna else self._window2
|
|
self._ao = (
|
|
median_price.rolling(self._window1, min_periods=min_periods_s).mean()
|
|
- median_price.rolling(self._window2, min_periods=min_periods_len).mean()
|
|
)
|
|
|
|
def awesome_oscillator(self) -> pd.Series:
|
|
"""Awesome Oscillator
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
ao_series = self._check_fillna(self._ao, value=0)
|
|
return pd.Series(ao_series, name="ao")
|
|
|
|
|
|
class WilliamsRIndicator(IndicatorMixin):
|
|
"""Williams %R
|
|
|
|
Developed by Larry Williams, Williams %R is a momentum indicator that is
|
|
the inverse of the Fast Stochastic Oscillator. Also referred to as %R,
|
|
Williams %R reflects the level of the close relative to the highest high
|
|
for the look-back period. In contrast, the Stochastic Oscillator reflects
|
|
the level of the close relative to the lowest low. %R corrects for the
|
|
inversion by multiplying the raw value by -100. As a result, the Fast
|
|
Stochastic Oscillator and Williams %R produce the exact same lines, only
|
|
the scaling is different. Williams %R oscillates from 0 to -100.
|
|
|
|
Readings from 0 to -20 are considered overbought. Readings from -80 to -100
|
|
are considered oversold.
|
|
|
|
Unsurprisingly, signals derived from the Stochastic Oscillator are also
|
|
applicable to Williams %R.
|
|
|
|
%R = (Highest High - Close)/(Highest High - Lowest Low) * -100
|
|
|
|
Lowest Low = lowest low for the look-back period
|
|
Highest High = highest high for the look-back period
|
|
%R is multiplied by -100 correct the inversion and move the decimal.
|
|
|
|
https://school.stockcharts.com/doku.php?id=technical_indicators:williams_r
|
|
|
|
The Williams %R oscillates from 0 to -100. When the indicator produces
|
|
readings from 0 to -20, this indicates overbought market conditions. When
|
|
readings are -80 to -100, it indicates oversold market conditions.
|
|
|
|
Args:
|
|
high(pandas.Series): dataset 'High' column.
|
|
low(pandas.Series): dataset 'Low' column.
|
|
close(pandas.Series): dataset 'Close' column.
|
|
lbp(int): lookback period.
|
|
fillna(bool): if True, fill nan values with -50.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
high: pd.Series,
|
|
low: pd.Series,
|
|
close: pd.Series,
|
|
lbp: int = 14,
|
|
fillna: bool = False,
|
|
):
|
|
self._high = high
|
|
self._low = low
|
|
self._close = close
|
|
self._lbp = lbp
|
|
self._fillna = fillna
|
|
self._run()
|
|
|
|
def _run(self):
|
|
min_periods = 0 if self._fillna else self._lbp
|
|
highest_high = self._high.rolling(
|
|
self._lbp, min_periods=min_periods
|
|
).max() # highest high over lookback period lbp
|
|
lowest_low = self._low.rolling(
|
|
self._lbp, min_periods=min_periods
|
|
).min() # lowest low over lookback period lbp
|
|
self._wr = -100 * (highest_high - self._close) / (highest_high - lowest_low)
|
|
|
|
def williams_r(self) -> pd.Series:
|
|
"""Williams %R
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
wr_series = self._check_fillna(self._wr, value=-50)
|
|
return pd.Series(wr_series, name="wr")
|
|
|
|
|
|
class StochRSIIndicator(IndicatorMixin):
|
|
"""Stochastic RSI
|
|
|
|
The StochRSI oscillator was developed to take advantage of both momentum
|
|
indicators in order to create a more sensitive indicator that is attuned to
|
|
a specific security's historical performance rather than a generalized analysis
|
|
of price change.
|
|
|
|
https://school.stockcharts.com/doku.php?id=technical_indicators:stochrsi
|
|
https://www.investopedia.com/terms/s/stochrsi.asp
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window(int): n period
|
|
smooth1(int): moving average of Stochastic RSI
|
|
smooth2(int): moving average of %K
|
|
fillna(bool): if True, fill nan values.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
close: pd.Series,
|
|
window: int = 14,
|
|
smooth1: int = 3,
|
|
smooth2: int = 3,
|
|
fillna: bool = False,
|
|
):
|
|
self._close = close
|
|
self._window = window
|
|
self._smooth1 = smooth1
|
|
self._smooth2 = smooth2
|
|
self._fillna = fillna
|
|
self._run()
|
|
|
|
def _run(self):
|
|
self._rsi = RSIIndicator(
|
|
close=self._close, window=self._window, fillna=self._fillna
|
|
).rsi()
|
|
lowest_low_rsi = self._rsi.rolling(self._window).min()
|
|
self._stochrsi = (self._rsi - lowest_low_rsi) / (
|
|
self._rsi.rolling(self._window).max() - lowest_low_rsi
|
|
)
|
|
self._stochrsi_k = self._stochrsi.rolling(self._smooth1).mean()
|
|
|
|
def stochrsi(self):
|
|
"""Stochastic RSI
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
stochrsi_series = self._check_fillna(self._stochrsi)
|
|
return pd.Series(stochrsi_series, name="stochrsi")
|
|
|
|
def stochrsi_k(self):
|
|
"""Stochastic RSI %k
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
stochrsi_k_series = self._check_fillna(self._stochrsi_k)
|
|
return pd.Series(stochrsi_k_series, name="stochrsi_k")
|
|
|
|
def stochrsi_d(self):
|
|
"""Stochastic RSI %d
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
stochrsi_d_series = self._stochrsi_k.rolling(self._smooth2).mean()
|
|
stochrsi_d_series = self._check_fillna(stochrsi_d_series)
|
|
return pd.Series(stochrsi_d_series, name="stochrsi_d")
|
|
|
|
|
|
class PercentagePriceOscillator(IndicatorMixin):
|
|
"""
|
|
The Percentage Price Oscillator (PPO) is a momentum oscillator that measures
|
|
the difference between two moving averages as a percentage of the larger moving average.
|
|
|
|
https://school.stockcharts.com/doku.php?id=technical_indicators:price_oscillators_ppo
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Price' column.
|
|
window_slow(int): n period long-term.
|
|
window_fast(int): n period short-term.
|
|
window_sign(int): n period to signal.
|
|
fillna(bool): if True, fill nan values.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
close: pd.Series,
|
|
window_slow: int = 26,
|
|
window_fast: int = 12,
|
|
window_sign: int = 9,
|
|
fillna: bool = False,
|
|
):
|
|
self._close = close
|
|
self._window_slow = window_slow
|
|
self._window_fast = window_fast
|
|
self._window_sign = window_sign
|
|
self._fillna = fillna
|
|
self._run()
|
|
|
|
def _run(self):
|
|
_emafast = _ema(self._close, self._window_fast, self._fillna)
|
|
_emaslow = _ema(self._close, self._window_slow, self._fillna)
|
|
self._ppo = ((_emafast - _emaslow) / _emaslow) * 100
|
|
self._ppo_signal = _ema(self._ppo, self._window_sign, self._fillna)
|
|
self._ppo_hist = self._ppo - self._ppo_signal
|
|
|
|
def ppo(self):
|
|
"""Percentage Price Oscillator Line
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
ppo_series = self._check_fillna(self._ppo, value=0)
|
|
return pd.Series(
|
|
ppo_series, name=f"PPO_{self._window_fast}_{self._window_slow}"
|
|
)
|
|
|
|
def ppo_signal(self):
|
|
"""Percentage Price Oscillator Signal Line
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
|
|
ppo_signal_series = self._check_fillna(self._ppo_signal, value=0)
|
|
return pd.Series(
|
|
ppo_signal_series, name=f"PPO_sign_{self._window_fast}_{self._window_slow}"
|
|
)
|
|
|
|
def ppo_hist(self):
|
|
"""Percentage Price Oscillator Histogram
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
|
|
ppo_hist_series = self._check_fillna(self._ppo_hist, value=0)
|
|
return pd.Series(
|
|
ppo_hist_series, name=f"PPO_hist_{self._window_fast}_{self._window_slow}"
|
|
)
|
|
|
|
|
|
class PercentageVolumeOscillator(IndicatorMixin):
|
|
"""
|
|
The Percentage Volume Oscillator (PVO) is a momentum oscillator for volume.
|
|
The PVO measures the difference between two volume-based moving averages as a
|
|
percentage of the larger moving average.
|
|
|
|
https://school.stockcharts.com/doku.php?id=technical_indicators:percentage_volume_oscillator_pvo
|
|
|
|
Args:
|
|
volume(pandas.Series): dataset 'Volume' column.
|
|
window_slow(int): n period long-term.
|
|
window_fast(int): n period short-term.
|
|
window_sign(int): n period to signal.
|
|
fillna(bool): if True, fill nan values.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
volume: pd.Series,
|
|
window_slow: int = 26,
|
|
window_fast: int = 12,
|
|
window_sign: int = 9,
|
|
fillna: bool = False,
|
|
):
|
|
self._volume = volume
|
|
self._window_slow = window_slow
|
|
self._window_fast = window_fast
|
|
self._window_sign = window_sign
|
|
self._fillna = fillna
|
|
self._run()
|
|
|
|
def _run(self):
|
|
_emafast = _ema(self._volume, self._window_fast, self._fillna)
|
|
_emaslow = _ema(self._volume, self._window_slow, self._fillna)
|
|
self._pvo = ((_emafast - _emaslow) / _emaslow) * 100
|
|
self._pvo_signal = _ema(self._pvo, self._window_sign, self._fillna)
|
|
self._pvo_hist = self._pvo - self._pvo_signal
|
|
|
|
def pvo(self) -> pd.Series:
|
|
"""PVO Line
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
pvo_series = self._check_fillna(self._pvo, value=0)
|
|
return pd.Series(
|
|
pvo_series, name=f"PVO_{self._window_fast}_{self._window_slow}"
|
|
)
|
|
|
|
def pvo_signal(self) -> pd.Series:
|
|
"""Signal Line
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
|
|
pvo_signal_series = self._check_fillna(self._pvo_signal, value=0)
|
|
return pd.Series(
|
|
pvo_signal_series, name=f"PVO_sign_{self._window_fast}_{self._window_slow}"
|
|
)
|
|
|
|
def pvo_hist(self) -> pd.Series:
|
|
"""Histgram
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
|
|
pvo_hist_series = self._check_fillna(self._pvo_hist, value=0)
|
|
return pd.Series(
|
|
pvo_hist_series, name=f"PVO_hist_{self._window_fast}_{self._window_slow}"
|
|
)
|
|
|
|
|
|
def rsi(close, window=14, fillna=False) -> pd.Series:
|
|
"""Relative Strength Index (RSI)
|
|
|
|
Compares the magnitude of recent gains and losses over a specified time
|
|
period to measure speed and change of price movements of a security. It is
|
|
primarily used to attempt to identify overbought or oversold conditions in
|
|
the trading of an asset.
|
|
|
|
https://www.investopedia.com/terms/r/rsi.asp
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window(int): n period.
|
|
fillna(bool): if True, fill nan values.
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
return RSIIndicator(close=close, window=window, fillna=fillna).rsi()
|
|
|
|
|
|
def tsi(close, window_slow=25, window_fast=13, fillna=False) -> pd.Series:
|
|
"""True strength index (TSI)
|
|
|
|
Shows both trend direction and overbought/oversold conditions.
|
|
|
|
https://en.wikipedia.org/wiki/True_strength_index
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window_slow(int): high period.
|
|
window_fast(int): low period.
|
|
fillna(bool): if True, fill nan values.
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
return TSIIndicator(
|
|
close=close, window_slow=window_slow, window_fast=window_fast, fillna=fillna
|
|
).tsi()
|
|
|
|
|
|
def ultimate_oscillator(
|
|
high,
|
|
low,
|
|
close,
|
|
window1=7,
|
|
window2=14,
|
|
window3=28,
|
|
weight1=4.0,
|
|
weight2=2.0,
|
|
weight3=1.0,
|
|
fillna=False,
|
|
) -> pd.Series:
|
|
"""Ultimate Oscillator
|
|
|
|
Larry Williams' (1976) signal, a momentum oscillator designed to capture
|
|
momentum across three different timeframes.
|
|
|
|
http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:ultimate_oscillator
|
|
|
|
BP = Close - Minimum(Low or Prior Close).
|
|
TR = Maximum(High or Prior Close) - Minimum(Low or Prior Close)
|
|
Average7 = (7-period BP Sum) / (7-period TR Sum)
|
|
Average14 = (14-period BP Sum) / (14-period TR Sum)
|
|
Average28 = (28-period BP Sum) / (28-period TR Sum)
|
|
|
|
UO = 100 x [(4 x Average7)+(2 x Average14)+Average28]/(4+2+1)
|
|
|
|
Args:
|
|
high(pandas.Series): dataset 'High' column.
|
|
low(pandas.Series): dataset 'Low' column.
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window1(int): short period.
|
|
window2(int): medium period.
|
|
window3(int): long period.
|
|
weight1(float): weight of short BP average for UO.
|
|
weight2(float): weight of medium BP average for UO.
|
|
weight3(float): weight of long BP average for UO.
|
|
fillna(bool): if True, fill nan values with 50.
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
|
|
"""
|
|
return UltimateOscillator(
|
|
high=high,
|
|
low=low,
|
|
close=close,
|
|
window1=window1,
|
|
window2=window2,
|
|
window3=window3,
|
|
weight1=weight1,
|
|
weight2=weight2,
|
|
weight3=weight3,
|
|
fillna=fillna,
|
|
).ultimate_oscillator()
|
|
|
|
|
|
def stoch(high, low, close, window=14, smooth_window=3, fillna=False) -> pd.Series:
|
|
"""Stochastic Oscillator
|
|
|
|
Developed in the late 1950s by George Lane. The stochastic
|
|
oscillator presents the location of the closing price of a
|
|
stock in relation to the high and low range of the price
|
|
of a stock over a period of time, typically a 14-day period.
|
|
|
|
https://www.investopedia.com/terms/s/stochasticoscillator.asp
|
|
|
|
Args:
|
|
high(pandas.Series): dataset 'High' column.
|
|
low(pandas.Series): dataset 'Low' column.
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window(int): n period.
|
|
smooth_window(int): sma period over stoch_k
|
|
fillna(bool): if True, fill nan values.
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
|
|
return StochasticOscillator(
|
|
high=high,
|
|
low=low,
|
|
close=close,
|
|
window=window,
|
|
smooth_window=smooth_window,
|
|
fillna=fillna,
|
|
).stoch()
|
|
|
|
|
|
def stoch_signal(
|
|
high, low, close, window=14, smooth_window=3, fillna=False
|
|
) -> pd.Series:
|
|
"""Stochastic Oscillator Signal
|
|
|
|
Shows SMA of Stochastic Oscillator. Typically a 3 day SMA.
|
|
|
|
https://www.investopedia.com/terms/s/stochasticoscillator.asp
|
|
|
|
Args:
|
|
high(pandas.Series): dataset 'High' column.
|
|
low(pandas.Series): dataset 'Low' column.
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window(int): n period.
|
|
smooth_window(int): sma period over stoch_k
|
|
fillna(bool): if True, fill nan values.
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
return StochasticOscillator(
|
|
high=high,
|
|
low=low,
|
|
close=close,
|
|
window=window,
|
|
smooth_window=smooth_window,
|
|
fillna=fillna,
|
|
).stoch_signal()
|
|
|
|
|
|
def williams_r(high, low, close, lbp=14, fillna=False) -> pd.Series:
|
|
"""Williams %R
|
|
|
|
From: http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:williams_r
|
|
|
|
Developed by Larry Williams, Williams %R is a momentum indicator that is
|
|
the inverse of the Fast Stochastic Oscillator. Also referred to as %R,
|
|
Williams %R reflects the level of the close relative to the highest high
|
|
for the look-back period. In contrast, the Stochastic Oscillator reflects
|
|
the level of the close relative to the lowest low. %R corrects for the
|
|
inversion by multiplying the raw value by -100. As a result, the Fast
|
|
Stochastic Oscillator and Williams %R produce the exact same lines, only
|
|
the scaling is different. Williams %R oscillates from 0 to -100.
|
|
|
|
Readings from 0 to -20 are considered overbought. Readings from -80 to -100
|
|
are considered oversold.
|
|
|
|
Unsurprisingly, signals derived from the Stochastic Oscillator are also
|
|
applicable to Williams %R.
|
|
|
|
%R = (Highest High - Close)/(Highest High - Lowest Low) * -100
|
|
|
|
Lowest Low = lowest low for the look-back period
|
|
Highest High = highest high for the look-back period
|
|
%R is multiplied by -100 correct the inversion and move the decimal.
|
|
|
|
From: https://www.investopedia.com/terms/w/williamsr.asp
|
|
The Williams %R oscillates from 0 to -100. When the indicator produces
|
|
readings from 0 to -20, this indicates overbought market conditions. When
|
|
readings are -80 to -100, it indicates oversold market conditions.
|
|
|
|
Args:
|
|
high(pandas.Series): dataset 'High' column.
|
|
low(pandas.Series): dataset 'Low' column.
|
|
close(pandas.Series): dataset 'Close' column.
|
|
lbp(int): lookback period.
|
|
fillna(bool): if True, fill nan values with -50.
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
return WilliamsRIndicator(
|
|
high=high, low=low, close=close, lbp=lbp, fillna=fillna
|
|
).williams_r()
|
|
|
|
|
|
def awesome_oscillator(high, low, window1=5, window2=34, fillna=False) -> pd.Series:
|
|
"""Awesome Oscillator
|
|
|
|
From: https://www.tradingview.com/wiki/Awesome_Oscillator_(AO)
|
|
|
|
The Awesome Oscillator is an indicator used to measure market momentum. AO
|
|
calculates the difference of a 34 Period and 5 Period Simple Moving
|
|
Averages. The Simple Moving Averages that are used are not calculated
|
|
using closing price but rather each bar's midpoints. AO is generally used
|
|
to affirm trends or to anticipate possible reversals.
|
|
|
|
From: https://www.ifcm.co.uk/ntx-indicators/awesome-oscillator
|
|
|
|
Awesome Oscillator is a 34-period simple moving average, plotted through
|
|
the central points of the bars (H+L)/2, and subtracted from the 5-period
|
|
simple moving average, graphed across the central points of the bars
|
|
(H+L)/2.
|
|
|
|
MEDIAN PRICE = (HIGH+LOW)/2
|
|
|
|
AO = SMA(MEDIAN PRICE, 5)-SMA(MEDIAN PRICE, 34)
|
|
|
|
where
|
|
|
|
SMA — Simple Moving Average.
|
|
|
|
Args:
|
|
high(pandas.Series): dataset 'High' column.
|
|
low(pandas.Series): dataset 'Low' column.
|
|
window1(int): short period.
|
|
window2(int): long period.
|
|
fillna(bool): if True, fill nan values with -50.
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
return AwesomeOscillatorIndicator(
|
|
high=high, low=low, window1=window1, window2=window2, fillna=fillna
|
|
).awesome_oscillator()
|
|
|
|
|
|
def kama(close, window=10, pow1=2, pow2=30, fillna=False) -> pd.Series:
|
|
"""Kaufman's Adaptive Moving Average (KAMA)
|
|
|
|
Moving average designed to account for market noise or volatility. KAMA
|
|
will closely follow prices when the price swings are relatively small and
|
|
the noise is low. KAMA will adjust when the price swings widen and follow
|
|
prices from a greater distance. This trend-following indicator can be
|
|
used to identify the overall trend, time turning points and filter price
|
|
movements.
|
|
|
|
https://www.tradingview.com/ideas/kama/
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window(int): n number of periods for the efficiency ratio.
|
|
pow1(int): number of periods for the fastest EMA constant.
|
|
pow2(int): number of periods for the slowest EMA constant.
|
|
fillna(bool): if True, fill nan values.
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
return KAMAIndicator(
|
|
close=close, window=window, pow1=pow1, pow2=pow2, fillna=fillna
|
|
).kama()
|
|
|
|
|
|
def roc(close: pd.Series, window: int = 12, fillna: bool = False) -> pd.Series:
|
|
"""Rate of Change (ROC)
|
|
|
|
The Rate-of-Change (ROC) indicator, which is also referred to as simply
|
|
Momentum, is a pure momentum oscillator that measures the percent change in
|
|
price from one period to the next. The ROC calculation compares the current
|
|
price with the price “n” periods ago. The plot forms an oscillator that
|
|
fluctuates above and below the zero line as the Rate-of-Change moves from
|
|
positive to negative. As a momentum oscillator, ROC signals include
|
|
centerline crossovers, divergences and overbought-oversold readings.
|
|
Divergences fail to foreshadow reversals more often than not, so this
|
|
article will forgo a detailed discussion on them. Even though centerline
|
|
crossovers are prone to whipsaw, especially short-term, these crossovers
|
|
can be used to identify the overall trend. Identifying overbought or
|
|
oversold extremes comes naturally to the Rate-of-Change oscillator.
|
|
|
|
https://school.stockcharts.com/doku.php?id=technical_indicators:rate_of_change_roc_and_momentum
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window(int): n periods.
|
|
fillna(bool): if True, fill nan values.
|
|
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
|
|
"""
|
|
return ROCIndicator(close=close, window=window, fillna=fillna).roc()
|
|
|
|
|
|
def stochrsi(
|
|
close: pd.Series,
|
|
window: int = 14,
|
|
smooth1: int = 3,
|
|
smooth2: int = 3,
|
|
fillna: bool = False,
|
|
) -> pd.Series:
|
|
"""Stochastic RSI
|
|
|
|
The StochRSI oscillator was developed to take advantage of both momentum
|
|
indicators in order to create a more sensitive indicator that is attuned to
|
|
a specific security's historical performance rather than a generalized analysis
|
|
of price change.
|
|
|
|
https://www.investopedia.com/terms/s/stochrsi.asp
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window(int): n period
|
|
smooth1(int): moving average of Stochastic RSI
|
|
smooth2(int): moving average of %K
|
|
fillna(bool): if True, fill nan values.
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
return StochRSIIndicator(
|
|
close=close, window=window, smooth1=smooth1, smooth2=smooth2, fillna=fillna
|
|
).stochrsi()
|
|
|
|
|
|
def stochrsi_k(
|
|
close: pd.Series,
|
|
window: int = 14,
|
|
smooth1: int = 3,
|
|
smooth2: int = 3,
|
|
fillna: bool = False,
|
|
) -> pd.Series:
|
|
"""Stochastic RSI %k
|
|
|
|
The StochRSI oscillator was developed to take advantage of both momentum
|
|
indicators in order to create a more sensitive indicator that is attuned to
|
|
a specific security's historical performance rather than a generalized analysis
|
|
of price change.
|
|
|
|
https://www.investopedia.com/terms/s/stochrsi.asp
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window(int): n period
|
|
smooth1(int): moving average of Stochastic RSI
|
|
smooth2(int): moving average of %K
|
|
fillna(bool): if True, fill nan values.
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
return StochRSIIndicator(
|
|
close=close, window=window, smooth1=smooth1, smooth2=smooth2, fillna=fillna
|
|
).stochrsi_k()
|
|
|
|
|
|
def stochrsi_d(
|
|
close: pd.Series,
|
|
window: int = 14,
|
|
smooth1: int = 3,
|
|
smooth2: int = 3,
|
|
fillna: bool = False,
|
|
) -> pd.Series:
|
|
"""Stochastic RSI %d
|
|
|
|
The StochRSI oscillator was developed to take advantage of both momentum
|
|
indicators in order to create a more sensitive indicator that is attuned to
|
|
a specific security's historical performance rather than a generalized analysis
|
|
of price change.
|
|
|
|
https://www.investopedia.com/terms/s/stochrsi.asp
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Close' column.
|
|
window(int): n period
|
|
smooth1(int): moving average of Stochastic RSI
|
|
smooth2(int): moving average of %K
|
|
fillna(bool): if True, fill nan values.
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
return StochRSIIndicator(
|
|
close=close, window=window, smooth1=smooth1, smooth2=smooth2, fillna=fillna
|
|
).stochrsi_d()
|
|
|
|
|
|
def ppo(
|
|
close: pd.Series,
|
|
window_slow: int = 26,
|
|
window_fast: int = 12,
|
|
window_sign: int = 9,
|
|
fillna: bool = False,
|
|
) -> pd.Series:
|
|
"""
|
|
The Percentage Price Oscillator (PPO) is a momentum oscillator that measures
|
|
the difference between two moving averages as a percentage of the larger moving average.
|
|
|
|
https://school.stockcharts.com/doku.php?id=technical_indicators:price_oscillators_ppo
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Price' column.
|
|
window_slow(int): n period long-term.
|
|
window_fast(int): n period short-term.
|
|
window_sign(int): n period to signal.
|
|
fillna(bool): if True, fill nan values.
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
return PercentagePriceOscillator(
|
|
close=close,
|
|
window_slow=window_slow,
|
|
window_fast=window_fast,
|
|
window_sign=window_sign,
|
|
fillna=fillna,
|
|
).ppo()
|
|
|
|
|
|
def ppo_signal(
|
|
close: pd.Series, window_slow=26, window_fast=12, window_sign=9, fillna=False
|
|
) -> pd.Series:
|
|
"""
|
|
The Percentage Price Oscillator (PPO) is a momentum oscillator that measures
|
|
the difference between two moving averages as a percentage of the larger moving average.
|
|
|
|
https://school.stockcharts.com/doku.php?id=technical_indicators:price_oscillators_ppo
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Price' column.
|
|
window_slow(int): n period long-term.
|
|
window_fast(int): n period short-term.
|
|
window_sign(int): n period to signal.
|
|
fillna(bool): if True, fill nan values.
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
return PercentagePriceOscillator(
|
|
close=close,
|
|
window_slow=window_slow,
|
|
window_fast=window_fast,
|
|
window_sign=window_sign,
|
|
fillna=fillna,
|
|
).ppo_signal()
|
|
|
|
|
|
def ppo_hist(
|
|
close: pd.Series,
|
|
window_slow: int = 26,
|
|
window_fast: int = 12,
|
|
window_sign: int = 9,
|
|
fillna: bool = False,
|
|
) -> pd.Series:
|
|
"""
|
|
The Percentage Price Oscillator (PPO) is a momentum oscillator that measures
|
|
the difference between two moving averages as a percentage of the larger moving average.
|
|
|
|
https://school.stockcharts.com/doku.php?id=technical_indicators:price_oscillators_ppo
|
|
|
|
Args:
|
|
close(pandas.Series): dataset 'Price' column.
|
|
window_slow(int): n period long-term.
|
|
window_fast(int): n period short-term.
|
|
window_sign(int): n period to signal.
|
|
fillna(bool): if True, fill nan values.
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
return PercentagePriceOscillator(
|
|
close=close,
|
|
window_slow=window_slow,
|
|
window_fast=window_fast,
|
|
window_sign=window_sign,
|
|
fillna=fillna,
|
|
).ppo_hist()
|
|
|
|
|
|
def pvo(
|
|
volume: pd.Series,
|
|
window_slow: int = 26,
|
|
window_fast: int = 12,
|
|
window_sign: int = 9,
|
|
fillna: bool = False,
|
|
) -> pd.Series:
|
|
"""
|
|
The Percentage Volume Oscillator (PVO) is a momentum oscillator for volume.
|
|
The PVO measures the difference between two volume-based moving averages as a
|
|
percentage of the larger moving average.
|
|
|
|
https://school.stockcharts.com/doku.php?id=technical_indicators:percentage_volume_oscillator_pvo
|
|
|
|
Args:
|
|
volume(pandas.Series): dataset 'Volume' column.
|
|
window_slow(int): n period long-term.
|
|
window_fast(int): n period short-term.
|
|
window_sign(int): n period to signal.
|
|
fillna(bool): if True, fill nan values.
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
|
|
indicator = PercentageVolumeOscillator(
|
|
volume=volume,
|
|
window_slow=window_slow,
|
|
window_fast=window_fast,
|
|
window_sign=window_sign,
|
|
fillna=fillna,
|
|
)
|
|
return indicator.pvo()
|
|
|
|
|
|
def pvo_signal(
|
|
volume: pd.Series,
|
|
window_slow: int = 26,
|
|
window_fast: int = 12,
|
|
window_sign: int = 9,
|
|
fillna: bool = False,
|
|
) -> pd.Series:
|
|
"""
|
|
The Percentage Volume Oscillator (PVO) is a momentum oscillator for volume.
|
|
The PVO measures the difference between two volume-based moving averages as a
|
|
percentage of the larger moving average.
|
|
|
|
https://school.stockcharts.com/doku.php?id=technical_indicators:percentage_volume_oscillator_pvo
|
|
|
|
Args:
|
|
volume(pandas.Series): dataset 'Volume' column.
|
|
window_slow(int): n period long-term.
|
|
window_fast(int): n period short-term.
|
|
window_sign(int): n period to signal.
|
|
fillna(bool): if True, fill nan values.
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
|
|
indicator = PercentageVolumeOscillator(
|
|
volume=volume,
|
|
window_slow=window_slow,
|
|
window_fast=window_fast,
|
|
window_sign=window_sign,
|
|
fillna=fillna,
|
|
)
|
|
return indicator.pvo_signal()
|
|
|
|
|
|
def pvo_hist(
|
|
volume: pd.Series,
|
|
window_slow: int = 26,
|
|
window_fast: int = 12,
|
|
window_sign: int = 9,
|
|
fillna: bool = False,
|
|
) -> pd.Series:
|
|
"""
|
|
The Percentage Volume Oscillator (PVO) is a momentum oscillator for volume.
|
|
The PVO measures the difference between two volume-based moving averages as a
|
|
percentage of the larger moving average.
|
|
|
|
https://school.stockcharts.com/doku.php?id=technical_indicators:percentage_volume_oscillator_pvo
|
|
|
|
Args:
|
|
volume(pandas.Series): dataset 'Volume' column.
|
|
window_slow(int): n period long-term.
|
|
window_fast(int): n period short-term.
|
|
window_sign(int): n period to signal.
|
|
fillna(bool): if True, fill nan values.
|
|
Returns:
|
|
pandas.Series: New feature generated.
|
|
"""
|
|
|
|
indicator = PercentageVolumeOscillator(
|
|
volume=volume,
|
|
window_slow=window_slow,
|
|
window_fast=window_fast,
|
|
window_sign=window_sign,
|
|
fillna=fillna,
|
|
)
|
|
return indicator.pvo_hist()
|