mirror of
https://github.com/wassname/pandas-ta.git
synced 2026-06-27 16:10:07 +08:00
ENH Gann HiLo Activator added MAINT refactoring
This commit is contained in:
@@ -59,11 +59,15 @@ and _Weighted Moving Average_.
|
||||
* _Squeeze_ (**squeeze**). A Momentum indicator. Both John Carter's TTM **and** Lazybear's TradingView versions are implemented. The default is John Carter's, or ```lazybear=False```. Set ```lazybear=True``` to enable Lazybear's.
|
||||
* _TTM Trend_ (**ttm_trend**). A trend indicator inspired from John Carter's book "Mastering the Trade".
|
||||
* _SMI Ergodic_ (**smi**) Developed by William Blau, the SMI Ergodic Indicator is the same as the True Strength Index (TSI) except the SMI includes a signal line and oscillator.
|
||||
* _Gann High-Low Activator_ (**hilo**) The Gann High Low Activator Indicator was created by Robert Krausz in a 1998
|
||||
issue of Stocks & Commodities Magazine. It is a moving average based trend
|
||||
indicator consisting of two different simple moving averages.
|
||||
|
||||
## __Updated Indicators__
|
||||
* _Fisher Transform_ (**fisher**): Added Fisher's default **ema** signal line. To change the length of the signal line, use the argument: ```signal=5```. Default: 5
|
||||
* _Fisher Transform_ (**fisher**) and _Kaufman's Adaptive Moving Average_ (**kama**): Fixed a bug where their columns were not added to final DataFrame when using the _strategy_ method.
|
||||
* _Trend Return_ (**trend_return**): Returns a DataFrame now instead of Series.
|
||||
* _Trend Return_ (**trend_return**): Returns a DataFrame now instead of Series.
|
||||
* _Average True Range_ (**atr**): Added option to return **atr** as a percentage. See: ```help(ta.atr)```
|
||||
|
||||
|
||||
## What is a Pandas DataFrame Extension?
|
||||
@@ -358,11 +362,12 @@ print(bothhl2.name) # "pre_HL2_post"
|
||||
|:--------:|
|
||||
|  |
|
||||
|
||||
## _Overlap_ (26)
|
||||
## _Overlap_ (27)
|
||||
|
||||
* _Double Exponential Moving Average_: **dema**
|
||||
* _Exponential Moving Average_: **ema**
|
||||
* _Fibonacci's Weighted Moving Average_: **fwma**
|
||||
* _Gann High-Low Activator_: **hilo**
|
||||
* _High-Low Average_: **hl2**
|
||||
* _High-Low-Close Average_: **hlc3**
|
||||
* Commonly known as 'Typical Price' in Technical Analysis literature
|
||||
|
||||
+24
-24
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
+112
-125
File diff suppressed because one or more lines are too long
@@ -28,7 +28,7 @@ Category = {
|
||||
"momentum": ["ao", "apo", "bias", "bop", "brar", "cci", "cg", "cmo", "coppock", "er", "eri", "fisher", "inertia", "kdj", "kst", "macd", "mom", "pgo", "ppo", "psl", "pvo", "roc", "rsi", "rvgi", "slope", "smi", "squeeze", "stoch", "trix", "tsi", "uo", "willr"],
|
||||
|
||||
# Overlap
|
||||
"overlap": ["dema", "ema", "fwma", "hl2", "hlc3", "hma", "ichimoku", "kama", "linreg", "midpoint", "midprice", "ohlc4", "pwma", "rma", "sinwma", "sma", "supertrend", "swma", "t3", "tema", "trima", "vwap", "vwma", "wcp", "wma", "zlma"],
|
||||
"overlap": ["dema", "ema", "fwma", "hilo", "hl2", "hlc3", "hma", "ichimoku", "kama", "linreg", "midpoint", "midprice", "ohlc4", "pwma", "rma", "sinwma", "sma", "supertrend", "swma", "t3", "tema", "trima", "vwap", "vwma", "wcp", "wma", "zlma"],
|
||||
|
||||
# Performance
|
||||
"performance": ["log_return", "percent_return", "trend_return"],
|
||||
|
||||
+10
-1
@@ -23,7 +23,7 @@ from pandas_ta.volatility import *
|
||||
from pandas_ta.volume import *
|
||||
from pandas_ta.utils import *
|
||||
|
||||
version = ".".join(("0", "1", "98b"))
|
||||
version = ".".join(("0", "1", "99b"))
|
||||
|
||||
|
||||
def mp_worker(args):
|
||||
@@ -900,6 +900,15 @@ class AnalysisIndicators(BasePandasObject):
|
||||
result = fwma(close=close, length=length, offset=offset, **kwargs)
|
||||
return result
|
||||
|
||||
@finalize
|
||||
def hilo(self, high=None, low=None, close=None, high_length=None, low_length=None, offset=None, **kwargs):
|
||||
high = self._get_column(high, "high")
|
||||
low = self._get_column(low, "low")
|
||||
close = self._get_column(close, "close")
|
||||
|
||||
result = hilo(high=high, low=low, close=close, high_length=high_length, low_length=low_length, offset=offset, **kwargs)
|
||||
return result
|
||||
|
||||
@finalize
|
||||
def hl2(self, high=None, low=None, offset=None, **kwargs):
|
||||
high = self._get_column(high, "high")
|
||||
|
||||
@@ -33,14 +33,14 @@ def cmo(close, length=None, scalar=None, drift=None, offset=None, **kwargs):
|
||||
cmo = cmo.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
cmo.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
cmo.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
cmo.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
cmo.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
cmo.name = f"CMO_{length}"
|
||||
cmo.category = 'momentum'
|
||||
cmo.category = "momentum"
|
||||
|
||||
return cmo
|
||||
|
||||
@@ -65,11 +65,11 @@ Calculation:
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
scalar (float): How much to magnify. Default: 100
|
||||
talib (bool): If True, uses TA-Libs implementation. Otherwise uses EMA version. Default: True
|
||||
drift (int): The short period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
talib (bool): If True, uses TA-Libs implementation. Otherwise uses EMA version. Default: True
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
fill_method (value, optional): Type of fill method
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
from .dema import dema
|
||||
from .ema import ema
|
||||
from .fwma import fwma
|
||||
from .hilo import hilo
|
||||
from .hl2 import hl2
|
||||
from .hlc3 import hlc3
|
||||
from .hma import hma
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from numpy import NaN as npNaN
|
||||
from pandas import DataFrame, Series
|
||||
from .ema import ema
|
||||
from .hma import hma
|
||||
from .sma import sma
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
def hilo(high, low, close, high_length=None, low_length=None, mamode=None, offset=None, **kwargs):
|
||||
"""Indicator: Gann HiLo (HiLo)"""
|
||||
# Validate Arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
high_length = int(high_length) if high_length and high_length > 0 else 13
|
||||
low_length = int(low_length) if low_length and low_length > 0 else 21
|
||||
mamode = mamode.lower() if mamode else "sma"
|
||||
offset = get_offset(offset)
|
||||
|
||||
# Calculate Result
|
||||
m = close.size
|
||||
hilo = Series(npNaN, index=close.index)
|
||||
long = Series(npNaN, index=close.index)
|
||||
short = Series(npNaN, index=close.index)
|
||||
|
||||
if mamode == "ema":
|
||||
high_ma = ema(high, high_length)
|
||||
low_ma = ema(low, low_length)
|
||||
if mamode == "hma":
|
||||
high_ma = hma(high, high_length)
|
||||
low_ma = hma(low, low_length)
|
||||
else: # "sma"
|
||||
high_ma = sma(high, high_length)
|
||||
low_ma = sma(low, low_length)
|
||||
|
||||
for i in range(1, m):
|
||||
if close.iloc[i] > high_ma.iloc[i - 1]:
|
||||
hilo.iloc[i] = long.iloc[i] = low_ma.iloc[i]
|
||||
elif close.iloc[i] < low_ma.iloc[i - 1]:
|
||||
|
||||
hilo.iloc[i] = short.iloc[i] = high_ma.iloc[i]
|
||||
else:
|
||||
hilo.iloc[i] = hilo.iloc[i - 1]
|
||||
long.iloc[i] = short.iloc[i] = hilo.iloc[i - 1]
|
||||
|
||||
# Offset
|
||||
if offset != 0:
|
||||
hilo = hilo.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if "fillna" in kwargs:
|
||||
hilo.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
hilo.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name & Category
|
||||
_props = f"_{high_length}_{low_length}"
|
||||
df = DataFrame({
|
||||
f"HILO{_props}": hilo,
|
||||
f"HILOl{_props}": long,
|
||||
f"HILOs{_props}": short
|
||||
}, index=close.index)
|
||||
|
||||
df.name = f"HILO{_props}"
|
||||
df.category = "overlap"
|
||||
|
||||
return df
|
||||
|
||||
|
||||
|
||||
hilo.__doc__ = \
|
||||
"""Gann HiLo Activator(HiLo)
|
||||
|
||||
The Gann High Low Activator Indicator was created by Robert Krausz in a 1998
|
||||
issue of Stocks & Commodities Magazine. It is a moving average based trend
|
||||
indicator consisting of two different simple moving averages.
|
||||
|
||||
The indicator tracks both curves (of the highs and the lows). The close of the
|
||||
bar defines which of the two gets plotted.
|
||||
|
||||
Increasing high_length and decreasing low_length better for short trades,
|
||||
vice versa for long positions.
|
||||
|
||||
Sources:
|
||||
https://www.sierrachart.com/index.php?page=doc/StudiesReference.php&ID=447&Name=Gann_HiLo_Activator
|
||||
https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/simple-moving-average-sma/
|
||||
https://www.tradingview.com/script/XNQSLIYb-Gann-High-Low/
|
||||
|
||||
Calculation:
|
||||
Default Inputs:
|
||||
high_length=13, low_length=21, mamode="sma"
|
||||
EMA = Exponential Moving Average
|
||||
HMA = Hull Moving Average
|
||||
SMA = Simple Moving Average # Default
|
||||
|
||||
if "ema":
|
||||
high_ma = EMA(high, high_length)
|
||||
low_ma = EMA(low, low_length)
|
||||
elif "hma":
|
||||
high_ma = HMA(high, high_length)
|
||||
low_ma = HMA(low, low_length)
|
||||
else: # "sma"
|
||||
high_ma = SMA(high, high_length)
|
||||
low_ma = SMA(low, low_length)
|
||||
|
||||
# Similar to Supertrend MA selection
|
||||
hilo = Series(npNaN, index=close.index)
|
||||
for i in range(1, m):
|
||||
if close.iloc[i] > high_ma.iloc[i - 1]:
|
||||
hilo.iloc[i] = low_ma.iloc[i]
|
||||
elif close.iloc[i] < low_ma.iloc[i - 1]:
|
||||
hilo.iloc[i] = high_ma.iloc[i]
|
||||
else:
|
||||
hilo.iloc[i] = hilo.iloc[i - 1]
|
||||
|
||||
Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
high_length (int): It's period. Default: 13
|
||||
low_length (int): It's period. Default: 21
|
||||
mamode (str): Options: 'sma' or 'ema'. Default: 'sma'
|
||||
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.DataFrame: HILO (line), HILOl (long), HILOs (short) columns.
|
||||
"""
|
||||
@@ -18,7 +18,7 @@ def rma(close, length=None, offset=None, **kwargs):
|
||||
|
||||
# Name & Category
|
||||
rma.name = f"RMA_{length}"
|
||||
rma.category = 'overlap'
|
||||
rma.category = "overlap"
|
||||
|
||||
return rma
|
||||
|
||||
|
||||
@@ -60,11 +60,11 @@ def supertrend(high, low, close, length=None, multiplier=None, offset=None, **kw
|
||||
df = df.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
df.fillna(kwargs['fillna'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
df.fillna(kwargs["fillna"], inplace=True)
|
||||
|
||||
if 'fill_method' in kwargs:
|
||||
df.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
df.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
return df
|
||||
|
||||
|
||||
+4
-2
@@ -227,8 +227,7 @@ def signals(indicator, xa, xb, cross_values, xserie, xserie_a, xserie_b, cross_s
|
||||
|
||||
|
||||
def df_error_analysis(dfA: pd.DataFrame, dfB: pd.DataFrame, **kwargs) -> pd.DataFrame:
|
||||
""" """
|
||||
col = kwargs.pop("col", None)
|
||||
"""DataFrame Correlation Analysis helper"""
|
||||
corr_method = kwargs.pop("corr_method", "pearson")
|
||||
|
||||
# Find their differences and correlation
|
||||
@@ -241,6 +240,9 @@ def df_error_analysis(dfA: pd.DataFrame, dfB: pd.DataFrame, **kwargs) -> pd.Data
|
||||
if diff[diff > 0].any():
|
||||
diff.plot(kind="kde")
|
||||
|
||||
if kwargs.pop("triangular", False):
|
||||
return corr.where(np.triu(np.ones(corr.shape)).astype(np.bool))
|
||||
|
||||
return corr
|
||||
|
||||
def fibonacci(**kwargs) -> np.ndarray:
|
||||
|
||||
@@ -32,16 +32,16 @@ def aberration(high, low, close, length=None, atr_length=None, offset=None, **kw
|
||||
atr_ = atr_.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
zg.fillna(kwargs['fillna'], inplace=True)
|
||||
sg.fillna(kwargs['fillna'], inplace=True)
|
||||
xg.fillna(kwargs['fillna'], inplace=True)
|
||||
atr_.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
zg.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
sg.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
xg.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
atr_.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
zg.fillna(kwargs["fillna"], inplace=True)
|
||||
sg.fillna(kwargs["fillna"], inplace=True)
|
||||
xg.fillna(kwargs["fillna"], inplace=True)
|
||||
atr_.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
zg.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
sg.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
xg.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
atr_.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
_props = f"_{length}_{atr_length}"
|
||||
@@ -49,7 +49,7 @@ def aberration(high, low, close, length=None, atr_length=None, offset=None, **kw
|
||||
sg.name = f"ABER_SG{_props}"
|
||||
xg.name = f"ABER_XG{_props}"
|
||||
atr_.name = f"ABER_ATR{_props}"
|
||||
zg.category = sg.category = 'volatility'
|
||||
zg.category = sg.category = "volatility"
|
||||
xg.category = atr_.category = zg.category
|
||||
|
||||
# Prepare DataFrame to return
|
||||
@@ -61,7 +61,7 @@ def aberration(high, low, close, length=None, atr_length=None, offset=None, **kw
|
||||
}
|
||||
aberdf = DataFrame(data)
|
||||
aberdf.name = f"ABER{_props}"
|
||||
aberdf.category = 'volatility'
|
||||
aberdf.category = zg.category
|
||||
|
||||
return aberdf
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pandas import DataFrame
|
||||
from ..utils import get_drift, get_offset, non_zero_range, verify_series
|
||||
from pandas_ta.overlap import ema, sma
|
||||
from pandas_ta.utils import get_drift, get_offset, non_zero_range, verify_series
|
||||
|
||||
def accbands(high, low, close, length=None, c=None, drift=None, mamode=None, offset=None, **kwargs):
|
||||
"""Indicator: Acceleration Bands (ACCBANDS)"""
|
||||
@@ -12,7 +13,7 @@ def accbands(high, low, close, length=None, c=None, drift=None, mamode=None, off
|
||||
length = int(length) if length and length > 0 else 20
|
||||
c = float(c) if c and c > 0 else 4
|
||||
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
|
||||
mamode = mamode.lower() if mamode else 'sma'
|
||||
mamode = mamode.lower() if mamode else "sma"
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
@@ -22,14 +23,17 @@ def accbands(high, low, close, length=None, c=None, drift=None, mamode=None, off
|
||||
_lower = low * (1 - hl_ratio)
|
||||
_upper = high * (1 + hl_ratio)
|
||||
|
||||
if mamode is None or mamode == 'sma':
|
||||
lower = _lower.rolling(length, min_periods=min_periods).mean()
|
||||
mid = close.rolling(length, min_periods=min_periods).mean()
|
||||
upper = _upper.rolling(length, min_periods=min_periods).mean()
|
||||
elif mamode == 'ema':
|
||||
lower = _lower.ewm(span=length, min_periods=min_periods).mean()
|
||||
mid = close.ewm(span=length, min_periods=min_periods).mean()
|
||||
upper = _upper.ewm(span=length, min_periods=min_periods).mean()
|
||||
if mamode == "ema":
|
||||
# lower = _lower.ewm(span=length, min_periods=min_periods).mean()
|
||||
# mid = close.ewm(span=length, min_periods=min_periods).mean()
|
||||
# upper = _upper.ewm(span=length, min_periods=min_periods).mean()
|
||||
lower = ema(_lower, length=length)
|
||||
mid = ema(close, length=length)
|
||||
upper = ema(_upper, length=length)
|
||||
else: # "sma"
|
||||
lower = sma(_lower, length=length)
|
||||
mid = sma(close, length=length)
|
||||
upper = sma(_upper, length=length)
|
||||
|
||||
# Offset
|
||||
if offset != 0:
|
||||
@@ -38,26 +42,26 @@ def accbands(high, low, close, length=None, c=None, drift=None, mamode=None, off
|
||||
upper = upper.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
lower.fillna(kwargs['fillna'], inplace=True)
|
||||
mid.fillna(kwargs['fillna'], inplace=True)
|
||||
upper.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
lower.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
mid.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
upper.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
lower.fillna(kwargs["fillna"], inplace=True)
|
||||
mid.fillna(kwargs["fillna"], inplace=True)
|
||||
upper.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
lower.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
mid.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
upper.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
lower.name = f"ACCBL_{length}"
|
||||
mid.name = f"ACCBM_{length}"
|
||||
upper.name = f"ACCBU_{length}"
|
||||
mid.category = upper.category = lower.category = 'volatility'
|
||||
mid.category = upper.category = lower.category = "volatility"
|
||||
|
||||
# Prepare DataFrame to return
|
||||
data = {lower.name: lower, mid.name: mid, upper.name: upper}
|
||||
accbandsdf = DataFrame(data)
|
||||
accbandsdf.name = f"ACCBANDS_{length}"
|
||||
accbandsdf.category = 'volatility'
|
||||
accbandsdf.category = mid.category
|
||||
|
||||
return accbandsdf
|
||||
|
||||
|
||||
+28
-21
@@ -1,8 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# from ..overlap.ema import ema
|
||||
from ..overlap.rma import rma
|
||||
from pandas_ta.overlap import ema, rma
|
||||
from .true_range import true_range
|
||||
from ..utils import get_drift, get_offset, verify_series
|
||||
from pandas_ta.utils import get_drift, get_offset, verify_series
|
||||
|
||||
def atr(high, low, close, length=None, mamode=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: Average True Range (ATR)"""
|
||||
@@ -11,32 +10,37 @@ def atr(high, low, close, length=None, mamode=None, drift=None, offset=None, **k
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 14
|
||||
min_periods = int(kwargs['min_periods']) if 'min_periods' in kwargs and kwargs['min_periods'] is not None else length
|
||||
mamode = mamode.lower() if mamode else 'ema'
|
||||
mamode = mamode.lower() if mamode else "ema"
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
# Calculate Result
|
||||
tr = true_range(high=high, low=low, close=close, drift=drift)
|
||||
if mamode == 'ema':
|
||||
alpha = (1.0 / length) if length > 0 else 0.5
|
||||
atr = tr.ewm(alpha=alpha, min_periods=min_periods).mean()
|
||||
if mamode == "ema":
|
||||
# alpha = (1.0 / length) if length > 0 else 0.5
|
||||
# atr = tr.ewm(alpha=alpha).mean()
|
||||
atr = rma(tr, length=length)
|
||||
else:
|
||||
atr = tr.rolling(length, min_periods=min_periods).mean()
|
||||
# atr = tr.rolling(length).mean()
|
||||
atr = sma(tr, length=length)
|
||||
|
||||
percentage = kwargs.pop("percent", False)
|
||||
if percentage:
|
||||
atr *= 100 / close
|
||||
|
||||
# Offset
|
||||
if offset != 0:
|
||||
atr = atr.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
atr.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
atr.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
atr.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
atr.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
atr.name = f"ATR_{length}"
|
||||
atr.category = 'volatility'
|
||||
atr.name = f"ATR{'p' if percentage else ''}_{length}"
|
||||
atr.category = "volatility"
|
||||
|
||||
return atr
|
||||
|
||||
@@ -53,7 +57,7 @@ Sources:
|
||||
|
||||
Calculation:
|
||||
Default Inputs:
|
||||
length=14, drift=1
|
||||
length=14, drift=1, percent=False
|
||||
SMA = Simple Moving Average
|
||||
EMA = Exponential Moving Average
|
||||
TR = True Range
|
||||
@@ -63,19 +67,22 @@ Calculation:
|
||||
else:
|
||||
ATR = SMA(tr, length)
|
||||
|
||||
if percent:
|
||||
ATR *= 100 / close
|
||||
|
||||
Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 14
|
||||
mamode (str): Two options: None or 'ema'. Default: 'ema'
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 14
|
||||
mamode (str): Two options: None or 'ema'. Default: 'ema'
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
percent (bool, optional): Return as percentage. Default: False
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
fill_method (value, optional): Type of fill method
|
||||
min_periods (int, optional) : Minimum number of periods before calculating ATR. Default : length
|
||||
|
||||
Returns:
|
||||
pd.Series: New feature generated.
|
||||
|
||||
+18
-16
@@ -14,13 +14,12 @@ def kc(high, low, close, length=None, scalar=None, mamode=None, offset=None, **k
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 20
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
scalar = float(scalar) if scalar and scalar > 0 else 2
|
||||
use_tr = kwargs.pop("tr", True)
|
||||
mamode = mamode.lower() if mamode else None
|
||||
offset = get_offset(offset)
|
||||
|
||||
# Calculate Result
|
||||
use_tr = kwargs.pop("tr", True)
|
||||
if use_tr:
|
||||
range_ = true_range(high, low, close)
|
||||
else:
|
||||
@@ -82,21 +81,22 @@ Sources:
|
||||
|
||||
Calculation:
|
||||
Default Inputs:
|
||||
length=20, scalar=2, mamode=None
|
||||
ATR = Average True Range
|
||||
EMA = Exponential Moving Average
|
||||
length=20, scalar=2, mamode=None, tr=True
|
||||
TR = True Range
|
||||
SMA = Simple Moving Average
|
||||
EMA = Exponential Moving Average
|
||||
|
||||
if tr:
|
||||
RANGE = TR(high, low, close)
|
||||
else:
|
||||
RANGE = high - low
|
||||
|
||||
BAND = ATR(high, low, close)
|
||||
if mamode == "ema":
|
||||
BASIS = EMA(close, length)
|
||||
BASIS = sma(close, length)
|
||||
BAND = sma(RANGE, length)
|
||||
elif mamode == "sma":
|
||||
BASIS = SMA(close, length)
|
||||
else: # Typical Price
|
||||
hl_range = high - low
|
||||
tp = typical_price = hlc3(high, low, close)
|
||||
BASIS = SMA(tp, length)
|
||||
BAND = SMA(hl_range, length)
|
||||
BASIS = sma(close, length)
|
||||
BAND = sma(RANGE, length)
|
||||
|
||||
LOWER = BASIS - scalar * BAND
|
||||
UPPER = BASIS + scalar * BAND
|
||||
@@ -106,11 +106,13 @@ Args:
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): The short period. Default: 20
|
||||
scalar (float): A positive float to scale the bands. Default: 2
|
||||
mamode (str): Two options: None or "ema". Default: "ema"
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
scalar (float): A positive float to scale the bands. Default: 2
|
||||
mamode (str): Two options: "sma" or "ema". Default: "ema"
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
tr (bool): When True, it uses True Range for calculation. When False, use a
|
||||
high - low as it's range calculation. Default: True
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
fill_method (value, optional): Type of fill method
|
||||
|
||||
|
||||
@@ -30,10 +30,10 @@ def rvi(close, high=None, low=None, length=None, scalar=None, refined=None, thir
|
||||
pos_std = pos * std
|
||||
neg_std = neg * std
|
||||
|
||||
if mamode == 'sma':
|
||||
if mamode == "sma":
|
||||
pos_avg = sma(pos_std, length)
|
||||
neg_avg = sma(neg_std, length)
|
||||
else: # 'ema'
|
||||
else: # "ema"
|
||||
pos_avg = ema(pos_std, length)
|
||||
neg_avg = ema(neg_std, length)
|
||||
|
||||
@@ -61,10 +61,10 @@ def rvi(close, high=None, low=None, length=None, scalar=None, refined=None, thir
|
||||
rvi = rvi.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
rvi.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
rvi.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
rvi.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
rvi.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
rvi.name = f"RVI{_mode}_{length}"
|
||||
@@ -103,9 +103,9 @@ Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): The short period. Default: 14
|
||||
length (int): The short period. Default: 14
|
||||
scalar (float): A positive float to scale the bands. Default: 100
|
||||
mamode (str): Two options: None or 'ema'. Default: 'ema'
|
||||
mamode (str): Options: 'sma' or 'ema'. Default: 'sma'
|
||||
refined (bool): Use 'refined' calculation which is the average of
|
||||
RVI(high) and RVI(low) instead of RVI(close). Default: False
|
||||
thirds (bool): Average of high, low and close. Default: False
|
||||
|
||||
@@ -30,10 +30,10 @@ def ui(close, length=None, scalar=None, offset=None, **kwargs):
|
||||
ui = ui.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if 'fillna' in kwargs:
|
||||
ui.fillna(kwargs['fillna'], inplace=True)
|
||||
if 'fill_method' in kwargs:
|
||||
ui.fillna(method=kwargs['fill_method'], inplace=True)
|
||||
if "fillna" in kwargs:
|
||||
ui.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
ui.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
ui.name = f"UI{'' if not everget else 'e'}_{length}"
|
||||
|
||||
@@ -71,6 +71,11 @@ class TestOverlap(TestCase):
|
||||
self.assertIsInstance(result, Series)
|
||||
self.assertEqual(result.name, "FWMA_10")
|
||||
|
||||
def test_hilo(self):
|
||||
result = pandas_ta.hilo(self.high, self.low, self.close)
|
||||
self.assertIsInstance(result, DataFrame)
|
||||
self.assertEqual(result.name, "HILO_13_21")
|
||||
|
||||
def test_hl2(self):
|
||||
result = pandas_ta.hl2(self.high, self.low)
|
||||
self.assertIsInstance(result, Series)
|
||||
|
||||
@@ -38,6 +38,11 @@ class TestOverlapExtension(TestCase):
|
||||
self.assertIsInstance(self.data, DataFrame)
|
||||
self.assertEqual(self.data.columns[-1], "FWMA_10")
|
||||
|
||||
def test_hilo_ext(self):
|
||||
self.data.ta.hilo(append=True)
|
||||
self.assertIsInstance(self.data, DataFrame)
|
||||
self.assertEqual(list(self.data.columns[-3:]), ["HILO_13_21", "HILOl_13_21", "HILOs_13_21"])
|
||||
|
||||
def test_hl2_ext(self):
|
||||
self.data.ta.hl2(append=True)
|
||||
self.assertIsInstance(self.data, DataFrame)
|
||||
|
||||
Reference in New Issue
Block a user