Merge pull request #18 from twopirllc/overlap-refactor

overlap refactoring
This commit is contained in:
Kevin Johnson
2019-05-20 13:26:25 -07:00
committed by GitHub
40 changed files with 1459 additions and 1529 deletions
+1
View File
@@ -134,6 +134,7 @@ pandas_pips
reqs.txt
requirements.txt
qd.py
_overlap.py
_trend.py
_statistics.py
simple.ipynb
+24
View File
@@ -18,6 +18,30 @@ except DistributionNotFound:
else:
__version__ = _dist.version
# Overlap
from .overlap.dema import dema
from .overlap.ema import ema
from .overlap.fwma import fwma
from .overlap.hl2 import hl2
from .overlap.hlc3 import hlc3
from .overlap.hma import hma
from .overlap.ichimoku import ichimoku
from .overlap.linreg import linreg
from .overlap.midpoint import midpoint
from .overlap.midprice import midprice
from .overlap.ohlc4 import ohlc4
from .overlap.pwma import pwma
from .overlap.rma import rma
from .overlap.sma import sma
from .overlap.swma import swma
from .overlap.t3 import t3
from .overlap.tema import tema
from .overlap.trima import trima
from .overlap.vwap import vwap
from .overlap.vwma import vwma
from .overlap.wma import wma
from .overlap.zlma import zlma
# Performance
from .performance.log_return import log_return
from .performance.percent_return import percent_return
+22 -1
View File
@@ -4,7 +4,6 @@ import pandas as pd
from pandas.core.base import PandasObject
from .momentum import *
from .overlap import *
from .utils import *
class BasePandasObject(PandasObject):
@@ -351,18 +350,21 @@ class AnalysisIndicators(BasePandasObject):
# Overlap Indicators
def dema(self, close=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.dema import dema
result = dema(close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def ema(self, close=None, length=None, offset=None, adjust=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.ema import ema
result = ema(close=close, length=length, offset=offset, adjust=adjust, **kwargs)
self._append(result, **kwargs)
return result
def fwma(self, close=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.fwma import fwma
result = fwma(close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -370,6 +372,7 @@ class AnalysisIndicators(BasePandasObject):
def hl2(self, high=None, low=None, offset=None, **kwargs):
high = self._get_column(high, 'high')
low = self._get_column(low, 'low')
from .overlap.hl2 import hl2
result = hl2(high=high, low=low, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -378,12 +381,14 @@ class AnalysisIndicators(BasePandasObject):
high = self._get_column(high, 'high')
low = self._get_column(low, 'low')
close = self._get_column(close, 'close')
from .overlap.hlc3 import hlc3
result = hlc3(high=high, low=low, close=close, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def hma(self, close=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.hma import hma
result = hma(close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -392,18 +397,21 @@ class AnalysisIndicators(BasePandasObject):
high = self._get_column(high, 'high')
low = self._get_column(low, 'low')
close = self._get_column(close, 'close')
from .overlap.ichimoku import ichimoku
result, span = ichimoku(high=high, low=low, close=close, tenkan=tenkan, kijun=kijun, senkou=senkou, offset=offset, **kwargs)
self._append(result, **kwargs)
return result, span
def linreg(self, close=None, length=None, offset=None, adjust=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.linreg import linreg
result = linreg(close=close, length=length, offset=offset, adjust=adjust, **kwargs)
self._append(result, **kwargs)
return result
def midpoint(self, close=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.midpoint import midpoint
result = midpoint(close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -411,6 +419,7 @@ class AnalysisIndicators(BasePandasObject):
def midprice(self, high=None, low=None, length=None, offset=None, **kwargs):
high = self._get_column(high, 'high')
low = self._get_column(low, 'low')
from .overlap.midprice import midprice
result = midprice(high=high, low=low, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -420,48 +429,56 @@ class AnalysisIndicators(BasePandasObject):
high = self._get_column(high, 'high')
low = self._get_column(low, 'low')
close = self._get_column(close, 'close')
from .overlap.ohlc4 import ohlc4
result = ohlc4(open_=open_, high=high, low=low, close=close, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def pwma(self, close=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.pwma import pwma
result = pwma(close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def rma(self, close=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.rma import rma
result = rma(close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def sma(self, close=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.sma import sma
result = sma(close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def swma(self, close=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.swma import swma
result = swma(close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def t3(self, close=None, length=None, a=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.t3 import t3
result = t3(close=close, length=length, a=a, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def tema(self, close=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.tema import tema
result = tema(close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def trima(self, close=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.trima import trima
result = trima(close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -471,6 +488,7 @@ class AnalysisIndicators(BasePandasObject):
low = self._get_column(low, 'low')
close = self._get_column(close, 'close')
volume = self._get_column(volume, 'volume')
from .overlap.vwap import vwap
result = vwap(high=high, low=low, close=close, volume=volume, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
@@ -478,18 +496,21 @@ class AnalysisIndicators(BasePandasObject):
def vwma(self, close=None, volume=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
volume = self._get_column(volume, 'volume')
from .overlap.vwma import vwma
result = vwma(close=close, volume=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def wma(self, close=None, length=None, offset=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.wma import wma
result = wma(close=close, length=length, offset=offset, **kwargs)
self._append(result, **kwargs)
return result
def zlma(self, close=None, length=None, offset=None, mamode=None, **kwargs):
close = self._get_column(close, 'close')
from .overlap.zlma import zlma
result = zlma(close=close, length=length, offset=offset, mamode=mamode, **kwargs)
self._append(result, **kwargs)
return result
+4 -1
View File
@@ -2,7 +2,10 @@
import numpy as np
import pandas as pd
from .overlap import hlc3, ema, sma, wma
from .overlap.hlc3 import hlc3
from .overlap.ema import ema
from .overlap.sma import sma
from .overlap.wma import wma
from .statistics.mad import mad
from .utils import get_drift, get_offset, verify_series
-1484
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
# -*- coding: utf-8 -*-
+59
View File
@@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
from .ema import ema
from ..utils import get_offset, verify_series, weights
def dema(close, length=None, offset=None, **kwargs):
"""Indicator: Double Exponential Moving Average (DEMA)"""
# 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
ema1 = ema(close=close, length=length, **kwargs)
ema2 = ema(close=ema1, length=length, **kwargs)
dema = 2 * ema1 - ema2
# Offset
if offset != 0:
dema = dema.shift(offset)
# Name & Category
dema.name = f"DEMA_{length}"
dema.category = 'overlap'
return dema
dema.__doc__ = \
"""Double Exponential Moving Average (DEMA)
The Double Exponential Moving Average attempts to a smoother average with less
lag than the normal Exponential Moving Average (EMA).
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/double-exponential-moving-average-dema/
Calculation:
Default Inputs:
length=10
EMA = Exponential Moving Average
ema1 = EMA(close, length)
ema2 = EMA(ema1, length)
DEMA = 2 * ema1 - ema2
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
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.
"""
+86
View File
@@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
from numpy import NaN as npNaN
from ..utils import get_offset, verify_series
def ema(close, length=None, offset=None, **kwargs):
"""Indicator: Exponential Moving Average (EMA)"""
# Validate Arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 10
min_periods = kwargs.pop('min_periods', length)
adjust = kwargs.pop('adjust', True)
offset = get_offset(offset)
sma = kwargs.pop('sma', True)
ewm = kwargs.pop('ewm', False)
# Calculate Result
if ewm:
# Mathematical Implementation of an Exponential Weighted Moving Average
ema = close.ewm(span=length, min_periods=min_periods, adjust=adjust).mean()
else:
alpha = 2 / (length + 1)
close = close.copy()
def ema_(series):
# Technical Anaylsis Definition of an Exponential Moving Average
# Slow for large series
series.iloc[1] = alpha * (series.iloc[1] - series.iloc[0]) + series.iloc[0]
return series.iloc[1]
seed = close[0:length].mean() if sma else close.iloc[0]
close[:length - 1] = npNaN
close.iloc[length - 1] = seed
ma = close[length - 1:].rolling(2, min_periods=2).apply(ema_, raw=False)
ema = close[:length].append(ma[1:])
# Offset
if offset != 0:
ema = ema.shift(offset)
# Name & Category
ema.name = f"EMA_{length}"
ema.category = 'overlap'
return ema
ema.__doc__ = \
"""Exponential Moving Average (EMA)
The Exponential Moving Average is more responsive moving average compared to the
Simple Moving Average (SMA). The weights are determined by alpha which is
proportional to it's length. There are several different methods of calculating
EMA. One method uses just the standard definition of EMA and another uses the
SMA to generate the initial value for the rest of the calculation.
Sources:
https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages
https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp
Calculation:
Default Inputs:
length=10
SMA = Simple Moving Average
if kwargs['presma']:
initial = SMA(close, length)
rest = close[length:]
close = initial + rest
EMA = close.ewm(span=length, adjust=adjust).mean()
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
offset (int): How many periods to offset the result. Default: 0
Kwargs:
adjust (bool, optional): Default: True
sma (bool, optional): If True, uses SMA for initial value.
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+61
View File
@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
from ..utils import fibonacci, get_offset, verify_series, weights
def fwma(close, length=None, asc=None, offset=None, **kwargs):
"""Indicator: Fibonacci's Weighted Moving Average (FWMA)"""
# 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
asc = asc if asc else True
offset = get_offset(offset)
# Calculate Result
fibs = fibonacci(n=length, weighted=True)
fwma = close.rolling(length, min_periods=length).apply(weights(fibs), raw=True)
# Offset
if offset != 0:
fwma = fwma.shift(offset)
# Name & Category
fwma.name = f"FWMA_{length}"
fwma.category = 'overlap'
return fwma
fwma.__doc__ = \
"""Fibonacci's Weighted Moving Average (FWMA)
Fibonacci's Weighted Moving Average is similar to a Weighted Moving Average
(WMA) where the weights are based on the Fibonacci Sequence.
Source: Kevin Johnson
Calculation:
Default Inputs:
length=10,
def weights(w):
def _compute(x):
return np.dot(w * x)
return _compute
fibs = utils.fibonacci(length - 1)
FWMA = close.rolling(length)_.apply(weights(fibs), raw=True)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
asc (bool): Recent values weigh more. 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.
"""
+22
View File
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def hl2(high, low, offset=None, **kwargs):
"""Indicator: HL2 """
# Validate Arguments
high = verify_series(high)
low = verify_series(low)
offset = get_offset(offset)
# Calculate Result
hl2 = 0.5 * (high + low)
# Offset
if offset != 0:
hl2 = hl2.shift(offset)
# Name & Category
hl2.name = "HL2"
hl2.category = 'overlap'
return hl2
+23
View File
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def hlc3(high, low, close, offset=None, **kwargs):
"""Indicator: HLC3"""
# Validate Arguments
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
offset = get_offset(offset)
# Calculate Result
hlc3 = (high + low + close) / 3
# Offset
if offset != 0:
hlc3 = hlc3.shift(offset)
# Name & Category
hlc3.name = "HLC3"
hlc3.category = 'overlap'
return hlc3
+69
View File
@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
from math import sqrt
from .wma import wma
from ..utils import get_offset, verify_series
def hma(close, length=None, offset=None, **kwargs):
"""Indicator: Hull Moving Average (HMA)
Use help(df.ta.hma) for specific documentation where 'df' represents
the DataFrame you are using.
"""
# 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
half_length = int(length / 2)
sqrt_length = int(sqrt(length))
wmaf = wma(close=close, length=half_length)
wmas = wma(close=close, length=length)
hma = wma(close=2 * wmaf - wmas, length=sqrt_length)
# Offset
if offset != 0:
hma = hma.shift(offset)
# Name & Category
hma.name = f"HMA_{length}"
hma.category = 'overlap'
return hma
hma.__doc__ = \
"""Hull Moving Average (HMA)
The Hull Exponential Moving Average attempts to reduce or remove lag in moving
averages.
Sources:
https://alanhull.com/hull-moving-average
Calculation:
Default Inputs:
length=10
WMA = Weighted Moving Average
half_length = int(0.5 * length)
sqrt_length = int(math.sqrt(length))
wmaf = WMA(close, half_length)
wmas = WMA(close, length)
HMA = WMA(2 * wmaf - wmas, sqrt_length)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
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.
"""
+126
View File
@@ -0,0 +1,126 @@
# -*- coding: utf-8 -*-
from pandas import date_range, DataFrame, RangeIndex, Timedelta
from .midprice import midprice
from ..utils import get_offset, verify_series
def ichimoku(high, low, close, tenkan=None, kijun=None, senkou=None, offset=None, **kwargs):
"""Indicator: Ichimoku Kinkō Hyō (Ichimoku)"""
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
tenkan = int(tenkan) if tenkan and tenkan > 0 else 9
kijun = int(kijun) if kijun and kijun > 0 else 26
senkou = int(senkou) if senkou and senkou > 0 else 52
offset = get_offset(offset)
# Calculate Result
tenkan_sen = midprice(high=high, low=low, length=tenkan)
kijun_sen = midprice(high=high, low=low, length=kijun)
span_a = 0.5 * (tenkan_sen + kijun_sen)
span_b = midprice(high=high, low=low, length=senkou)
# Copy Span A and B values before their shift
_span_a = span_a[-kijun:].copy()
_span_b = span_b[-kijun:].copy()
span_a = span_a.shift(kijun)
span_b = span_b.shift(kijun)
chikou_span = close.shift(-kijun)
# Offset
if offset != 0:
tenkan_sen = tenkan_sen.shift(offset)
kijun_sen = kijun_sen.shift(offset)
span_a = span_a.shift(offset)
span_b = span_b.shift(offset)
chikou_span = chikou_span.shift(offset)
# Handle fills
if 'fillna' in kwargs:
span_a.fillna(kwargs['fillna'], inplace=True)
span_b.fillna(kwargs['fillna'], inplace=True)
chikou_span.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
span_a.fillna(method=kwargs['fill_method'], inplace=True)
span_b.fillna(method=kwargs['fill_method'], inplace=True)
chikou_span.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
span_a.name = f"ISA_{tenkan}"
span_b.name = f"ISB_{kijun}"
tenkan_sen.name = f"ITS_{tenkan}"
kijun_sen.name = f"IKS_{kijun}"
chikou_span.name = f"ICS_{kijun}"
chikou_span.category = kijun_sen.category = tenkan_sen.category = 'trend'
span_b.category = span_a.category = chikou_span
# Prepare Ichimoku DataFrame
data = {span_a.name: span_a, span_b.name: span_b, tenkan_sen.name: tenkan_sen, kijun_sen.name: kijun_sen, chikou_span.name: chikou_span}
ichimokudf = DataFrame(data)
ichimokudf.name = f"ICHIMOKU_{tenkan}_{kijun}_{senkou}"
ichimokudf.category = 'overlap'
# Prepare Span DataFrame
last = close.index[-1]
if close.index.dtype == 'int64':
ext_index = RangeIndex(start=last + 1, stop=last + kijun + 1)
spandf = DataFrame(index=ext_index, columns=[span_a.name, span_b.name])
_span_a.index = _span_b.index = ext_index
else:
df_freq = close.index.value_counts().mode()[0]
tdelta = Timedelta(df_freq, unit='d')
new_dt = date_range(start=last + tdelta, periods=kijun, freq='B')
spandf = DataFrame(index=new_dt, columns=[span_a.name, span_b.name])
_span_a.index = _span_b.index = new_dt
spandf[span_a.name] = _span_a
spandf[span_b.name] = _span_b
spandf.name = f"ICHISPAN_{tenkan}_{kijun}"
spandf.category = 'overlap'
return ichimokudf, spandf
ichimoku.__doc__ = \
"""Ichimoku Kinkō Hyō (ichimoku)
Developed Pre WWII as a forecasting model for financial markets.
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/ichimoku-ich/
Calculation:
Default Inputs:
tenkan=9, kijun=26, senkou=52
MIDPRICE = Midprice
TENKAN_SEN = MIDPRICE(high, low, close, length=tenkan)
KIJUN_SEN = MIDPRICE(high, low, close, length=kijun)
CHIKOU_SPAN = close.shift(-kijun)
SPAN_A = 0.5 * (TENKAN_SEN + KIJUN_SEN)
SPAN_A = SPAN_A.shift(kijun)
SPAN_B = MIDPRICE(high, low, close, length=senkou)
SPAN_B = SPAN_B.shift(kijun)
Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
tenkan (int): Tenkan period. Default: 9
kijun (int): Kijun period. Default: 26
senkou (int): Senkou period. Default: 52
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: Two DataFrames.
For the visible period: spanA, spanB, tenkan_sen, kijun_sen,
and chikou_span columns
For the forward looking period: spanA and spanB columns
"""
+122
View File
@@ -0,0 +1,122 @@
# -*- coding: utf-8 -*-
import math
from ..utils import get_offset, verify_series
def linreg(close, length=None, offset=None, **kwargs):
"""Indicator: Linear Regression"""
# Validate arguments
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)
angle = kwargs.pop('angle', False)
intercept = kwargs.pop('intercept', False)
degrees = kwargs.pop('degrees', False)
r = kwargs.pop('r', False)
slope = kwargs.pop('slope', False)
tsf = kwargs.pop('tsf', False)
# Calculate Result
x = range(1, length + 1) # [1, 2, ..., n] from 1 to n keeps Sum(xy) low
x_sum = 0.5 * length * (length + 1)
x2_sum = x_sum * (2 * length + 1) / 3
divisor = length * x2_sum - x_sum * x_sum
def linear_regression(series):
y_sum = series.sum()
xy_sum = (x * series).sum()
m = (length * xy_sum - x_sum * y_sum) / divisor
if slope:
return m
b = (y_sum * x2_sum - x_sum * xy_sum) / divisor
if intercept:
return b
if angle:
theta = math.atan(m)
if degrees:
theta *= 180 / math.pi
return theta
if r:
y2_sum = (series * series).sum()
rn = length * xy_sum - x_sum * y_sum
rd = math.sqrt(divisor * (length * y2_sum - y_sum * y_sum))
return rn / rd
return m * length + b if tsf else m * (length - 1) + b
linreg = close.rolling(length, min_periods=length).apply(linear_regression, raw=False)
# Offset
if offset != 0:
linreg = linreg.shift(offset)
# Handle fills
if 'fillna' in kwargs:
linreg.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
linreg.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
linreg.name = f"LR"
if slope:
linreg.name += "m"
if intercept:
linreg.name += "b"
if angle:
linreg.name += "a"
if r:
linreg.name += "r"
linreg.name += f"_{length}"
linreg.category = 'overlap'
return linreg
linreg.__doc__ = \
"""Linear Regression Moving Average (linreg)
Linear Regression Moving Average
Source: TA Lib
Calculation:
Default Inputs:
length=14
x = [1, 2, ..., n]
x_sum = 0.5 * length * (length + 1)
x2_sum = length * (length + 1) * (2 * length + 1) / 6
divisor = length * x2_sum - x_sum * x_sum
lr(series):
y_sum = series.sum()
y2_sum = (series* series).sum()
xy_sum = (x * series).sum()
m = (length * xy_sum - x_sum * y_sum) / divisor
b = (y_sum * x2_sum - x_sum * xy_sum) / divisor
return m * (length - 1) + b
linreg = close.rolling(length).apply(lr)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
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
angle (bool, optional): Default: False. If True, returns the angle of the slope in radians
degrees (bool, optional): Default: False. If True, returns the angle of the slope in degrees
intercept (bool, optional): Default: False. If True, returns the angle of the slope in radians
r (bool, optional): Default: False. If True, returns it's correlation 'r'
slope (bool, optional): Default: False. If True, returns the slope
tsf (bool, optional): Default: False. If True, returns the Time Series Forecast value.
Returns:
pd.Series: New feature generated.
"""
+31
View File
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def midpoint(close, length=None, offset=None, **kwargs):
"""Indicator: Midpoint"""
# Validate arguments
close = verify_series(close)
length = int(length) if length and length > 0 else 2
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 = close.rolling(length, min_periods=min_periods).min()
highest = close.rolling(length, min_periods=min_periods).max()
midpoint = 0.5 * (lowest + highest)
# Offset
if offset != 0:
midpoint = midpoint.shift(offset)
# Handle fills
if 'fillna' in kwargs:
midpoint.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
midpoint.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
midpoint.name = f"MIDPOINT_{length}"
midpoint.category = 'overlap'
return midpoint
+32
View File
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def midprice(high, low, length=None, offset=None, **kwargs):
"""Indicator: Midprice"""
# Validate arguments
high = verify_series(high)
low = verify_series(low)
length = int(length) if length and length > 0 else 2
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()
midprice = 0.5 * (lowest_low + highest_high)
# Offset
if offset != 0:
midprice = midprice.shift(offset)
# Handle fills
if 'fillna' in kwargs:
midprice.fillna(kwargs['fillna'], inplace=True)
if 'fill_method' in kwargs:
midprice.fillna(method=kwargs['fill_method'], inplace=True)
# Name and Categorize it
midprice.name = f"MIDPRICE_{length}"
midprice.category = 'overlap'
return midprice
+24
View File
@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def ohlc4(open_, high, low, close, offset=None, **kwargs):
"""Indicator: OHLC4"""
# Validate Arguments
open_ = verify_series(open_)
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
offset = get_offset(offset)
# Calculate Result
ohlc4 = 0.25 * (open_ + high + low + close)
# Offset
if offset != 0:
ohlc4 = ohlc4.shift(offset)
# Name & Category
ohlc4.name = "OHLC4"
ohlc4.category = 'overlap'
return ohlc4
+61
View File
@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, pascals_triangle, verify_series, weights
def pwma(close, length=None, asc=None, offset=None, **kwargs):
"""Indicator: Pascals Weighted Moving Average (PWMA)"""
# 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
asc = asc if asc else True
offset = get_offset(offset)
# Calculate Result
triangle = pascals_triangle(n=length - 1, weighted=True)
pwma = close.rolling(length, min_periods=length).apply(weights(triangle), raw=True)
# Offset
if offset != 0:
pwma = pwma.shift(offset)
# Name & Category
pwma.name = f"PWMA_{length}"
pwma.category = 'overlap'
return pwma
pwma.__doc__ = \
"""Pascal's Weighted Moving Average (PWMA)
Pascal's Weighted Moving Average is similar to a symmetric triangular
window except PWMA's weights are based on Pascal's Triangle.
Source: Kevin Johnson
Calculation:
Default Inputs:
length=10
def weights(w):
def _compute(x):
return np.dot(w * x)
return _compute
triangle = utils.pascals_triangle(length + 1)
PWMA = close.rolling(length)_.apply(weights(triangle), raw=True)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
asc (bool): Recent values weigh more. 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.
"""
+55
View File
@@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def rma(close, length=None, offset=None, **kwargs):
"""Indicator: wildeR's Moving Average (RMA)"""
# 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)
alpha = (1.0 / length) if length > 0 else 0.5
# Calculate Result
rma = close.ewm(alpha=alpha, min_periods=min_periods).mean()
# Offset
if offset != 0:
rma = rma.shift(offset)
# Name & Category
rma.name = f"RMA_{length}"
rma.category = 'overlap'
return rma
rma.__doc__ = \
"""wildeR's Moving Average (RMA)
The WildeR's Moving Average is simply an Exponential Moving Average (EMA)
with a modified alpha = 1 / length.
Sources:
https://alanhull.com/hull-moving-average
Calculation:
Default Inputs:
length=10
EMA = Exponential Moving Average
alpha = 1 / length
RMA = EMA(close, alpha=alpha)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
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.
"""
+54
View File
@@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, verify_series
def sma(close, length=None, offset=None, **kwargs):
"""Indicator: Simple Moving Average (SMA)"""
# 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
sma = close.rolling(length, min_periods=min_periods).mean()
# Offset
if offset != 0:
sma = sma.shift(offset)
# Name & Category
sma.name = f"SMA_{length}"
sma.category = 'overlap'
return sma
sma.__doc__ = \
"""Simple Moving Average (SMA)
The Simple Moving Average is the classic moving average that is the equally
weighted average over n periods.
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/simple-moving-average-sma/
Calculation:
Default Inputs:
length=10
SMA = SUM(close, length) / length
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
offset (int): How many periods to offset the result. Default: 0
Kwargs:
adjust (bool): Default: True
presma (bool, optional): If True, uses SMA for initial value.
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+63
View File
@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
from ..utils import get_offset, pascals_triangle, verify_series, weights
def swma(close, length=None, asc=None, offset=None, **kwargs):
"""Indicator: Symmetric Weighted Moving Average (SWMA)"""
# 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
asc = asc if asc else True
offset = get_offset(offset)
# Calculate Result
triangle = pascals_triangle(n=length - 1, weighted=True)
swma = close.rolling(length, min_periods=length).apply(weights(triangle), raw=True)
# Offset
if offset != 0:
swma = swma.shift(offset)
# Name & Category
swma.name = f"SWMA_{length}"
swma.category = 'overlap'
return swma
swma.__doc__ = \
"""Symmetric Weighted Moving Average (SWMA)
Symmetric Weighted Moving Average where weights are based on a symmetric
triangle. For example: n=3 -> [1, 2, 1], n=4 -> [1, 2, 2, 1], etc... This moving
average has variable length in contrast to TradingView's fixed length of 4.
Source:
https://www.tradingview.com/study-script-reference/#fun_swma
Calculation:
Default Inputs:
length=10
def weights(w):
def _compute(x):
return np.dot(w * x)
return _compute
triangle = utils.symmetric_triangle(length - 1)
SWMA = close.rolling(length)_.apply(weights(triangle), raw=True)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
asc (bool): Recent values weigh more. 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.
"""
+79
View File
@@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
from .ema import ema
from ..utils import get_offset, verify_series
def t3(close, length=None, a=None, offset=None, **kwargs):
"""Indicator: T3"""
# 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
a = float(a) if a and a > 0 and a < 1 else 0.7
offset = get_offset(offset)
# Calculate Result
c1 = -a * a ** 2
c2 = 3 * a ** 2 + 3 * a ** 3
c3 = -6 * a ** 2 - 3 * a - 3 * a ** 3
c4 = a ** 3 + 3 * a ** 2 + 3 * a + 1
e1 = ema(close=close, length=length, **kwargs)
e2 = ema(close=e1, length=length, **kwargs)
e3 = ema(close=e2, length=length, **kwargs)
e4 = ema(close=e3, length=length, **kwargs)
e5 = ema(close=e4, length=length, **kwargs)
e6 = ema(close=e5, length=length, **kwargs)
t3 = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3
# Offset
if offset != 0:
t3 = t3.shift(offset)
# Name & Category
t3.name = f"T3_{length}_{a}"
t3.category = 'overlap'
return t3
t3.__doc__ = \
"""Tim Tillson's T3 Moving Average (T3)
Tim Tillson's T3 Moving Average is considered a smoother and more responsive
moving average relative to other moving averages.
Sources:
http://www.binarytribune.com/forex-trading-indicators/t3-moving-average-indicator/
Calculation:
Default Inputs:
length=10, a=0.7
c1 = -a^3
c2 = 3a^2 + 3a^3 = 3a^2 * (1 + a)
c3 = -6a^2 - 3a - 3a^3
c4 = a^3 + 3a^2 + 3a + 1
ema1 = EMA(close, length)
ema2 = EMA(ema1, length)
ema3 = EMA(ema2, length)
ema4 = EMA(ema3, length)
ema5 = EMA(ema4, length)
ema6 = EMA(ema5, length)
T3 = c1 * ema6 + c2 * ema5 + c3 * ema4 + c4 * ema3
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
a (float): 0 < a < 1. Default: 0.7
offset (int): How many periods to offset the result. Default: 0
Kwargs:
adjust (bool): Default: True
presma (bool, optional): If True, uses SMA for initial value.
fillna (value, optional): pd.DataFrame.fillna(value)
fill_method (value, optional): Type of fill method
Returns:
pd.Series: New feature generated.
"""
+61
View File
@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
from .ema import ema
from ..utils import get_offset, verify_series
def tema(close, length=None, offset=None, **kwargs):
"""Indicator: Triple Exponential Moving Average (TEMA)"""
# 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
ema1 = ema(close=close, length=length, **kwargs)
ema2 = ema(close=ema1, length=length, **kwargs)
ema3 = ema(close=ema2, length=length, **kwargs)
tema = 3 * (ema1 - ema2) + ema3
# Offset
if offset != 0:
tema = tema.shift(offset)
# Name & Category
tema.name = f"TEMA_{length}"
tema.category = 'overlap'
return tema
tema.__doc__ = \
"""Triple Exponential Moving Average (TEMA)
A less laggy Exponential Moving Average.
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triple-exponential-moving-average-tema/
Calculation:
Default Inputs:
length=10
EMA = Exponential Moving Average
ema1 = EMA(close, length)
ema2 = EMA(ema1, length)
ema3 = EMA(ema2, length)
TEMA = 3 * (ema1 - ema2) + ema3
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
offset (int): How many periods to offset the result. Default: 0
Kwargs:
adjust (bool): Default: True
presma (bool, optional): If True, uses SMA for initial value.
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 trima(close, length=None, offset=None, **kwargs):
"""Indicator: Triangular Moving Average (TRIMA)"""
# 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
half_length = round(0.5 * (length + 1))
sma1 = close.rolling(half_length, min_periods=half_length).mean()
trima = sma1.rolling(half_length, min_periods=half_length).mean()
# Offset
if offset != 0:
trima = trima.shift(offset)
# Name & Category
trima.name = f"TRIMA_{length}"
trima.category = 'overlap'
return trima
trima.__doc__ = \
"""Triangular Moving Average (TRIMA)
A weighted moving average where the shape of the weights are triangular and the
greatest weight is in the middle of the period.
Sources:
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triangular-moving-average-trima/
tma = sma(sma(src, ceil(length / 2)), floor(length / 2) + 1) # Tradingview
trima = sma(sma(x, n), n) # Tradingview
Calculation:
Default Inputs:
length=10
SMA = Simple Moving Average
half_length = math.round(0.5 * (length + 1))
SMA1 = SMA(close, half_length)
TRIMA = SMA(SMA1, half_length)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
offset (int): How many periods to offset the result. Default: 0
Kwargs:
adjust (bool): Default: True
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 .hlc3 import hlc3
from ..utils import get_offset, verify_series
def vwap(high, low, close, volume, offset=None, **kwargs):
"""Indicator: Volume Weighted Average Price (VWAP)"""
# Validate Arguments
high = verify_series(high)
low = verify_series(low)
close = verify_series(close)
volume = verify_series(volume)
offset = get_offset(offset)
# Calculate Result
tp = hlc3(high=high, low=low, close=close)
vwap = (tp * volume).cumsum() / volume.cumsum()
# Offset
if offset != 0:
vwap = vwap.shift(offset)
# Name & Category
vwap.name = "VWAP"
vwap.category = 'overlap'
return vwap
vwap.__doc__ = \
"""Volume Weighted Average Price (VWAP)
The Volume Weighted Average Price that measures the average typical price
by volume. It is typically used with intraday charts to identify general
direction.
Sources:
https://www.tradingview.com/wiki/Volume_Weighted_Average_Price_(VWAP)
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/volume-weighted-average-price-vwap/
Calculation:
tp = typical_price = hlc3(high, low, close)
tpv = tp * volume
VWAP = tpv.cumsum() / volume.cumsum()
Args:
high (pd.Series): Series of 'high's
low (pd.Series): Series of 'low's
close (pd.Series): Series of 'close's
volume (pd.Series): Series of 'volume'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.
"""
+56
View File
@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
from .sma import sma
from ..utils import get_offset, verify_series
def vwma(close, volume, length=None, offset=None, **kwargs):
"""Indicator: Volume Weighted Moving Average (VWMA)"""
# Validate Arguments
close = verify_series(close)
volume = verify_series(volume)
length = int(length) if length and length > 0 else 10
offset = get_offset(offset)
# Calculate Result
pv = close * volume
vwma = sma(close=pv, length=length) / sma(close=volume, length=length)
# Offset
if offset != 0:
vwma = vwma.shift(offset)
# Name & Category
vwma.name = f"VWMA_{length}"
vwma.category = 'overlap'
return vwma
vwma.__doc__ = \
"""Volume Weighted Moving Average (VWMA)
Volume Weighted Moving Average.
Sources:
https://www.motivewave.com/studies/volume_weighted_moving_average.htm
Calculation:
Default Inputs:
length=10
SMA = Simple Moving Average
pv = close * volume
VWMA = SMA(pv, length) / SMA(volume, length)
Args:
close (pd.Series): Series of 'close's
volume (pd.Series): Series of 'volume's
length (int): It's period. Default: 10
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.
"""
+75
View File
@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
from numpy import arange as nparange
from pandas import Series
from ..utils import get_offset, verify_series
def wma(close, length=None, asc=None, offset=None, **kwargs):
"""Indicator: Weighted Moving Average (WMA)"""
# 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
asc = asc if asc else True
offset = get_offset(offset)
# Calculate Result
total_weight = 0.5 * length * (length + 1)
weights_ = Series(nparange(1, length + 1))
weights = weights_ if asc else weights_[::-1]
def linear(w):
def _compute(x):
return (w * x).sum() / total_weight
return _compute
close_ = close.rolling(length, min_periods=length)
wma = close_.apply(linear(weights), raw=True)
# Offset
if offset != 0:
wma = wma.shift(offset)
# Name & Category
wma.name = f"WMA_{length}"
wma.category = 'overlap'
return wma
wma.__doc__ = \
"""Weighted Moving Average (WMA)
The Weighted Moving Average where the weights are linearly increasing and
the most recent data has the heaviest weight.
Sources:
https://en.wikipedia.org/wiki/Moving_average#Weighted_moving_average
Calculation:
Default Inputs:
length=10, asc=True
total_weight = 0.5 * length * (length + 1)
weights_ = [1, 2, ..., length + 1] # Ascending
weights = weights if asc else weights[::-1]
def linear_weights(w):
def _compute(x):
return (w * x).sum() / total_weight
return _compute
WMA = close.rolling(length)_.apply(linear_weights(weights), raw=True)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
asc (bool): Recent values weigh more. 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.
"""
+74
View File
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
from .ema import ema
from .hma import hma
from .sma import sma
from .wma import wma
from ..utils import get_offset, verify_series
def zlma(close, length=None, offset=None, mamode=None, **kwargs):
"""Indicator: Zero Lag Moving Average (ZLMA)"""
# 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)
mamode = mamode.lower() if mamode else None
# Calculate Result
lag = int(0.5 * (length - 1))
close = 2 * close - close.shift(lag)
if mamode is None or mamode == 'ema':
zlma = ema(close, length=length, **kwargs)
kind = "E"
if mamode == 'hma':
zlma = hma(close, length=length, **kwargs)
kind = "H"
if mamode == 'sma':
zlma = sma(close, length=length, **kwargs)
kind = "S"
if mamode == 'wma':
zlma = wma(close, length=length, **kwargs)
kind = "W"
# Offset
if offset != 0:
zlma = zlma.shift(offset)
# Name & Category
zlma.name = f"ZL{kind}MA_{length}"
zlma.category = 'overlap'
return zlma
zlma.__doc__ = \
"""Zero Lag Moving Average (ZLMA)
The Zero Lag Moving Average attempts to eliminate the lag associated
with moving averages. This is an adaption created by John Ehler and Ric Way.
Sources:
https://en.wikipedia.org/wiki/Zero_lag_exponential_moving_average
Calculation:
Default Inputs:
length=10, mamode=EMA
EMA = Exponential Moving Average
lag = int(0.5 * (length - 1))
source = 2 * close - close.shift(lag)
ZLMA = EMA(source, length)
Args:
close (pd.Series): Series of 'close's
length (int): It's period. Default: 10
mamode (str): Two options: None or 'ema'. Default: 'ema'
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 ..overlap import sma
from ..overlap.sma import sma
from .stdev import stdev
from ..utils import get_offset, verify_series
+1 -1
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from ..overlap import rma
from ..overlap.rma import rma
from ..volatility.atr import atr
from ..utils import get_drift, get_offset, verify_series, zero
+6 -1
View File
@@ -1,7 +1,12 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from .long_run import long_run
from ..overlap import ema, hma, linreg, rma, sma, wma
from ..overlap.ema import ema
from ..overlap.hma import hma
from ..overlap.linreg import linreg
from ..overlap.rma import rma
from ..overlap.sma import sma
from ..overlap.wma import wma
from .short_run import short_run
from ..utils import get_offset, verify_series
+5 -1
View File
@@ -1,5 +1,9 @@
# -*- coding: utf-8 -*-
from ..overlap import dema, ema, hma, rma, sma
from ..overlap.dema import dema
from ..overlap.ema import ema
from ..overlap.hma import hma
from ..overlap.rma import rma
from ..overlap.sma import sma
from ..utils import get_offset, verify_series
def qstick(open_, close, length=None, offset=None, **kwargs):
+2 -1
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from ..overlap import ema, sma
from ..overlap.ema import ema
from ..overlap.sma import sma
from ..statistics.stdev import stdev
from ..utils import get_offset, verify_series
+1 -1
View File
@@ -2,7 +2,7 @@
from numpy import sqrt as npsqrt
from pandas import DataFrame
from .atr import atr
from ..overlap import hlc3
from ..overlap.hlc3 import hlc3
from ..statistics.variance import variance
from ..utils import get_offset, verify_series
+1 -1
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from ..overlap import ema
from ..overlap.ema import ema
from ..utils import get_offset, verify_series
def massi(high, low, fast=None, slow=None, offset=None, **kwargs):
+1 -1
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
from .ad import ad
from ..overlap import ema
from ..overlap.ema import ema
from ..utils import get_offset, verify_series
def adosc(high, low, close, volume, open_=None, fast=None, slow=None, offset=None, **kwargs):
+7 -2
View File
@@ -1,6 +1,11 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from .obv import obv
from ..overlap import *
from ..overlap.ema import ema
from ..overlap.hma import hma
from ..overlap.linreg import linreg
from ..overlap.sma import sma
from ..overlap.wma import wma
from ..trend.long_run import long_run
from ..trend.short_run import short_run
from ..utils import get_offset, verify_series
@@ -75,7 +80,7 @@ def aobv(close, volume, fast=None, slow=None, mamode=None, max_lookback=None, mi
f"AOBV_LR_{run_length}": obv_long,
f"AOBV_SR_{run_length}": obv_short
}
aobvdf = pd.DataFrame(data)
aobvdf = DataFrame(data)
# Name and Categorize it
aobvdf.name = f"AOBV_{mamode}_{fast}_{slow}_{min_lookback}_{max_lookback}_{run_length}"
+1 -1
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from ..overlap import hl2
from ..overlap.hl2 import hl2
from ..utils import get_drift, get_offset, verify_series
def eom(high, low, close, volume, length=None, divisor=None, drift=None, offset=None, **kwargs):
+1 -1
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
from pandas import DataFrame
from ..overlap import hlc3
from ..overlap.hlc3 import hlc3
from ..utils import get_drift, get_offset, verify_series
def mfi(high, low, close, volume, length=None, drift=None, offset=None, **kwargs):
+28 -31
View File
@@ -32,15 +32,12 @@ class TestOverlap(TestCase):
def setUp(self):
self.overlap = pandas_ta.overlap
def tearDown(self):
del self.overlap
def setUp(self): pass
def tearDown(self): pass
def test_dema(self):
result = self.overlap.dema(self.close)
result = pandas_ta.dema(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'DEMA_10')
@@ -55,7 +52,7 @@ class TestOverlap(TestCase):
error_analysis(result, CORRELATION, ex)
def test_ema(self):
result = self.overlap.ema(self.close, presma=False)
result = pandas_ta.ema(self.close, presma=False)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'EMA_10')
@@ -70,17 +67,17 @@ class TestOverlap(TestCase):
error_analysis(result, CORRELATION, ex)
def test_fwma(self):
result = self.overlap.fwma(self.close)
result = pandas_ta.fwma(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'FWMA_10')
def test_hl2(self):
result = self.overlap.hl2(self.high, self.low)
result = pandas_ta.hl2(self.high, self.low)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'HL2')
def test_hlc3(self):
result = self.overlap.hlc3(self.high, self.low, self.close)
result = pandas_ta.hlc3(self.high, self.low, self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'HLC3')
@@ -95,19 +92,19 @@ class TestOverlap(TestCase):
error_analysis(result, CORRELATION, ex)
def test_hma(self):
result = self.overlap.hma(self.close)
result = pandas_ta.hma(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'HMA_10')
def test_ichimoku(self):
ichimoku, span = self.overlap.ichimoku(self.high, self.low, self.close)
ichimoku, span = pandas_ta.ichimoku(self.high, self.low, self.close)
self.assertIsInstance(ichimoku, DataFrame)
self.assertIsInstance(span, DataFrame)
self.assertEqual(ichimoku.name, 'ICHIMOKU_9_26_52')
self.assertEqual(span.name, 'ICHISPAN_9_26')
def test_linreg(self):
result = self.overlap.linreg(self.close)
result = pandas_ta.linreg(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'LR_14')
@@ -122,7 +119,7 @@ class TestOverlap(TestCase):
error_analysis(result, CORRELATION, ex)
def test_linreg_angle(self):
result = self.overlap.linreg(self.close, angle=True)
result = pandas_ta.linreg(self.close, angle=True)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'LRa_14')
@@ -137,7 +134,7 @@ class TestOverlap(TestCase):
error_analysis(result, CORRELATION, ex)
def test_linreg_intercept(self):
result = self.overlap.linreg(self.close, intercept=True)
result = pandas_ta.linreg(self.close, intercept=True)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'LRb_14')
@@ -152,12 +149,12 @@ class TestOverlap(TestCase):
error_analysis(result, CORRELATION, ex)
def test_linreg_r(self):
result = self.overlap.linreg(self.close, r=True)
result = pandas_ta.linreg(self.close, r=True)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'LRr_14')
def test_linreg_slope(self):
result = self.overlap.linreg(self.close, slope=True)
result = pandas_ta.linreg(self.close, slope=True)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'LRm_14')
@@ -172,7 +169,7 @@ class TestOverlap(TestCase):
error_analysis(result, CORRELATION, ex)
def test_midpoint(self):
result = self.overlap.midpoint(self.close)
result = pandas_ta.midpoint(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'MIDPOINT_2')
@@ -187,7 +184,7 @@ class TestOverlap(TestCase):
error_analysis(result, CORRELATION, ex)
def test_midprice(self):
result = self.overlap.midprice(self.high, self.low)
result = pandas_ta.midprice(self.high, self.low)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'MIDPRICE_2')
@@ -202,22 +199,22 @@ class TestOverlap(TestCase):
error_analysis(result, CORRELATION, ex)
def test_ohlc4(self):
result = self.overlap.ohlc4(self.open, self.high, self.low, self.close)
result = pandas_ta.ohlc4(self.open, self.high, self.low, self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'OHLC4')
def test_pwma(self):
result = self.overlap.pwma(self.close)
result = pandas_ta.pwma(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'PWMA_10')
def test_rma(self):
result = self.overlap.rma(self.close)
result = pandas_ta.rma(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'RMA_10')
def test_sma(self):
result = self.overlap.sma(self.close)
result = pandas_ta.sma(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'SMA_10')
@@ -232,12 +229,12 @@ class TestOverlap(TestCase):
error_analysis(result, CORRELATION, ex)
def test_swma(self):
result = self.overlap.swma(self.close)
result = pandas_ta.swma(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'SWMA_10')
def test_t3(self):
result = self.overlap.t3(self.close)
result = pandas_ta.t3(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'T3_10_0.7')
@@ -252,7 +249,7 @@ class TestOverlap(TestCase):
error_analysis(result, CORRELATION, ex)
def test_tema(self):
result = self.overlap.tema(self.close)
result = pandas_ta.tema(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'TEMA_10')
@@ -267,7 +264,7 @@ class TestOverlap(TestCase):
error_analysis(result, CORRELATION, ex)
def test_trima(self):
result = self.overlap.trima(self.close)
result = pandas_ta.trima(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'TRIMA_10')
@@ -282,17 +279,17 @@ class TestOverlap(TestCase):
error_analysis(result, CORRELATION, ex)
def test_vwap(self):
result = self.overlap.vwap(self.high, self.low, self.close, self.volume)
result = pandas_ta.vwap(self.high, self.low, self.close, self.volume)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'VWAP')
def test_vwma(self):
result = self.overlap.vwma(self.close, self.volume)
result = pandas_ta.vwma(self.close, self.volume)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'VWMA_10')
def test_wma(self):
result = self.overlap.wma(self.close)
result = pandas_ta.wma(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'WMA_10')
@@ -307,6 +304,6 @@ class TestOverlap(TestCase):
error_analysis(result, CORRELATION, ex)
def test_zlma(self):
result = self.overlap.zlma(self.close)
result = pandas_ta.zlma(self.close)
self.assertIsInstance(result, Series)
self.assertEqual(result.name, 'ZLEMA_10')