trend refactoring

This commit is contained in:
Kevin Johnson
2019-05-20 09:08:51 -07:00
parent 8c88e51b5c
commit 38ea426eb4
18 changed files with 744 additions and 704 deletions
+1 -3
View File
@@ -134,8 +134,6 @@ pandas_pips
reqs.txt
requirements.txt
qd.py
_performance.py
_trend.py
_statistics.py
_volatility.py
_volume.py
simple.ipynb
+12
View File
@@ -33,6 +33,18 @@ from .statistics.stdev import stdev
from .statistics.variance import variance
from .statistics.zscore import zscore
# Trend
from .trend.adx import adx
from .trend.amat import amat
from .trend.aroon import aroon
from .trend.decreasing import decreasing
from .trend.dpo import dpo
from .trend.increasing import increasing
from .trend.long_run import long_run
from .trend.qstick import qstick
from .trend.short_run import short_run
from .trend.vortex import vortex
# Volatility
from .volatility.accbands import accbands
from .volatility.atr import atr
+10 -1
View File
@@ -5,7 +5,6 @@ from pandas.core.base import PandasObject
from .momentum import *
from .overlap import *
from .trend import *
from .utils import *
class BasePandasObject(PandasObject):
@@ -584,36 +583,42 @@ class AnalysisIndicators(BasePandasObject):
high = self._get_column(high, 'high')
low = self._get_column(low, 'low')
close = self._get_column(close, 'close')
from .trend.adx import adx
result = adx(high=high, low=low, close=close, drift=drift, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def amat(self, close=None, fast=None, slow=None, mamode=None, lookback=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .trend.amat import amat
result = amat(close=close, fast=fast, slow=slow, mamode=mamode, lookback=lookback, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def aroon(self, close=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .trend.aroon import aroon
result = aroon(close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def decreasing(self, close=None, length=None, asint=True, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .trend.decreasing import decreasing
result = decreasing(close=close, length=length, asint=asint, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def dpo(self, close=None, length=None, centered=True, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .trend.dpo import dpo
result = dpo(close=close, length=length, centered=centered, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def increasing(self, close=None, length=None, asint=True, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .trend.increasing import increasing
result = increasing(close=close, length=length, asint=asint, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -623,6 +628,7 @@ class AnalysisIndicators(BasePandasObject):
else:
fast = self._get_column(fast, f"{fast}")
slow = self._get_column(slow, f"{slow}")
from .trend.long_run import long_run
result = long_run(fast=fast, slow=slow, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -630,6 +636,7 @@ class AnalysisIndicators(BasePandasObject):
def qstick(self, open_=None, close=None, length=None, offset=None, **kwargs):
open_ = self._get_column(open_, 'open')
close = self._get_column(close, 'close')
from .trend.qstick import qstick
result = qstick(open_=open_, close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -639,6 +646,7 @@ class AnalysisIndicators(BasePandasObject):
else:
fast = self._get_column(fast, f"{fast}")
slow = self._get_column(slow, f"{slow}")
from .trend.short_run import short_run
result = short_run(fast=fast, slow=slow, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -647,6 +655,7 @@ class AnalysisIndicators(BasePandasObject):
high = self._get_column(high, 'high')
low = self._get_column(low, 'low')
close = self._get_column(close, 'close')
from .trend.vortex import vortex
result = vortex(high=high, low=low, close=close, drift=drift, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
-683
View File
@@ -1,683 +0,0 @@
# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
from .momentum import roc
from .overlap import dema, ema, hma, midprice, rma, sma
from .utils import get_drift, get_offset, verify_series, zero
from .volatility.true_range import true_range
from .volatility.atr import atr
def adx(high, low, close, length=None, drift=None, offset=None, **kwargs):
"""Indicator: ADX"""
# Validate Arguments
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
length = length if length and length > 0 else 14
drift = get_drift(drift)
offset = get_offset(offset)
# Calculate Result
_atr = atr(high=high, low=low, close=close, length=length)
up = high - high.shift(drift)
dn = low.shift(drift) - low
pos = ((up > dn) & (up > 0)) * up
neg = ((dn > up) & (dn > 0)) * dn
pos = pos.apply(zero)
neg = neg.apply(zero)
dmp = (100 / _atr) * rma(close=pos, length=length)
dmn = (100 / _atr) * rma(close=neg, length=length)
dx = 100 * (dmp - dmn).abs() / (dmp + dmn)
adx = rma(close=dx, length=length)
# Offset
if offset != 0:
dmp = dmp.shift(offset)
dmn = dmn.shift(offset)
adx = adx.shift(offset)
# Handle fills
if 'fillna' in kwargs:
adx.fillna(kwargs['fillna'], inplace=True)
dmp.fillna(kwargs['fillna'], inplace=True)
dmn.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
adx.fillna(method=kwargs['fill_method'], inplace=True)
dmp.fillna(method=kwargs['fill_method'], inplace=True)
dmn.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
adx.name = f"ADX_{length}"
dmp.name = f"DMP_{length}"
dmn.name = f"DMN_{length}"
adx.category = dmp.category = dmn.category = 'trend'
# Prepare DataFrame to return
data = {adx.name: adx, dmp.name: dmp, dmn.name: dmn}
adxdf = pd.DataFrame(data)
adxdf.name = f"ADX_{length}"
adxdf.category = 'trend'
return adxdf
def amat(close=None, fast=None, slow=None, mamode=None, lookback=None, offset=None, **kwargs):
"""Indicator: Archer Moving Averages Trends (AMAT)"""
# Validate Arguments
close = verify_series(close)
fast = int(fast) if fast and fast > 0 else 8
slow = int(slow) if slow and slow > 0 else 21
lookback = int(lookback) if lookback and lookback > 0 else 2
mamode = mamode.upper() if mamode else 'EMA'
offset = get_offset(offset)
# Calculate Result
if mamode == 'EMA':
fast_ma = ema(close=close, length=fast, **kwargs)
slow_ma = ema(close=close, length=slow, **kwargs)
elif mamode == 'HMA':
fast_ma = hma(close=close, length=fast, **kwargs)
slow_ma = hma(close=close, length=slow, **kwargs)
elif mamode == 'LINREG':
fast_ma = linreg(close=close, length=fast, **kwargs)
slow_ma = linreg(close=close, length=slow, **kwargs)
elif mamode == 'RMA':
fast_ma = rma(close=close, length=fast, **kwargs)
slow_ma = rma(close=close, length=slow, **kwargs)
elif mamode == 'SMA':
fast_ma = sma(close=close, length=fast, **kwargs)
slow_ma = sma(close=close, length=slow, **kwargs)
elif mamode == 'WMA':
fast_ma = wma(close=close, length=fast, **kwargs)
slow_ma = wma(close=close, length=slow, **kwargs)
mas_long = long_run(fast_ma, slow_ma, length=lookback)
mas_short = short_run(fast_ma, slow_ma, length=lookback)
# Offset
if offset != 0:
mas_long = mas_long.shift(offset)
mas_short = mas_short.shift(offset)
# # Handle fills
if 'fillna' in kwargs:
mas_long.fillna(kwargs['fillna'], inplace=True)
mas_short.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
mas_long.fillna(method=kwargs['fill_method'], inplace=True)
mas_short.fillna(method=kwargs['fill_method'], inplace=True)
# Prepare DataFrame to return
amatdf = pd.DataFrame({
f"AMAT_{mas_long.name}": mas_long,
f"AMAT_{mas_short.name}": mas_short
})
# Name and Categorize it
amatdf.name = f"AMAT_{mamode}_{fast}_{slow}_{lookback}"
amatdf.category = 'trend'
return amatdf
def aroon(close, length=None, offset=None, **kwargs):
"""Indicator: Aroon Oscillator"""
# Validate Arguments
close = verify_series(close)
length = 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
def maxidx(x):
return 100 * (int(np.argmax(x)) + 1) / length
def minidx(x):
return 100 * (int(np.argmin(x)) + 1) / length
_close = close.rolling(length, min_periods=min_periods)
aroon_up = _close.apply(maxidx, raw=True)
aroon_down = _close.apply(minidx, raw=True)
# Handle fills
if 'fillna' in kwargs:
aroon_up.fillna(kwargs['fillna'], inplace=True)
aroon_down.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
aroon_up.fillna(method=kwargs['fill_method'], inplace=True)
aroon_down.fillna(method=kwargs['fill_method'], inplace=True)
# Offset
if offset != 0:
aroon_up = aroon_up.shift(offset)
aroon_down = aroon_down.shift(offset)
# Name and Categorize it
aroon_up.name = f"AROONU_{length}"
aroon_down.name = f"AROOND_{length}"
aroon_down.category = aroon_up.category = 'trend'
# Prepare DataFrame to return
data = {aroon_down.name: aroon_down, aroon_up.name: aroon_up}
aroondf = pd.DataFrame(data)
aroondf.name = f"AROON_{length}"
aroondf.category = 'trend'
return aroondf
def decreasing(close, length=None, asint=True, offset=None, **kwargs):
"""Indicator: Decreasing"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 1
offset = get_offset(offset)
# Calculate Result
decreasing = close.diff(length) < 0
if asint:
decreasing = decreasing.astype(int)
# Offset
if offset != 0:
decreasing = decreasing.shift(offset)
# Handle fills
if 'fillna' in kwargs:
decreasing.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
decreasing.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
decreasing.name = f"DEC_{length}"
decreasing.category = 'trend'
return decreasing
def dpo(close, length=None, centered=True, offset=None, **kwargs):
"""Indicator: Detrend Price Oscillator (DPO)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 1
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
drift = int(0.5 * length) + 1 # int((0.5 * length) + 1)
dpo = close.shift(drift) - close.rolling(length, min_periods=min_periods).mean()
if centered:
dpo = dpo.shift(-drift)
# Offset
if offset != 0:
dpo = dpo.shift(offset)
# Handle fills
if 'fillna' in kwargs:
dpo.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
dpo.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
dpo.name = f"DPO_{length}"
dpo.category = 'trend'
return dpo
def increasing(close, length=None, asint=True, offset=None, **kwargs):
"""Indicator: Increasing"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 1
offset = get_offset(offset)
# Calculate Result
increasing = close.diff(length) > 0
if asint:
increasing = increasing.astype(int)
# Offset
if offset != 0:
increasing = increasing.shift(offset)
# Handle fills
if 'fillna' in kwargs:
increasing.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
increasing.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
increasing.name = f"INC_{length}"
increasing.category = 'trend'
return increasing
def long_run(fast, slow, length=None, offset=None, **kwargs):
"""Indicator: Long Run"""
# Validate Arguments
fast = verify_series(fast)
slow = verify_series(slow)
length = int(length) if length and length > 0 else 2
offset = get_offset(offset)
# Calculate Result
pb = increasing(fast, length) & decreasing(slow, length) # potential bottom or bottom
bi = increasing(fast, length) & increasing(slow, length) # fast and slow are increasing
long_run = pb | bi
# Offset
if offset != 0:
long_run = long_run.shift(offset)
# Handle fills
if 'fillna' in kwargs:
long_run.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
long_run.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
long_run.name = f"LR_{length}"
long_run.category = 'trend'
return long_run
def qstick(open_, close, length=None, offset=None, **kwargs):
"""Indicator: Q Stick"""
# Validate Arguments
open_ = verify_series(open_)
close = verify_series(close)
length = int(length) if length and length > 0 else 10
offset = get_offset(offset)
ma = kwargs.pop('ma', 'sma') if 'ma' in kwargs else 'sma'
# Calculate Result
diff = close - open_
if ma in [None, 'sma']: qstick = sma(diff, length=length)
if ma == 'dema': qstick = dema(diff, length=length, **kwargs)
if ma == 'ema': qstick = ema(diff, length=length, **kwargs)
if ma == 'hma': qstick = hma(diff, length=length)
if ma == 'rma': qstick = rma(diff, length=length)
# Offset
if offset != 0:
qstick = qstick.shift(offset)
# Handle fills
if 'fillna' in kwargs:
qstick.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
qstick.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
qstick.name = f"QS_{length}"
qstick.category = 'trend'
return qstick
def short_run(fast, slow, length=None, offset=None, **kwargs):
"""Indicator: Short Run"""
# Validate Arguments
fast = verify_series(fast)
slow = verify_series(slow)
length = int(length) if length and length > 0 else 2
offset = get_offset(offset)
# Calculate Result
pt = decreasing(fast, length) & increasing(slow, length) # potential top or top
bd = decreasing(fast, length) & decreasing(slow, length) # fast and slow are decreasing
short_run = pt | bd
# Offset
if offset != 0:
short_run = short_run.shift(offset)
# Handle fills
if 'fillna' in kwargs:
short_run.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
short_run.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
short_run.name = f"SR_{length}"
short_run.category = 'trend'
return short_run
def vortex(high, low, close, length=None, drift=None, offset=None, **kwargs):
"""Indicator: Vortex"""
# Validate arguments
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
length = 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
drift = get_drift(drift)
offset = get_offset(offset)
# Calculate Result
tr = true_range(high=high, low=low, close=close)
tr_sum = tr.rolling(length, min_periods=min_periods).sum()
vmp = (high - low.shift(drift)).abs()
vmm = (low - high.shift(drift)).abs()
vip = vmp.rolling(length, min_periods=min_periods).sum() / tr_sum
vim = vmm.rolling(length, min_periods=min_periods).sum() / tr_sum
# Offset
if offset != 0:
vip = vip.shift(offset)
vim = vim.shift(offset)
# Handle fills
if 'fillna' in kwargs:
vip.fillna(kwargs['fillna'], inplace=True)
vim.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
vip.fillna(method=kwargs['fill_method'], inplace=True)
vim.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
vip.name = f"VTXP_{length}"
vim.name = f"VTXM_{length}"
vip.category = vim.category = 'trend'
# Prepare DataFrame to return
data = {vip.name: vip, vim.name: vim}
vtxdf = pd.DataFrame(data)
vtxdf.name = f"VTX_{length}"
vtxdf.category = 'trend'
return vtxdf
# Trend Documentation
adx.__doc__ = \
"""Average Directional Movement (ADX)
Average Directional Movement is meant to quantify trend strength by measuring
the amount of movement in a single direction.
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/average-directional-movement-adx/
Calculation:
DMI ADX TREND 2.0 by @TraderR0BERT, NETWORTHIE.COM
//Created by @TraderR0BERT, NETWORTHIE.COM, last updated 01/26/2016
//DMI Indicator
//Resolution input option for higher/lower time frames
study(title="DMI ADX TREND 2.0", shorttitle="ADX TREND 2.0")
adxlen = input(14, title="ADX Smoothing")
dilen = input(14, title="DI Length")
thold = input(20, title="Threshold")
threshold = thold
//Script for Indicator
dirmov(len) =>
up = change(high)
down = -change(low)
truerange = rma(tr, len)
plus = fixnan(100 * rma(up > down and up > 0 ? up : 0, len) / truerange)
minus = fixnan(100 * rma(down > up and down > 0 ? down : 0, len) / truerange)
[plus, minus]
adx(dilen, adxlen) =>
[plus, minus] = dirmov(dilen)
sum = plus + minus
adx = 100 * rma(abs(plus - minus) / (sum == 0 ? 1 : sum), adxlen)
[adx, plus, minus]
[sig, up, down] = adx(dilen, adxlen)
osob=input(40,title="Exhaustion Level for ADX, default = 40")
col = sig >= sig[1] ? green : sig <= sig[1] ? red : gray
//Plot Definitions Current Timeframe
p1 = plot(sig, color=col, linewidth = 3, title="ADX")
p2 = plot(sig, color=col, style=circles, linewidth=3, title="ADX")
p3 = plot(up, color=blue, linewidth = 3, title="+DI")
p4 = plot(up, color=blue, style=circles, linewidth=3, title="+DI")
p5 = plot(down, color=fuchsia, linewidth = 3, title="-DI")
p6 = plot(down, color=fuchsia, style=circles, linewidth=3, title="-DI")
h1 = plot(threshold, color=black, linewidth =3, title="Threshold")
trender = (sig >= up or sig >= down) ? 1 : 0
bgcolor(trender>0?black:gray, transp=85)
//Alert Function for ADX crossing Threshold
Up_Cross = crossover(up, threshold)
alertcondition(Up_Cross, title="DMI+ cross", message="DMI+ Crossing Threshold")
Down_Cross = crossover(down, threshold)
alertcondition(Down_Cross, title="DMI- cross", message="DMI- Crossing Threshold")
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
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: adx, dmp, dmn columns.
"""
aroon.__doc__ = \
"""Aroon (AROON)
Aroon attempts to identify if a security is trending and how strong.
Sources:
https://www.tradingview.com/wiki/Aroon
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/aroon-ar/
Calculation:
Default Inputs:
length=1
def maxidx(x):
return 100 * (int(np.argmax(x)) + 1) / length
def minidx(x):
return 100 * (int(np.argmin(x)) + 1) / length
_close = close.rolling(length, min_periods=min_periods)
aroon_up = _close.apply(maxidx, raw=True)
aroon_down = _close.apply(minidx, raw=True)
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.DataFrame: aroon_up, aroon_down columns.
"""
decreasing.__doc__ = \
"""Decreasing
Returns True or False if the series is decreasing over a periods. By default,
it returns True and False as 1 and 0 respectively with kwarg 'asint'.
Sources:
Calculation:
decreasing = close.diff(length) < 0
if asint:
decreasing = decreasing.astype(int)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 1
asint (bool): Returns as binary. Default: True
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.
"""
dpo.__doc__ = \
"""Detrend Price Oscillator (DPO)
Is an indicator designed to remove trend from price and make it easier to
identify cycles.
Sources:
http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:detrended_price_osci
Calculation:
Default Inputs:
length=1, centered=True
SMA = Simple Moving Average
drift = int(0.5 * length) + 1
DPO = close.shift(drift) - SMA(close, length)
if centered:
DPO = DPO.shift(-drift)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 1
centered (bool): Shift the dpo back by int(0.5 * length) + 1. Default: True
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.
"""
increasing.__doc__ = \
"""Increasing
Returns True or False if the series is increasing over a periods. By default,
it returns True and False as 1 and 0 respectively with kwarg 'asint'.
Sources:
Calculation:
increasing = close.diff(length) > 0
if asint:
increasing = increasing.astype(int)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 1
asint (bool): Returns as binary. Default: True
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.
"""
qstick.__doc__ = \
"""Q Stick
The Q Stick indicator, developed by Tushar Chande, attempts to quantify and identify
trends in candlestick charts.
Sources:
https://library.tradingtechnologies.com/trade/chrt-ti-qstick.html
Calculation:
Default Inputs:
length=10
xMA is one of: sma (default), dema, ema, hma, rma
qstick = xMA(close - open, length)
Args:
open (pd.Series): Series of 'open's
close (pd.Series): Series of 'close's
length (int): It's period. Default: 1
ma (str): The type of moving average to use. Default: None, which is 'sma'
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.
"""
vortex.__doc__ = \
"""Vortex
Two oscillators that capture positive and negative trend movement.
Sources:
https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:vortex_indicator
Calculation:
Default Inputs:
length=14, drift=1
TR = True Range
SMA = Simple Moving Average
tr = TR(high, low, close)
tr_sum = tr.rolling(length).sum()
vmp = (high - low.shift(drift)).abs()
vmn = (low - high.shift(drift)).abs()
VIP = vmp.rolling(length).sum() / tr_sum
VIM = vmn.rolling(length).sum() / tr_sum
Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
length (int): ROC 1 period. Default: 14
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: vip and vim columns
"""
+1
View File
@@ -0,0 +1 @@
# -*- coding: utf-8 -*-
+141
View File
@@ -0,0 +1,141 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from ..overlap import rma
from ..volatility.atr import atr
from ..utils import get_drift, get_offset, verify_series, zero
def adx(high, low, close, length=None, drift=None, offset=None, **kwargs):
"""Indicator: ADX"""
# Validate Arguments
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
length = length if length and length > 0 else 14
drift = get_drift(drift)
offset = get_offset(offset)
# Calculate Result
_atr = atr(high=high, low=low, close=close, length=length)
up = high - high.shift(drift)
dn = low.shift(drift) - low
pos = ((up > dn) & (up > 0)) * up
neg = ((dn > up) & (dn > 0)) * dn
pos = pos.apply(zero)
neg = neg.apply(zero)
dmp = (100 / _atr) * rma(close=pos, length=length)
dmn = (100 / _atr) * rma(close=neg, length=length)
dx = 100 * (dmp - dmn).abs() / (dmp + dmn)
adx = rma(close=dx, length=length)
# Offset
if offset != 0:
dmp = dmp.shift(offset)
dmn = dmn.shift(offset)
adx = adx.shift(offset)
# Handle fills
if 'fillna' in kwargs:
adx.fillna(kwargs['fillna'], inplace=True)
dmp.fillna(kwargs['fillna'], inplace=True)
dmn.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
adx.fillna(method=kwargs['fill_method'], inplace=True)
dmp.fillna(method=kwargs['fill_method'], inplace=True)
dmn.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
adx.name = f"ADX_{length}"
dmp.name = f"DMP_{length}"
dmn.name = f"DMN_{length}"
adx.category = dmp.category = dmn.category = 'trend'
# Prepare DataFrame to return
data = {adx.name: adx, dmp.name: dmp, dmn.name: dmn}
adxdf = DataFrame(data)
adxdf.name = f"ADX_{length}"
adxdf.category = 'trend'
return adxdf
adx.__doc__ = \
"""Average Directional Movement (ADX)
Average Directional Movement is meant to quantify trend strength by measuring
the amount of movement in a single direction.
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/average-directional-movement-adx/
Calculation:
DMI ADX TREND 2.0 by @TraderR0BERT, NETWORTHIE.COM
//Created by @TraderR0BERT, NETWORTHIE.COM, last updated 01/26/2016
//DMI Indicator
//Resolution input option for higher/lower time frames
study(title="DMI ADX TREND 2.0", shorttitle="ADX TREND 2.0")
adxlen = input(14, title="ADX Smoothing")
dilen = input(14, title="DI Length")
thold = input(20, title="Threshold")
threshold = thold
//Script for Indicator
dirmov(len) =>
up = change(high)
down = -change(low)
truerange = rma(tr, len)
plus = fixnan(100 * rma(up > down and up > 0 ? up : 0, len) / truerange)
minus = fixnan(100 * rma(down > up and down > 0 ? down : 0, len) / truerange)
[plus, minus]
adx(dilen, adxlen) =>
[plus, minus] = dirmov(dilen)
sum = plus + minus
adx = 100 * rma(abs(plus - minus) / (sum == 0 ? 1 : sum), adxlen)
[adx, plus, minus]
[sig, up, down] = adx(dilen, adxlen)
osob=input(40,title="Exhaustion Level for ADX, default = 40")
col = sig >= sig[1] ? green : sig <= sig[1] ? red : gray
//Plot Definitions Current Timeframe
p1 = plot(sig, color=col, linewidth = 3, title="ADX")
p2 = plot(sig, color=col, style=circles, linewidth=3, title="ADX")
p3 = plot(up, color=blue, linewidth = 3, title="+DI")
p4 = plot(up, color=blue, style=circles, linewidth=3, title="+DI")
p5 = plot(down, color=fuchsia, linewidth = 3, title="-DI")
p6 = plot(down, color=fuchsia, style=circles, linewidth=3, title="-DI")
h1 = plot(threshold, color=black, linewidth =3, title="Threshold")
trender = (sig >= up or sig >= down) ? 1 : 0
bgcolor(trender>0?black:gray, transp=85)
//Alert Function for ADX crossing Threshold
Up_Cross = crossover(up, threshold)
alertcondition(Up_Cross, title="DMI+ cross", message="DMI+ Crossing Threshold")
Down_Cross = crossover(down, threshold)
alertcondition(Down_Cross, title="DMI- cross", message="DMI- Crossing Threshold")
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
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: adx, dmp, dmn columns.
"""
+65
View File
@@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from .long_run import long_run
from ..overlap import ema, hma, linreg, rma, sma, wma
from .short_run import short_run
from ..utils import get_offset, verify_series
def amat(close=None, fast=None, slow=None, mamode=None, lookback=None, offset=None, **kwargs):
"""Indicator: Archer Moving Averages Trends (AMAT)"""
# Validate Arguments
close = verify_series(close)
fast = int(fast) if fast and fast > 0 else 8
slow = int(slow) if slow and slow > 0 else 21
lookback = int(lookback) if lookback and lookback > 0 else 2
mamode = mamode.upper() if mamode else 'EMA'
offset = get_offset(offset)
# Calculate Result
if mamode == 'EMA':
fast_ma = ema(close=close, length=fast, **kwargs)
slow_ma = ema(close=close, length=slow, **kwargs)
elif mamode == 'HMA':
fast_ma = hma(close=close, length=fast, **kwargs)
slow_ma = hma(close=close, length=slow, **kwargs)
elif mamode == 'LINREG':
fast_ma = linreg(close=close, length=fast, **kwargs)
slow_ma = linreg(close=close, length=slow, **kwargs)
elif mamode == 'RMA':
fast_ma = rma(close=close, length=fast, **kwargs)
slow_ma = rma(close=close, length=slow, **kwargs)
elif mamode == 'SMA':
fast_ma = sma(close=close, length=fast, **kwargs)
slow_ma = sma(close=close, length=slow, **kwargs)
elif mamode == 'WMA':
fast_ma = wma(close=close, length=fast, **kwargs)
slow_ma = wma(close=close, length=slow, **kwargs)
mas_long = long_run(fast_ma, slow_ma, length=lookback)
mas_short = short_run(fast_ma, slow_ma, length=lookback)
# Offset
if offset != 0:
mas_long = mas_long.shift(offset)
mas_short = mas_short.shift(offset)
# # Handle fills
if 'fillna' in kwargs:
mas_long.fillna(kwargs['fillna'], inplace=True)
mas_short.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
mas_long.fillna(method=kwargs['fill_method'], inplace=True)
mas_short.fillna(method=kwargs['fill_method'], inplace=True)
# Prepare DataFrame to return
amatdf = DataFrame({
f"AMAT_{mas_long.name}": mas_long,
f"AMAT_{mas_short.name}": mas_short
})
# Name and Categorize it
amatdf.name = f"AMAT_{mamode}_{fast}_{slow}_{lookback}"
amatdf.category = 'trend'
return amatdf
+88
View File
@@ -0,0 +1,88 @@
# -*- coding: utf-8 -*-
from numpy import argmax as npargmax
from numpy import argmin as npargmin
from pandas import DataFrame
from ..utils import get_offset, verify_series
def aroon(close, length=None, offset=None, **kwargs):
"""Indicator: Aroon Oscillator"""
# Validate Arguments
close = verify_series(close)
length = 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
def maxidx(x):
return 100 * (int(npargmax(x)) + 1) / length
def minidx(x):
return 100 * (int(npargmin(x)) + 1) / length
_close = close.rolling(length, min_periods=min_periods)
aroon_up = _close.apply(maxidx, raw=True)
aroon_down = _close.apply(minidx, raw=True)
# Handle fills
if 'fillna' in kwargs:
aroon_up.fillna(kwargs['fillna'], inplace=True)
aroon_down.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
aroon_up.fillna(method=kwargs['fill_method'], inplace=True)
aroon_down.fillna(method=kwargs['fill_method'], inplace=True)
# Offset
if offset != 0:
aroon_up = aroon_up.shift(offset)
aroon_down = aroon_down.shift(offset)
# Name and Categorize it
aroon_up.name = f"AROONU_{length}"
aroon_down.name = f"AROOND_{length}"
aroon_down.category = aroon_up.category = 'trend'
# Prepare DataFrame to return
data = {aroon_down.name: aroon_down, aroon_up.name: aroon_up}
aroondf = DataFrame(data)
aroondf.name = f"AROON_{length}"
aroondf.category = 'trend'
return aroondf
aroon.__doc__ = \
"""Aroon (AROON)
Aroon attempts to identify if a security is trending and how strong.
Sources:
https://www.tradingview.com/wiki/Aroon
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/aroon-ar/
Calculation:
Default Inputs:
length=1
def maxidx(x):
return 100 * (int(np.argmax(x)) + 1) / length
def minidx(x):
return 100 * (int(np.argmin(x)) + 1) / length
_close = close.rolling(length, min_periods=min_periods)
aroon_up = _close.apply(maxidx, raw=True)
aroon_down = _close.apply(minidx, raw=True)
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.DataFrame: aroon_up, aroon_down columns.
"""
+59
View File
@@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def decreasing(close, length=None, asint=True, offset=None, **kwargs):
"""Indicator: Decreasing"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 1
offset = get_offset(offset)
# Calculate Result
decreasing = close.diff(length) < 0
if asint:
decreasing = decreasing.astype(int)
# Offset
if offset != 0:
decreasing = decreasing.shift(offset)
# Handle fills
if 'fillna' in kwargs:
decreasing.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
decreasing.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
decreasing.name = f"DEC_{length}"
decreasing.category = 'trend'
return decreasing
decreasing.__doc__ = \
"""Decreasing
Returns True or False if the series is decreasing over a periods. By default,
it returns True and False as 1 and 0 respectively with kwarg 'asint'.
Sources:
Calculation:
decreasing = close.diff(length) < 0
if asint:
decreasing = decreasing.astype(int)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 1
asint (bool): Returns as binary. Default: True
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 ..utils import get_offset, verify_series
def dpo(close, length=None, centered=True, offset=None, **kwargs):
"""Indicator: Detrend Price Oscillator (DPO)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 1
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
drift = int(0.5 * length) + 1 # int((0.5 * length) + 1)
dpo = close.shift(drift) - close.rolling(length, min_periods=min_periods).mean()
if centered:
dpo = dpo.shift(-drift)
# Offset
if offset != 0:
dpo = dpo.shift(offset)
# Handle fills
if 'fillna' in kwargs:
dpo.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
dpo.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
dpo.name = f"DPO_{length}"
dpo.category = 'trend'
return dpo
dpo.__doc__ = \
"""Detrend Price Oscillator (DPO)
Is an indicator designed to remove trend from price and make it easier to
identify cycles.
Sources:
http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:detrended_price_osci
Calculation:
Default Inputs:
length=1, centered=True
SMA = Simple Moving Average
drift = int(0.5 * length) + 1
DPO = close.shift(drift) - SMA(close, length)
if centered:
DPO = DPO.shift(-drift)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 1
centered (bool): Shift the dpo back by int(0.5 * length) + 1. Default: True
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.
"""
+59
View File
@@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def increasing(close, length=None, asint=True, offset=None, **kwargs):
"""Indicator: Increasing"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 1
offset = get_offset(offset)
# Calculate Result
increasing = close.diff(length) > 0
if asint:
increasing = increasing.astype(int)
# Offset
if offset != 0:
increasing = increasing.shift(offset)
# Handle fills
if 'fillna' in kwargs:
increasing.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
increasing.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
increasing.name = f"INC_{length}"
increasing.category = 'trend'
return increasing
increasing.__doc__ = \
"""Increasing
Returns True or False if the series is increasing over a periods. By default,
it returns True and False as 1 and 0 respectively with kwarg 'asint'.
Sources:
Calculation:
increasing = close.diff(length) > 0
if asint:
increasing = increasing.astype(int)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 1
asint (bool): Returns as binary. Default: True
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.
"""
+33
View File
@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
from .decreasing import decreasing
from .increasing import increasing
from ..utils import get_offset, verify_series
def long_run(fast, slow, length=None, offset=None, **kwargs):
"""Indicator: Long Run"""
# Validate Arguments
fast = verify_series(fast)
slow = verify_series(slow)
length = int(length) if length and length > 0 else 2
offset = get_offset(offset)
# Calculate Result
pb = increasing(fast, length) & decreasing(slow, length) # potential bottom or bottom
bi = increasing(fast, length) & increasing(slow, length) # fast and slow are increasing
long_run = pb | bi
# Offset
if offset != 0:
long_run = long_run.shift(offset)
# Handle fills
if 'fillna' in kwargs:
long_run.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
long_run.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
long_run.name = f"LR_{length}"
long_run.category = 'trend'
return long_run
+69
View File
@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
from ..overlap import dema, ema, hma, rma, sma
from ..utils import get_offset, verify_series
def qstick(open_, close, length=None, offset=None, **kwargs):
"""Indicator: Q Stick"""
# Validate Arguments
open_ = verify_series(open_)
close = verify_series(close)
length = int(length) if length and length > 0 else 10
offset = get_offset(offset)
ma = kwargs.pop('ma', 'sma') if 'ma' in kwargs else 'sma'
# Calculate Result
diff = close - open_
if ma in [None, 'sma']: qstick = sma(diff, length=length)
if ma == 'dema': qstick = dema(diff, length=length, **kwargs)
if ma == 'ema': qstick = ema(diff, length=length, **kwargs)
if ma == 'hma': qstick = hma(diff, length=length)
if ma == 'rma': qstick = rma(diff, length=length)
# Offset
if offset != 0:
qstick = qstick.shift(offset)
# Handle fills
if 'fillna' in kwargs:
qstick.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
qstick.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
qstick.name = f"QS_{length}"
qstick.category = 'trend'
return qstick
qstick.__doc__ = \
"""Q Stick
The Q Stick indicator, developed by Tushar Chande, attempts to quantify and identify
trends in candlestick charts.
Sources:
https://library.tradingtechnologies.com/trade/chrt-ti-qstick.html
Calculation:
Default Inputs:
length=10
xMA is one of: sma (default), dema, ema, hma, rma
qstick = xMA(close - open, length)
Args:
open (pd.Series): Series of 'open's
close (pd.Series): Series of 'close's
length (int): It's period. Default: 1
ma (str): The type of moving average to use. Default: None, which is 'sma'
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.
"""
+33
View File
@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
from .decreasing import decreasing
from .increasing import increasing
from ..utils import get_offset, verify_series
def short_run(fast, slow, length=None, offset=None, **kwargs):
"""Indicator: Short Run"""
# Validate Arguments
fast = verify_series(fast)
slow = verify_series(slow)
length = int(length) if length and length > 0 else 2
offset = get_offset(offset)
# Calculate Result
pt = decreasing(fast, length) & increasing(slow, length) # potential top or top
bd = decreasing(fast, length) & decreasing(slow, length) # fast and slow are decreasing
short_run = pt | bd
# Offset
if offset != 0:
short_run = short_run.shift(offset)
# Handle fills
if 'fillna' in kwargs:
short_run.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
short_run.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
short_run.name = f"SR_{length}"
short_run.category = 'trend'
return short_run
+91
View File
@@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from ..volatility.true_range import true_range
from ..utils import get_drift, get_offset, verify_series, zero
def vortex(high, low, close, length=None, drift=None, offset=None, **kwargs):
"""Indicator: Vortex"""
# Validate arguments
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
length = 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
drift = get_drift(drift)
offset = get_offset(offset)
# Calculate Result
tr = true_range(high=high, low=low, close=close)
tr_sum = tr.rolling(length, min_periods=min_periods).sum()
vmp = (high - low.shift(drift)).abs()
vmm = (low - high.shift(drift)).abs()
vip = vmp.rolling(length, min_periods=min_periods).sum() / tr_sum
vim = vmm.rolling(length, min_periods=min_periods).sum() / tr_sum
# Offset
if offset != 0:
vip = vip.shift(offset)
vim = vim.shift(offset)
# Handle fills
if 'fillna' in kwargs:
vip.fillna(kwargs['fillna'], inplace=True)
vim.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
vip.fillna(method=kwargs['fill_method'], inplace=True)
vim.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
vip.name = f"VTXP_{length}"
vim.name = f"VTXM_{length}"
vip.category = vim.category = 'trend'
# Prepare DataFrame to return
data = {vip.name: vip, vim.name: vim}
vtxdf = DataFrame(data)
vtxdf.name = f"VTX_{length}"
vtxdf.category = 'trend'
return vtxdf
vortex.__doc__ = \
"""Vortex
Two oscillators that capture positive and negative trend movement.
Sources:
https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:vortex_indicator
Calculation:
Default Inputs:
length=14, drift=1
TR = True Range
SMA = Simple Moving Average
tr = TR(high, low, close)
tr_sum = tr.rolling(length).sum()
vmp = (high - low.shift(drift)).abs()
vmn = (low - high.shift(drift)).abs()
VIP = vmp.rolling(length).sum() / tr_sum
VIM = vmn.rolling(length).sum() / tr_sum
Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
length (int): ROC 1 period. Default: 14
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: vip and vim columns
"""
+2 -1
View File
@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
from .obv import obv
from ..overlap import *
from ..trend import long_run, short_run
from ..trend.long_run import long_run
from ..trend.short_run import short_run
from ..utils import get_offset, verify_series
def aobv(close, volume, fast=None, slow=None, mamode=None, max_lookback=None, min_lookback=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.23b",
version = "0.1.24b",
description=long_description,
long_description=long_description,
author = "Kevin Johnson",
+12 -15
View File
@@ -30,15 +30,12 @@ class TestTrend(TestCase):
del cls.data
def setUp(self):
self.trend = pandas_ta.trend
def tearDown(self):
del self.trend
def setUp(self): pass
def tearDown(self): pass
def test_adx(self):
result = self.trend.adx(self.high, self.low, self.close)
result = pandas_ta.adx(self.high, self.low, self.close)
self.assertIsInstance(result, DataFrame)
self.assertEqual(result.name, 'ADX_14')
@@ -53,12 +50,12 @@ class TestTrend(TestCase):
error_analysis(result, CORRELATION, ex)
def test_amat(self):
result = self.trend.amat(self.close)
result = pandas_ta.amat(self.close)
self.assertIsInstance(result, DataFrame)
self.assertEqual(result.name, 'AMAT_EMA_8_21_2')
def test_aroon(self):
result = self.trend.aroon(self.close)
result = pandas_ta.aroon(self.close)
self.assertIsInstance(result, DataFrame)
self.assertEqual(result.name, 'AROON_14')
@@ -80,36 +77,36 @@ class TestTrend(TestCase):
error_analysis(result.iloc[:,1], CORRELATION, ex, newline=False)
def test_decreasing(self):
result = self.trend.decreasing(self.close)
result = pandas_ta.decreasing(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'DEC_1')
def test_dpo(self):
result = self.trend.dpo(self.close)
result = pandas_ta.dpo(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'DPO_1')
def test_increasing(self):
result = self.trend.increasing(self.close)
result = pandas_ta.increasing(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'INC_1')
def test_long_run(self):
result = self.trend.long_run(self.close, self.open)
result = pandas_ta.long_run(self.close, self.open)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'LR_2')
def test_qstick(self):
result = self.trend.qstick(self.open, self.close)
result = pandas_ta.qstick(self.open, self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'QS_10')
def test_short_run(self):
result = self.trend.short_run(self.close, self.open)
result = pandas_ta.short_run(self.close, self.open)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'SR_2')
def test_vortex(self):
result = self.trend.vortex(self.high, self.low, self.close)
result = pandas_ta.vortex(self.high, self.low, self.close)
self.assertIsInstance(result, DataFrame)
self.assertEqual(result.name, 'VTX_14')