momentum refactor

This commit is contained in:
Kevin Johnson
2019-05-20 16:20:47 -07:00
parent 44f2431db4
commit 3fc6ab84ef
27 changed files with 1426 additions and 82 deletions
+55 -55
View File
File diff suppressed because one or more lines are too long
+19
View File
@@ -18,6 +18,25 @@ except DistributionNotFound:
else:
__version__ = _dist.version
# Momentum
from .momentum.ao import ao
from .momentum.apo import apo
from .momentum.bop import bop
from .momentum.cci import cci
from .momentum.cmo import cmo
from .momentum.coppock import coppock
from .momentum.kst import kst
from .momentum.macd import macd
from .momentum.mom import mom
from .momentum.ppo import ppo
from .momentum.roc import roc
from .momentum.rsi import rsi
from .momentum.stoch import stoch
from .momentum.trix import trix
from .momentum.tsi import tsi
from .momentum.uo import uo
from .momentum.willr import willr
# Overlap
from .overlap.dema import dema
from .overlap.ema import ema
+17 -1
View File
@@ -3,7 +3,6 @@ import time
import pandas as pd
from pandas.core.base import PandasObject
from .momentum import *
from .utils import *
class BasePandasObject(PandasObject):
@@ -235,12 +234,14 @@ class AnalysisIndicators(BasePandasObject):
def ao(self, high=None, low=None, fast=None, slow=None, offset=None, **kwargs):
high = self._get_column(high, 'high')
low = self._get_column(low, 'low')
from .momentum.ao import ao
result = ao(high=high, low=low, fast=fast, slow=slow, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def apo(self, close=None, fast=None, slow=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .momentum.apo import apo
result = apo(close=close, fast=fast, slow=slow, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -250,6 +251,7 @@ class AnalysisIndicators(BasePandasObject):
high = self._get_column(high, 'high')
low = self._get_column(low, 'low')
close = self._get_column(close, 'close')
from .momentum.bop import bop
result = bop(open_=open_, high=high, low=low, close=close, percentage=percentage, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -258,54 +260,63 @@ class AnalysisIndicators(BasePandasObject):
high = self._get_column(high, 'high')
low = self._get_column(low, 'low')
close = self._get_column(close, 'close')
from .momentum.cci import cci
result = cci(high=high, low=low, close=close, length=length, c=c, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def cmo(self, close=None, length=None, drift=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .momentum.cmo import cmo
result = cmo(close=close, length=length, drift=drift, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def coppock(self, close=None, length=None, fast=None, slow=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .momentum.coppock import coppock
result = coppock(close=close, length=length, fast=fast, slow=slow, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def kst(self, close=None, roc1=None, roc2=None, roc3=None, roc4=None, sma1=None, sma2=None, sma3=None, sma4=None, signal=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .momentum.kst import kst
result = kst(close=close, roc1=roc1, roc2=roc2, roc3=roc3, roc4=roc4, sma1=sma1, sma2=sma2, sma3=sma3, sma4=sma4, signal=signal, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def macd(self, close=None, fast=None, slow=None, signal=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .momentum.macd import macd
result = macd(close=close, fast=fast, slow=slow, signal=signal, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def mom(self, close=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .momentum.mom import mom
result = mom(close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def ppo(self, close=None, fast=None, slow=None, percentage=True, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .momentum.ppo import ppo
result = ppo(close=close, fast=fast, slow=slow, percentage=percentage, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def roc(self, close=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .momentum.roc import roc
result = roc(close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def rsi(self, close=None, length=None, drift=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .momentum.rsi import rsi
result = rsi(close=close, length=length, drift=drift, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -314,18 +325,21 @@ class AnalysisIndicators(BasePandasObject):
high = self._get_column(high, 'high')
low = self._get_column(low, 'low')
close = self._get_column(close, 'close')
from .momentum.stoch import stoch
result = stoch(high=high, low=low, close=close, fast_k=fast_k, slow_k=slow_k, slow_d=slow_d, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def trix(self, close=None, length=None, drift=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .momentum.trix import trix
result = trix(close=close, length=length, drift=drift, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def tsi(self, close=None, fast=None, slow=None, drift=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .momentum.tsi import tsi
result = tsi(close=close, fast=fast, slow=slow, drift=drift, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -334,6 +348,7 @@ class AnalysisIndicators(BasePandasObject):
high = self._get_column(high, 'high')
low = self._get_column(low, 'low')
close = self._get_column(close, 'close')
from .momentum.uo import uo
result = uo(high=high, low=low, close=close, fast=fast, medium=medium, slow=slow, fast_w=fast_w, medium_w=medium_w, slow_w=slow_w, drift=drift, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -342,6 +357,7 @@ class AnalysisIndicators(BasePandasObject):
high = self._get_column(high, 'high')
low = self._get_column(low, 'low')
close = self._get_column(close, 'close')
from .momentum.willr import willr
result = willr(high=high, low=low, close=close, length=length, percentage=percentage, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
+1
View File
@@ -0,0 +1 @@
# -*- coding: utf-8 -*-
+70
View File
@@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def ao(high, low, fast=None, slow=None, offset=None, **kwargs):
"""Indicator: Awesome Oscillator (AO)"""
# Validate Arguments
high = verify_series(high)
low = verify_series(low)
fast = int(fast) if fast and fast > 0 else 5
slow = int(slow) if slow and slow > 0 else 34
if slow < fast:
fast, slow = slow, fast
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else fast
offset = get_offset(offset)
# Calculate Result
median_price = 0.5 * (high + low)
fast_sma = median_price.rolling(fast, min_periods=min_periods).mean()
slow_sma = median_price.rolling(slow, min_periods=min_periods).mean()
ao = fast_sma - slow_sma
# Offset
if offset != 0:
ao = ao.shift(offset)
# Handle fills
if 'fillna' in kwargs:
ao.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
ao.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
ao.name = f"AO_{fast}_{slow}"
ao.category = 'momentum'
return ao
ao.__doc__ = \
"""Awesome Oscillator (AO)
The Awesome Oscillator is an indicator used to measure a security's momentum.
AO is generally used to affirm trends or to anticipate possible reversals.
Sources:
https://www.tradingview.com/wiki/Awesome_Oscillator_(AO)
https://www.ifcm.co.uk/ntx-indicators/awesome-oscillator
Calculation:
Default Inputs:
fast=5, slow=34
SMA = Simple Moving Average
median = (high + low) / 2
AO = SMA(median, fast) - SMA(median, slow)
Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
fast (int): The short period. Default: 5
slow (int): The long period. Default: 34
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+67
View File
@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
from ..overlap.ema import ema
from ..utils import get_offset, verify_series
def apo(close, fast=None, slow=None, offset=None, **kwargs):
"""Indicator: Absolute Price Oscillator (APO)"""
# Validate Arguments
close = verify_series(close)
fast = int(fast) if fast and fast > 0 else 12
slow = int(slow) if slow and slow > 0 else 26
if slow < fast:
fast, slow = slow, fast
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else fast
offset = get_offset(offset)
# Calculate Result
fastma = ema(close, length=fast, **kwargs)
slowma = ema(close, length=slow, **kwargs)
apo = fastma - slowma
# Offset
if offset != 0:
apo = apo.shift(offset)
# Handle fills
if 'fillna' in kwargs:
apo.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
apo.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
apo.name = f"APO_{fast}_{slow}"
apo.category = 'momentum'
return apo
apo.__doc__ = \
"""Absolute Price Oscillator (APO)
The Absolute Price Oscillator is an indicator used to measure a security's
momentum. It is simply the difference of two Exponential Moving Averages
(EMA) of two different periods. Note: APO and MACD lines are equivalent.
Sources:
https://www.investopedia.com/terms/p/ppo.asp
Calculation:
Default Inputs:
fast=12, slow=26
EMA = Exponential Moving Average
APO = EMA(close, fast) - EMA(close, slow)
Args:
close (pd.Series): Series of 'close's
fast (int): The short period. Default: 12
slow (int): The long period. Default: 26
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+60
View File
@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def bop(open_, high, low, close, offset=None, **kwargs):
"""Indicator: Balance of Power (BOP)"""
# Validate Arguments
open_ = verify_series(open_)
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
offset = get_offset(offset)
# Calculate Result
close_open_range = close - open_
high_low_range = high - low
bop = close_open_range / high_low_range
# Offset
if offset != 0:
bop = bop.shift(offset)
# Handle fills
if 'fillna' in kwargs:
bop.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
bop.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
bop.name = f"BOP"
bop.category = 'momentum'
return bop
bop.__doc__ = \
"""Balance of Power (BOP)
Balance of Power measure the market strength of buyers against sellers.
Sources:
http://www.worden.com/TeleChartHelp/Content/Indicators/Balance_of_Power.htm
Calculation:
BOP = (close - open) / (high - low)
Args:
open (pd.Series): Series of 'open's
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+77
View File
@@ -0,0 +1,77 @@
# -*- coding: utf-8 -*-
from ..overlap.hlc3 import hlc3
from ..overlap.sma import sma
from ..statistics.mad import mad
from ..utils import get_offset, verify_series
def cci(high, low, close, length=None, c=None, offset=None, **kwargs):
"""Indicator: Commodity Channel Index (CCI)"""
# Validate Arguments
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
length = int(length) if length and length > 0 else 20
c = float(c) if c and c > 0 else 0.015
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
offset = get_offset(offset)
# Calculate Result
typical_price = hlc3(high=high, low=low, close=close)
mean_typical_price = sma(typical_price, length=length)
mad_typical_price = mad(typical_price, length=length)
cci = typical_price - mean_typical_price
cci /= c * mad_typical_price
# Offset
if offset != 0:
cci = cci.shift(offset)
# Handle fills
if 'fillna' in kwargs:
cci.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
cci.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
cci.name = f"CCI_{length}_{c}"
cci.category = 'momentum'
return cci
cci.__doc__ = \
"""Commodity Channel Index (CCI)
Commodity Channel Index is a momentum oscillator used to primarily identify
overbought and oversold levels relative to a mean.
Sources:
https://www.tradingview.com/wiki/Commodity_Channel_Index_(CCI)
Calculation:
Default Inputs:
length=20, c=0.015
SMA = Simple Moving Average
MAD = Mean Absolute Deviation
tp = typical_price = hlc3 = (high + low + close) / 3
mean_tp = SMA(tp, length)
mad_tp = MAD(tp, length)
CCI = (tp - mean_tp) / (c * mad_tp)
Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
length (int): It's period. Default: 20
c (float): Scaling Constant. Default: 0.015
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+71
View File
@@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
from ..utils import get_drift, get_offset, verify_series
def cmo(close, length=None, drift=None, offset=None, **kwargs):
"""Indicator: Chande Momentum Oscillator (CMO)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 14
drift = get_drift(drift)
offset = get_offset(offset)
# Calculate Result
negative = close.diff(drift)
positive = negative.copy()
positive[positive < 0] = 0 # Make negatives 0 for the postive series
negative[negative > 0] = 0 # Make postives 0 for the negative series
pos_sum = positive.rolling(length).sum()
neg_sum = negative.abs().rolling(length).sum()
cmo = 100 * (pos_sum - neg_sum) / (pos_sum + neg_sum)
# Offset
if offset != 0:
cmo = cmo.shift(offset)
# Handle fills
if 'fillna' in kwargs:
cmo.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
cmo.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
cmo.name = f"CMO_{length}"
cmo.category = 'momentum'
return cmo
cmo.__doc__ = \
"""Chande Momentum Oscillator (CMO)
Attempts to capture the momentum of an asset with overbought at 50 and
oversold at -50.
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/chande-momentum-oscillator-cmo/
Calculation:
Default Inputs:
drift=1
if close.diff(drift) > 0:
PSUM = SUM(close - prev_close)
else:
NSUM = ABS(SUM(close - prev_close))
CMO = 100 * (PSUM - NSUM) / (PSUM + NSUM)
Args:
close (pd.Series): Series of 'close's
drift (int): The short period. Default: 1
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+74
View File
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
from .roc import roc
from ..overlap.rma import rma
from ..overlap.wma import wma
from ..utils import get_offset, verify_series
def coppock(close, length=None, fast=None, slow=None, offset=None, **kwargs):
"""Indicator: Coppock Curve (COPC)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
fast = int(fast) if fast and fast > 0 else 11
slow = int(slow) if slow and slow > 0 else 14
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
offset = get_offset(offset)
# Calculate Result
total_roc = roc(close, fast) + roc(close, slow)
coppock = wma(total_roc, length)
# Offset
if offset != 0:
coppock = coppock.shift(offset)
# Handle fills
if 'fillna' in kwargs:
coppock.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
coppock.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
coppock.name = f"COPC_{fast}_{slow}_{length}"
coppock.category = 'momentum'
return coppock
coppock.__doc__ = \
"""Coppock Curve (COPC)
Coppock Curve (originally called the "Trendex Model") is a momentum indicator
is designed for use on a monthly time scale. Although designed for monthly
use, a daily calculation over the same period can be made, converting the
periods to 294-day and 231-day rate of changes, and a 210-day weighted
moving average.
Sources:
https://en.wikipedia.org/wiki/Coppock_curve
Calculation:
Default Inputs:
length=10, fast=11, slow=14
SMA = Simple Moving Average
MAD = Mean Absolute Deviation
tp = typical_price = hlc3 = (high + low + close) / 3
mean_tp = SMA(tp, length)
mad_tp = MAD(tp, length)
CCI = (tp - mean_tp) / (c * mad_tp)
Args:
close (pd.Series): Series of 'close's
length (int): WMA period. Default: 10
fast (int): Fast ROC period. Default: 11
slow (int): Slow ROC period. Default: 14
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+104
View File
@@ -0,0 +1,104 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from .roc import roc
from ..utils import get_drift, get_offset, verify_series
def kst(close, roc1=None, roc2=None, roc3=None, roc4=None, sma1=None, sma2=None, sma3=None, sma4=None, signal=None, drift=None, offset=None, **kwargs):
"""Indicator: 'Know Sure Thing'"""
# Validate arguments
close = verify_series(close)
roc1 = int(roc1) if roc1 and roc1 > 0 else 10
roc2 = int(roc2) if roc2 and roc2 > 0 else 15
roc3 = int(roc3) if roc3 and roc3 > 0 else 20
roc4 = int(roc4) if roc4 and roc4 > 0 else 30
sma1 = int(sma1) if sma1 and sma1 > 0 else 10
sma2 = int(sma2) if sma2 and sma2 > 0 else 10
sma3 = int(sma3) if sma3 and sma3 > 0 else 10
sma4 = int(sma4) if sma4 and sma4 > 0 else 15
signal = int(signal) if signal and signal > 0 else 9
drift = get_drift(drift)
offset = get_offset(offset)
# Calculate Result
rocma1 = roc(close, roc1).rolling(sma1).mean()
rocma2 = roc(close, roc2).rolling(sma2).mean()
rocma3 = roc(close, roc3).rolling(sma3).mean()
rocma4 = roc(close, roc4).rolling(sma4).mean()
kst = 100 * (rocma1 + 2 * rocma2 + 3 * rocma3 + 4 * rocma4)
kst_signal = kst.rolling(signal).mean()
# Offset
if offset != 0:
kst = kst.shift(offset)
kst_signal = kst_signal.shift(offset)
# Handle fills
if 'fillna' in kwargs:
kst.fillna(kwargs['fillna'], inplace=True)
kst_signal.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
kst.fillna(method=kwargs['fill_method'], inplace=True)
kst_signal.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
kst.name = f"KST_{roc1}_{roc2}_{roc3}_{roc4}_{sma1}_{sma2}_{sma3}_{sma4}"
kst_signal.name = f"KSTS_{signal}"
kst.category = kst_signal.category = 'momentum'
# Prepare DataFrame to return
data = {kst.name: kst, kst_signal.name: kst_signal}
kstdf = DataFrame(data)
kstdf.name = f"KST_{roc1}_{roc2}_{roc3}_{roc4}_{sma1}_{sma2}_{sma3}_{sma4}_{signal}"
kstdf.category = 'momentum'
return kstdf
kst.__doc__ = \
"""'Know Sure Thing' (KST)
The 'Know Sure Thing' is a momentum based oscillator and based on ROC.
Sources:
https://www.tradingview.com/wiki/Know_Sure_Thing_(KST)
https://www.incrediblecharts.com/indicators/kst.php
Calculation:
Default Inputs:
roc1=10, roc2=15, roc3=20, roc4=30,
sma1=10, sma2=10, sma3=10, sma4=15, signal=9, drift=1
ROC = Rate of Change
SMA = Simple Moving Average
rocsma1 = SMA(ROC(close, roc1), sma1)
rocsma2 = SMA(ROC(close, roc2), sma2)
rocsma3 = SMA(ROC(close, roc3), sma3)
rocsma4 = SMA(ROC(close, roc4), sma4)
KST = 100 * (rocsma1 + 2 * rocsma2 + 3 * rocsma3 + 4 * rocsma4)
KST_Signal = SMA(KST, signal)
Args:
close (pd.Series): Series of 'close's
roc1 (int): ROC 1 period. Default: 10
roc2 (int): ROC 2 period. Default: 15
roc3 (int): ROC 3 period. Default: 20
roc4 (int): ROC 4 period. Default: 30
sma1 (int): SMA 1 period. Default: 10
sma2 (int): SMA 2 period. Default: 10
sma3 (int): SMA 3 period. Default: 10
sma4 (int): SMA 4 period. Default: 15
signal (int): It's period. Default: 9
drift (int): The difference period. Default: 1
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.DataFrame: kst and kst_signal columns
"""
+90
View File
@@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from ..overlap.ema import ema
from ..utils import get_offset, verify_series
def macd(close, fast=None, slow=None, signal=None, offset=None, **kwargs):
"""Indicator: Moving Average, Convergence/Divergence (MACD)"""
# Validate arguments
close = verify_series(close)
fast = int(fast) if fast and fast > 0 else 12
slow = int(slow) if slow and slow > 0 else 26
signal = int(signal) if signal and signal > 0 else 9
if slow < fast:
fast, slow = slow, fast
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else fast
offset = get_offset(offset)
# Calculate Result
fastma = ema(close, length=fast, **kwargs)
slowma = ema(close, length=slow, **kwargs)
macd = fastma - slowma
signalma = ema(close=macd, length=signal, **kwargs)
histogram = macd - signalma
# Offset
if offset != 0:
macd = macd.shift(offset)
histogram = histogram.shift(offset)
signalma = signalma.shift(offset)
# Handle fills
if 'fillna' in kwargs:
macd.fillna(kwargs['fillna'], inplace=True)
histogram.fillna(kwargs['fillna'], inplace=True)
signalma.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
macd.fillna(method=kwargs['fill_method'], inplace=True)
histogram.fillna(method=kwargs['fill_method'], inplace=True)
signalma.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
macd.name = f"MACD_{fast}_{slow}_{signal}"
histogram.name = f"MACDH_{fast}_{slow}_{signal}"
signalma.name = f"MACDS_{fast}_{slow}_{signal}"
macd.category = histogram.category = signalma.category = 'momentum'
# Prepare DataFrame to return
data = {macd.name: macd, histogram.name: histogram, signalma.name: signalma}
macddf = DataFrame(data)
macddf.name = f"MACD_{fast}_{slow}_{signal}"
macddf.category = 'momentum'
return macddf
macd.__doc__ = \
"""Moving Average Convergence Divergence (MACD)
The MACD is a popular indicator to that is used to identify a security's trend.
While APO and MACD are the same calculation, MACD also returns two more series
called Signal and Histogram. The Signal is an EMA of MACD and the Histogram is
the difference of MACD and Signal.
Sources:
https://www.tradingview.com/wiki/MACD_(Moving_Average_Convergence/Divergence)
Calculation:
Default Inputs:
fast=12, slow=26, signal=9
EMA = Exponential Moving Average
MACD = EMA(close, fast) - EMA(close, slow)
Signal = EMA(MACD, signal)
Histogram = MACD - Signal
Args:
close (pd.Series): Series of 'close's
fast (int): The short period. Default: 12
slow (int): The long period. Default: 26
signal (int): The signal period. Default: 9
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.DataFrame: macd, histogram, signal columns.
"""
+57
View File
@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def mom(close, length=None, offset=None, **kwargs):
"""Indicator: Momentum (MOM)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
offset = get_offset(offset)
# Calculate Result
mom = close.diff(length)
# Offset
if offset != 0:
mom = mom.shift(offset)
# Handle fills
if 'fillna' in kwargs:
mom.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
mom.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
mom.name = f"MOM_{length}"
mom.category = 'momentum'
return mom
mom.__doc__ = \
"""Momentum (MOM)
Momentum is an indicator used to measure a security's speed (or strength) of
movement. Or simply the change in price.
Sources:
http://www.onlinetradingconcepts.com/TechnicalAnalysis/Momentum.html
Calculation:
Default Inputs:
length=1
MOM = close.diff(length)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 1
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+90
View File
@@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from ..overlap.ema import ema
from ..utils import get_offset, verify_series
def ppo(close, fast=None, slow=None, signal=None, offset=None, **kwargs):
"""Indicator: Percentage Price Oscillator (PPO)"""
# Validate Arguments
close = verify_series(close)
fast = int(fast) if fast and fast > 0 else 12
slow = int(slow) if slow and slow > 0 else 26
signal = int(signal) if signal and signal > 0 else 9
if slow < fast:
fast, slow = slow, fast
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else fast
offset = get_offset(offset)
# Calculate Result
fastma = close.rolling(fast, min_periods=min_periods).mean()
slowma = close.rolling(slow, min_periods=min_periods).mean()
ppo = 100 * (fastma - slowma) / slowma
signalma = ema(close=ppo, length=signal, **kwargs)
histogram = ppo - signalma
# Offset
if offset != 0:
ppo = ppo.shift(offset)
signalma = signalma.shift(offset)
histogram = histogram.shift(offset)
# Handle fills
if 'fillna' in kwargs:
ppo.fillna(kwargs['fillna'], inplace=True)
histogram.fillna(kwargs['fillna'], inplace=True)
signalma.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
ppo.fillna(method=kwargs['fill_method'], inplace=True)
histogram.fillna(method=kwargs['fill_method'], inplace=True)
signalma.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
ppo.name = f"PPO_{fast}_{slow}_{signal}"
histogram.name = f"PPOH_{fast}_{slow}_{signal}"
signalma.name = f"PPOS_{fast}_{slow}_{signal}"
ppo.category = histogram.category = signalma.category = 'momentum'
# Prepare DataFrame to return
data = {ppo.name: ppo, histogram.name: histogram, signalma.name: signalma}
ppodf = DataFrame(data)
ppodf.name = f"PPO_{fast}_{slow}_{signal}"
ppodf.category = 'momentum'
return ppodf
ppo.__doc__ = \
"""Percentage Price Oscillator (PPO)
The Percentage Price Oscillator is similar to MACD in measuring momentum.
Sources:
https://www.tradingview.com/wiki/MACD_(Moving_Average_Convergence/Divergence)
Calculation:
Default Inputs:
fast=12, slow=26
SMA = Simple Moving Average
EMA = Exponential Moving Average
fast_sma = SMA(close, fast)
slow_sma = SMA(close, slow)
PPO = 100 * (fast_sma - slow_sma) / slow_sma
Signal = EMA(PPO, signal)
Histogram = PPO - Signal
Args:
close(pandas.Series): Series of 'close's
fast(int): The short period. Default: 12
slow(int): The long period. Default: 26
signal(int): The signal period. Default: 9
offset(int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.DataFrame: ppo, histogram, signal columns
"""
+61
View File
@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
from .mom import mom
from ..utils import get_offset, verify_series
def roc(close, length=None, offset=None, **kwargs):
"""Indicator: Rate of Change (ROC)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
offset = get_offset(offset)
# Calculate Result
roc = 100 * mom(close=close, length=length) / close.shift(length)
# Offset
if offset != 0:
roc = roc.shift(offset)
# Handle fills
if 'fillna' in kwargs:
roc.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
roc.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
roc.name = f"ROC_{length}"
roc.category = 'momentum'
return roc
roc.__doc__ = \
"""Rate of Change (ROC)
Rate of Change is an indicator is also referred to as Momentum (yeah, confusingly).
It is a pure momentum oscillator that measures the percent change in price with the
previous price 'n' (or length) periods ago.
Sources:
https://www.tradingview.com/wiki/Rate_of_Change_(ROC)
Calculation:
Default Inputs:
length=1
MOM = Momentum
ROC = 100 * MOM(close, length) / close.shift(length)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 1
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+74
View File
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
from ..utils import get_drift, get_offset, verify_series
def rsi(close, length=None, drift=None, offset=None, **kwargs):
"""Indicator: Relative Strength Index (RSI)"""
# Validate arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 14
drift = get_drift(drift)
offset = get_offset(offset)
# Calculate Result
negative = close.diff(drift)
positive = negative.copy()
positive[positive < 0] = 0 # Make negatives 0 for the postive series
negative[negative > 0] = 0 # Make postives 0 for the negative series
positive_avg = positive.ewm(com=length, adjust=False).mean()
negative_avg = negative.ewm(com=length, adjust=False).mean().abs()
rsi = 100 * positive_avg / (positive_avg + negative_avg)
# Offset
if offset != 0:
rsi = rsi.shift(offset)
# Handle fills
if 'fillna' in kwargs:
rsi.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
rsi.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
rsi.name = f"RSI_{length}"
rsi.category = 'momentum'
return rsi
rsi.__doc__ = \
"""Relative Strength Index (RSI)
The Relative Strength Index is popular momentum oscillator used to measure the
velocity as well as the magnitude of directional price movements.
Sources:
https://www.tradingview.com/wiki/Relative_Strength_Index_(RSI)
Calculation:
Default Inputs:
length=14, drift=1
ABS = Absolute Value
EMA = Exponential Moving Average
positive = close if close.diff(drift) > 0 else 0
negative = close if close.diff(drift) < 0 else 0
pos_avg = EMA(positive, length)
neg_avg = ABS(EMA(negative, length))
RSI = 100 * pos_avg / (pos_avg + neg_avg)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 1
drift (int): The difference period. Default: 1
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+100
View File
@@ -0,0 +1,100 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from ..overlap.sma import sma
from ..utils import get_offset, verify_series
def stoch(high, low, close, fast_k=None, slow_k=None, slow_d=None, offset=None, **kwargs):
"""Indicator: Stochastic Oscillator (STOCH)"""
# Validate arguments
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
fast_k = fast_k if fast_k and fast_k > 0 else 14
slow_k = slow_k if slow_k and slow_k > 0 else 5
slow_d = slow_d if slow_d and slow_d > 0 else 3
offset = get_offset(offset)
# Calculate Result
lowest_low = low.rolling(slow_k).min()
highest_high = high.rolling(slow_k).max()
fastk = 100 * (close - lowest_low) / (highest_high - lowest_low)
fastd = sma(fastk, length=slow_d)
slowk = sma(fastk, length=slow_k)
slowd = sma(slowk, length=slow_d)
# Offset
if offset != 0:
fastk = fastk.shift(offset)
fastd = fastd.shift(offset)
slowk = slowk.shift(offset)
slowd = slowd.shift(offset)
# Handle fills
if 'fillna' in kwargs:
fastk.fillna(kwargs['fillna'], inplace=True)
fastd.fillna(kwargs['fillna'], inplace=True)
slowk.fillna(kwargs['fillna'], inplace=True)
slowd.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
fastk.fillna(method=kwargs['fill_method'], inplace=True)
fastd.fillna(method=kwargs['fill_method'], inplace=True)
slowk.fillna(method=kwargs['fill_method'], inplace=True)
slowd.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
fastk.name = f"STOCHF_{fast_k}"
fastd.name = f"STOCHF_{slow_d}"
slowk.name = f"STOCH_{slow_k}"
slowd.name = f"STOCH_{slow_d}"
fastk.category = fastd.category = slowk.category = slowd.category = 'momentum'
# Prepare DataFrame to return
data = {fastk.name: fastk, fastd.name: fastd, slowk.name: slowk, slowd.name: slowd}
stochdf = DataFrame(data)
stochdf.name = f"STOCH_{fast_k}_{slow_k}_{slow_d}"
stochdf.category = 'momentum'
return stochdf
stoch.__doc__ = \
"""Stochastic (STOCH)
Stochastic Oscillator is a range bound momentum indicator. It displays the location
of the close relative to the high-low range over a period.
Sources:
https://www.tradingview.com/wiki/Stochastic_(STOCH)
Calculation:
Default Inputs:
fast_k=14, slow_k=5, slow_d=3
SMA = Simple Moving Average
lowest_low = low for last fast_k periods
highest_high = high for last fast_k periods
FASTK = 100 * (close - lowest_low) / (highest_high - lowest_low)
FASTD = SMA(FASTK, slow_d)
SLOWK = SMA(FASTK, slow_k)
SLOWD = SMA(SLOWK, slow_d)
Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
fast_k (int): The Fast %K period. Default: 14
slow_k (int): The Slow %K period. Default: 5
slow_d (int): The Slow %D period. Default: 3
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.DataFrame: fastk, fastd, slowk, slowd columns.
"""
+62
View File
@@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
from ..overlap.ema import ema
from ..utils import get_drift, get_offset, verify_series
def trix(close, length=None, drift=None, offset=None, **kwargs):
"""Indicator: Trix (TRIX)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 30
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
drift = get_drift(drift)
offset = get_offset(offset)
# Calculate Result
ema1 = ema(close=close, length=length, **kwargs)
ema2 = ema(close=ema1, length=length, **kwargs)
ema3 = ema(close=ema2, length=length, **kwargs)
trix = 100 * ema3.pct_change(drift)
# Offset
if offset != 0:
trix = trix.shift(offset)
# Name & Category
trix.name = f"TRIX_{length}"
trix.category = 'momentum'
return trix
trix.__doc__ = \
"""Trix (TRIX)
TRIX is a momentum oscillator to identify divergences.
Sources:
https://www.tradingview.com/wiki/TRIX
Calculation:
Default Inputs:
length=18, drift=1
EMA = Exponential Moving Average
ROC = Rate of Change
ema1 = EMA(close, length)
ema2 = EMA(ema1, length)
ema3 = EMA(ema2, length)
TRIX = 100 * ROC(ema3, drift)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 18
drift (int): The difference period. Default: 1
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+82
View File
@@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
from ..overlap.ema import ema
from ..utils import get_drift, get_offset, verify_series
def tsi(close, fast=None, slow=None, drift=None, offset=None, **kwargs):
"""Indicator: True Strength Index (TSI)"""
# Validate Arguments
close = verify_series(close)
fast = int(fast) if fast and fast > 0 else 13
slow = int(slow) if slow and slow > 0 else 25
if slow < fast:
fast, slow = slow, fast
drift = get_drift(drift)
offset = get_offset(offset)
# Calculate Result
diff = close.diff(drift)
slow_ema = ema(close=diff, length=slow, **kwargs)
fast_slow_ema = ema(close=slow_ema, length=fast, **kwargs)
abs_diff = diff.abs()
abs_slow_ema = ema(close=abs_diff, length=slow, **kwargs)
abs_fast_slow_ema = ema(close=abs_slow_ema, length=fast, **kwargs)
tsi = 100 * fast_slow_ema / abs_fast_slow_ema
# Offset
if offset != 0:
tsi = tsi.shift(offset)
# Handle fills
if 'fillna' in kwargs:
tsi.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
tsi.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
tsi.name = f"TSI_{fast}_{slow}"
tsi.category = 'momentum'
return tsi
tsi.__doc__ = \
"""True Strength Index (TSI)
The True Strength Index is a momentum indicator used to identify short-term
swings while in the direction of the trend as well as determining overbought
and oversold conditions.
Sources:
https://www.investopedia.com/terms/t/tsi.asp
Calculation:
Default Inputs:
fast=13, slow=25, drift=1
EMA = Exponential Moving Average
diff = close.diff(drift)
slow_ema = EMA(diff, slow)
fast_slow_ema = EMA(slow_ema, slow)
abs_diff_slow_ema = absolute_diff_ema = EMA(ABS(diff), slow)
abema = abs_diff_fast_slow_ema = EMA(abs_diff_slow_ema, fast)
TSI = 100 * fast_slow_ema / abema
Args:
close (pd.Series): Series of 'close's
fast (int): The short period. Default: 13
slow (int): The long period. Default: 25
drift (int): The difference period. Default: 1
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+104
View File
@@ -0,0 +1,104 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from ..utils import get_drift, get_offset, verify_series
def uo(high, low, close, fast=None, medium=None, slow=None, fast_w=None, medium_w=None, slow_w=None, drift=None, offset=None, **kwargs):
"""Indicator: Ultimate Oscillator (UO)"""
# Validate arguments
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
drift = get_drift(drift)
offset = get_offset(offset)
fast = int(fast) if fast and fast > 0 else 7
fast_w = float(fast_w) if fast_w and fast_w > 0 else 4.0
medium = int(medium) if medium and medium > 0 else 14
medium_w = float(medium_w) if medium_w and medium_w > 0 else 2.0
slow = int(slow) if slow and slow > 0 else 28
slow_w = float(slow_w) if slow_w and slow_w > 0 else 1.0
# Calculate Result
tdf = DataFrame({'high': high, 'low': low, f"close_{drift}": close.shift(drift)})
max_h_or_pc = tdf.loc[:, ['high', f"close_{drift}"]].max(axis=1)
min_l_or_pc = tdf.loc[:, ['low', f"close_{drift}"]].min(axis=1)
del tdf
bp = close - min_l_or_pc
tr = max_h_or_pc - min_l_or_pc
fast_avg = bp.rolling(fast).sum() / tr.rolling(fast).sum()
medium_avg = bp.rolling(medium).sum() / tr.rolling(medium).sum()
slow_avg = bp.rolling(slow).sum() / tr.rolling(slow).sum()
total_weight = fast_w + medium_w + slow_w
weights = (fast_w * fast_avg) + (medium_w * medium_avg) + (slow_w * slow_avg)
uo = 100 * weights / total_weight
# Offset
if offset != 0:
uo = uo.shift(offset)
# Handle fills
if 'fillna' in kwargs:
uo.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
uo.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
uo.name = f"UO_{fast}_{medium}_{slow}"
uo.category = 'momentum'
return uo
uo.__doc__ = \
"""Ultimate Oscillator (UO)
The Ultimate Oscillator is a momentum indicator over three different
periods. It attempts to correct false divergence trading signals.
Sources:
https://www.tradingview.com/wiki/Ultimate_Oscillator_(UO)
Calculation:
Default Inputs:
fast=7, medium=14, slow=28,
fast_w=4.0, medium_w=2.0, slow_w=1.0, drift=1
min_low_or_pc = close.shift(drift).combine(low, min)
max_high_or_pc = close.shift(drift).combine(high, max)
bp = buying pressure = close - min_low_or_pc
tr = true range = max_high_or_pc - min_low_or_pc
fast_avg = SUM(bp, fast) / SUM(tr, fast)
medium_avg = SUM(bp, medium) / SUM(tr, medium)
slow_avg = SUM(bp, slow) / SUM(tr, slow)
total_weight = fast_w + medium_w + slow_w
weights = (fast_w * fast_avg) + (medium_w * medium_avg) + (slow_w * slow_avg)
UO = 100 * weights / total_weight
Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
fast (int): The Fast %K period. Default: 7
medium (int): The Slow %K period. Default: 14
slow (int): The Slow %D period. Default: 28
fast_w (float): The Fast %K period. Default: 4.0
medium_w (float): The Slow %K period. Default: 2.0
slow_w (float): The Slow %D period. Default: 1.0
drift (int): The difference period. Default: 1
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+68
View File
@@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
from ..utils import get_drift, get_offset, verify_series
def willr(high, low, close, length=None, offset=None, **kwargs):
"""Indicator: William's Percent R (WILLR)"""
# Validate arguments
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
length = int(length) if length and length > 0 else 14
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
offset = get_offset(offset)
# Calculate Result
lowest_low = low.rolling(length, min_periods=min_periods).min()
highest_high = high.rolling(length, min_periods=min_periods).max()
willr = 100 * ((close - lowest_low) / (highest_high - lowest_low) - 1)
# Offset
if offset != 0:
willr = willr.shift(offset)
# Handle fills
if 'fillna' in kwargs:
willr.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
willr.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
willr.name = f"WILLR_{length}"
willr.category = 'momentum'
return willr
willr.__doc__ = \
"""William's Percent R (WILLR)
William's Percent R is a momentum oscillator similar to the RSI that
attempts to identify overbought and oversold conditions.
Sources:
https://www.tradingview.com/wiki/Williams_%25R_(%25R)
Calculation:
Default Inputs:
length=20
lowest_low = low.rolling(length).min()
highest_high = high.rolling(length).max()
WILLR = 100 * ((close - lowest_low) / (highest_high - lowest_low) - 1)
Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
length (int): It's period. Default: 14
offset (int): How many periods to offset the result. Default: 0
Kwargs:
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+1 -1
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from ..momentum import roc
from ..momentum.roc import roc
from ..utils import get_offset, signed_series, verify_series
def nvi(close, volume, length=None, initial=None, offset=None, **kwargs):
+1 -1
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from ..momentum import roc
from ..momentum.roc import roc
from ..utils import get_offset, signed_series, verify_series
def pvi(close, volume, length=None, initial=None, offset=None, **kwargs):
+1 -1
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from ..momentum import roc
from ..momentum.roc import roc
from ..utils import get_drift, get_offset, verify_series
def pvt(close, volume, drift=None, offset=None, **kwargs):
+1 -1
View File
@@ -6,7 +6,7 @@ long_description = "An easy to use Python 3 Pandas Extension of Technical Analys
setup(
name = "pandas_ta",
packages = ["pandas_ta"],
version = "0.1.24b",
version = "0.1.25b",
description=long_description,
long_description=long_description,
author = "Kevin Johnson",
+19 -22
View File
@@ -30,20 +30,17 @@ class TestMomentum(TestCase):
del cls.data
def setUp(self):
self.momentum = pandas_ta.momentum
def tearDown(self):
del self.momentum
def setUp(self): pass
def tearDown(self): pass
def test_ao(self):
result = self.momentum.ao(self.high, self.low)
result = pandas_ta.ao(self.high, self.low)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'AO_5_34')
def test_apo(self):
result = self.momentum.apo(self.close)
result = pandas_ta.apo(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'APO_12_26')
@@ -58,7 +55,7 @@ class TestMomentum(TestCase):
error_analysis(result, CORRELATION, ex)
def test_bop(self):
result = self.momentum.bop(self.open, self.high, self.low, self.close)
result = pandas_ta.bop(self.open, self.high, self.low, self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'BOP')
@@ -73,7 +70,7 @@ class TestMomentum(TestCase):
error_analysis(result, CORRELATION, ex)
def test_cci(self):
result = self.momentum.cci(self.high, self.low, self.close)
result = pandas_ta.cci(self.high, self.low, self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'CCI_20_0.015')
@@ -88,7 +85,7 @@ class TestMomentum(TestCase):
error_analysis(result, CORRELATION, ex)
def test_cmo(self):
result = self.momentum.cmo(self.close)
result = pandas_ta.cmo(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'CMO_14')
@@ -103,17 +100,17 @@ class TestMomentum(TestCase):
error_analysis(result, CORRELATION, ex)
def test_coppock(self):
result = self.momentum.coppock(self.close)
result = pandas_ta.coppock(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'COPC_11_14_10')
def test_kst(self):
result = self.momentum.kst(self.close)
result = pandas_ta.kst(self.close)
self.assertIsInstance(result, DataFrame)
self.assertEqual(result.name, 'KST_10_15_20_30_10_10_10_15_9')
def test_macd(self):
result = self.momentum.macd(self.close)
result = pandas_ta.macd(self.close)
self.assertIsInstance(result, DataFrame)
self.assertEqual(result.name, 'MACD_12_26_9')
@@ -141,7 +138,7 @@ class TestMomentum(TestCase):
error_analysis(result.iloc[:,2], CORRELATION, ex, newline=False)
def test_mom(self):
result = self.momentum.mom(self.close)
result = pandas_ta.mom(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'MOM_10')
@@ -156,7 +153,7 @@ class TestMomentum(TestCase):
error_analysis(result, CORRELATION, ex)
def test_ppo(self):
result = self.momentum.ppo(self.close)
result = pandas_ta.ppo(self.close)
self.assertIsInstance(result, DataFrame)
self.assertEqual(result.name, 'PPO_12_26_9')
@@ -171,7 +168,7 @@ class TestMomentum(TestCase):
error_analysis(result['PPO_12_26_9'], CORRELATION, ex)
def test_roc(self):
result = self.momentum.roc(self.close)
result = pandas_ta.roc(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'ROC_10')
@@ -186,7 +183,7 @@ class TestMomentum(TestCase):
error_analysis(result, CORRELATION, ex)
def test_rsi(self):
result = self.momentum.rsi(self.close)
result = pandas_ta.rsi(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'RSI_14')
@@ -201,7 +198,7 @@ class TestMomentum(TestCase):
error_analysis(result, CORRELATION, ex)
def test_stoch(self):
result = self.momentum.stoch(self.high, self.low, self.close)
result = pandas_ta.stoch(self.high, self.low, self.close)
self.assertIsInstance(result, DataFrame)
self.assertEqual(result.name, 'STOCH_14_5_3')
@@ -236,17 +233,17 @@ class TestMomentum(TestCase):
error_analysis(result.iloc[:,3], CORRELATION, ex, newline=False)
def test_trix(self):
result = self.momentum.trix(self.close)
result = pandas_ta.trix(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'TRIX_30')
def test_tsi(self):
result = self.momentum.tsi(self.close)
result = pandas_ta.tsi(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'TSI_13_25')
def test_uo(self):
result = self.momentum.uo(self.high, self.low, self.close)
result = pandas_ta.uo(self.high, self.low, self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'UO_7_14_28')
@@ -261,7 +258,7 @@ class TestMomentum(TestCase):
error_analysis(result, CORRELATION, ex)
def test_willr(self):
result = self.momentum.willr(self.high, self.low, self.close)
result = pandas_ta.willr(self.high, self.low, self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'WILLR_14')