mirror of
https://github.com/wassname/pandas-ta.git
synced 2026-09-11 12:30:30 +08:00
Merge pull request #18 from twopirllc/overlap-refactor
overlap refactoring
This commit is contained in:
@@ -134,6 +134,7 @@ pandas_pips
|
||||
reqs.txt
|
||||
requirements.txt
|
||||
qd.py
|
||||
_overlap.py
|
||||
_trend.py
|
||||
_statistics.py
|
||||
simple.ipynb
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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
|
||||
"""
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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.
|
||||
"""
|
||||
@@ -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,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,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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,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,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):
|
||||
|
||||
@@ -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,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,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):
|
||||
|
||||
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user